来自Lua的MySql未定义符号在运行时出现问题

时间:2014-01-11 19:42:32

标签: mysql nginx lua sinatra

我有一个lua Web服务,它需要使用MySql。如果我尝试从lua控制台访问MySql,我会获得成功,就像你可以看到的那样:

$lua
Lua 5.1.4  Copyright (C) 1994-2008 Lua.org, PUC-Rio
> local luasql = require('luasql.mysql')
> local json = require('json')
> mysql = assert(luasql.mysql())
> ret = {}
> db_name = "luaTest"
> db_host = "localhost"
> db_user = "root"
> db_pass = ""
> con = assert(mysql:connect(db_name, db_user, db_pass, db_host))
> cur = assert(con:execute("SELECT version()"))
> ret["driver_version"] = luasql._MYSQLVERSION
> ret["copyright"] = luasql._COPYRIGHT
> ret["description"] = luasql._DESCRIPTION
> ret["version"] = luasql._VERSION
> con:close()
> mysql:close()
> print(json.encode(ret))
{"copyright":"Copyright (C) 2003-2008 Kepler Project","version":"LuaSQL 2.1.2","driver_version":"5.5.29-MariaDB","description":"LuaSQL is a simple interface from Lua to a DBMS"}

我的代码是我的服务器(文件:/etc/nginx/www/ademar/app.lua):

local sinatra = require('sinatra')
local json = require('json')
local luasql = require('luasql.mysql')

local app = sinatra.app:new()

app:post("/signin", function()
    ret = {}
    mysql = assert(luasql.mysql())

    db_name = "luaTest"
    db_host = "localhost"
    db_user = "root"
    db_pass = ""

    con = assert(mysql:connect(db_name, db_user, db_pass, db_host))
    cur = assert(con:execute("SELECT version()"))

    ret["driver_version"] = luasql._MYSQLVERSION
    ret["copyright"] = luasql._COPYRIGHT
    ret["description"] = luasql._DESCRIPTION
    ret["version"] = luasql._VERSION

    con:close()
    mysql:close()

    return json.encode(ret)
end)

app:run()

如果我尝试用$curl -X POST http://127.0.0.1/signin运行它我得到一个html错误,在服务器日志上我得到它:

2014/01/11 17:32:20 [error] 5104#0: *2 lua entry thread aborted: runtime error: error loading module 'luasql.mysql' from file '/usr/lib/lua/5.1/luasql/mysql.so':
    /usr/lib/lua/5.1/luasql/mysql.so: undefined symbol: luaL_openlib
stack traceback:
coroutine 0:
    [C]: ?
    [C]: in function 'require'
    /etc/nginx/www/ademar/app.lua:3: in function </etc/nginx/www/ademar/app.lua:1>, client: 127.0.0.1, server: adem.ar, request: "POST /signin HTTP/1.1", host: "127.0.0.1"

我的Nginx conf:

$cat nginx.conf 
user nginx www-data;
worker_processes 1;
pid /var/run/nginx.pid;

events {
  worker_connections 768;
}

http {
  sendfile            on;
  tcp_nopush          on;
  tcp_nodelay         on;
  keepalive_timeout   65;
  types_hash_max_size 2048;

  include      /etc/nginx/mime.types;
  default_type application/octet-stream;

  access_log /var/log/nginx/access.log;
  error_log  /var/log/nginx/error.log;

  gzip         on;
  gzip_disable "msie6";

  include /etc/nginx/conf.d/*.conf;
  include /etc/nginx/sites-enabled/*;
}

$cat sites-enabled/xicoh.conf 
lua_package_path './?.lua;/usr/share/lua/5.1/?.lua;/usr/share/lua/5.1/?/init.lua;/usr/lib/lua/5.1/?.lua;/usr/lib/lua/5.1/?/init.lua;;';
lua_package_cpath './?.so;/usr/lib/lua/5.1/?.so;/usr/lib/lua/5.1/loadall.so;;';

server {
  listen      80;
  server_name adem.ar;
  charset     utf-8;
  root        /etc/nginx/www/ademar;

  location / {
    default_type 'text/plain';
    content_by_lua_file "/etc/nginx/www/ademar/app.lua";
  }

  error_page 500 502 503 504 /50x.html;
  location = /50x.html { root html; }
}

编辑

lua console中的一些变量:

package.path = ./?.lua;/usr/share/lua/5.1/?.lua;/usr/share/lua/5.1/?/init.lua;/usr/lib/lua/5.1/‌​?.lua;/usr/lib/lua/5.1/?/init.lua
package.cpath = ./?.so;/usr/lib/lua/5.1/?.so;/usr/lib/lua/5.1/loadall.so.
LD_LIBRARY_PATH = nil

和nginx脚本:

package.path = ./?.lua;/usr/share/lua/5.1/?.lua;/usr/share/lua/5.1/?/init.lua;/usr/lib/lua/5.1/‌​?.lua;/usr/lib/lua/5.1/?/init.lua;/usr/local/openresty/nginx/lualib/?.lua;/usr/lo‌​cal/openresty/nginx/lualib/?/init.lua;./?.lua;/usr/local/share/lua/5.1/?.lua;/usr‌​/local/share/lua/5.1/?/init.lua;/usr/local/lib/lua/5.1/?.lua;/usr/local/lib/lua/5‌​.1/?/init.lua;
package.cpath = ./?.so;/usr/lib/lua/5.1/?.so;/usr/lib/lua/5.1/loadall.so;/usr/local/openresty/ng‌​inx/lualib/?.so;./?.so;/usr/local/lib/lua/5.1/?.so;/usr/local/lib/lua/5.1/loadall‌​.so;
LD_LIBRARY_PATH = nil

1 个答案:

答案 0 :(得分:0)

luaL_openlib是一个在Lua 5.0中但不在5.1中的函数。在5.1中,它被luaL_register取代。所以您安装的luasql很可能是Lua 5.0,而您(根据您的包路径)假设您的系统上安装了Lua 5.1。

如果您根本没有安装5.0(也不是nginx下的某个地方),可能是路径差异?如果mysql.so链接到另一个.so或需要一个Lua模块(谁知道mysql做了什么,它可能会调用Lua的要求),但是在两个环境中看到的路径不同,它可能会找到错误的lib:lib可能正在使用5.0 luaL_openlib。或者,不同的环境(例如用户权限)使得mysql的行为不同,例如查找不同的lib。从脚本中打印package.pathpackage.cpath以及os.getenv("LD_LIBRARY_PATH")

好的,所以我在github上检查了luasql / mysql模块的源代码。版本2.2.x(6年前发布)和更早版本使用旧的luaL_openlib(必须用于Lua 5.0),尽管提交日志表明存在5.1的兼容性文件。可能你的mysql.so版本是为5.0构建的。版本2.3使用仅在Lua 5.2中的luaL_setfuncs,因此可能还需要使用一个构建设置来告诉编译器使用5.1头文件并链接到5.1。