2014-01-11 16 views
0

我有一個lua web服務,它需要使用MySql。如果我嘗試從Lua控制檯訪問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控制檯一些變量:

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 
+0

LD_LIBRARY_PATH應該存在。你用什麼命令來獲取它,是不是os.getenv(「LD_LIBRARY_PATH」)? – Schollii

+0

@Schollii正是這個命令,從控制檯複製: > = os.getenv(「LD_LIBRARY_PATH」) 無 – ademar111190

+0

您使用Lua還是Luajit? – Schollii

回答

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的require),但是在兩種環境中看到的路徑是不同的,它可能會發現錯誤的lib:該lib可能使用5.0 luaL_openlib。或者,環境不同(例如用戶權限)會使mysql的行爲不同,例如尋找不同的lib。從腳本中打印package.pathpackage.cpathos.getenv("LD_LIBRARY_PATH")

好吧,我檢查了github上的luasql/mysql模塊的源代碼。版本2.2.x(6年前發佈)和更早的版本使用舊的luaL_openlib(必須是Lua 5.0版本),儘管提交日誌表明5.1版本兼容文件。可能你的mysql.so版本是爲5.0構建的。版本2.3使用luaL_setfuncs,它僅在Lua 5.2中使用,因此可能需要使用一個生成設置來告訴編譯器使用5.1頭文件並鏈接到5.1。

+0

但爲什麼它在lua控制檯上工作? – ademar111190

+0

感謝您提供的信息,我用新聞編輯了問題並刪除了評論:) – ademar111190

相關問題