0

I have a lua web service, and it needs use MySql. If I try access the MySql from lua console I get success, like you can see:

$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"}

I have that code my server (file: /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()

if I try run it with $curl -X POST http://127.0.0.1/signin i get a html error, and on server log i get it:

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"

My 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/*;
}

and:

$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; }
}

edited

Some variables from 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

and from nginx script:

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
Community
  • 1
  • 1
ademar111190
  • 14,215
  • 14
  • 85
  • 114
  • LD_LIBRARY_PATH should be present. What command did you use to get it, is it os.getenv("LD_LIBRARY_PATH")? – Oliver Jan 14 '14 at 16:11
  • @Schollii exactly this command, the copy from console: > =os.getenv("LD_LIBRARY_PATH") nil – ademar111190 Jan 14 '14 at 16:27
  • You using Lua or Luajit? – Oliver Jan 14 '14 at 16:51
  • @Schollii good question because I have the two installed. On my command line tests I'm using lua and not luajit, and on nginx, following this thread because really I don't know http://stackoverflow.com/questions/19056429/how-to-check-if-nginx-uses-luajit-and-not-lua I'm using lua too, and not luajit. – ademar111190 Jan 14 '14 at 17:24

1 Answers1

0

The luaL_openlib is a function that was in Lua 5.0 but not in 5.1. In 5.1 it was replaced by luaL_register. So likely the luasql you installed is for Lua 5.0, whereas you have (I presume, based on your package path) Lua 5.1 installed on your system.

If you don't have 5.0 installed at all (not somewhere under nginx as well), maybe a path difference? if mysql.so links to another .so or requires a Lua module (who knows what mysql does, it may call Lua's require), but the path seen in both environments is different, it may find wrong lib: that lib may be using 5.0 luaL_openlib. Or, the environment being different (such as user permissions) makes mysql behave differently, such as looking for a different lib. Print the package.path and package.cpath and os.getenv("LD_LIBRARY_PATH") from the script.

OK so I checked the source for luasql/mysql module on github. Version 2.2.x (released 6 years ago) and older use the old luaL_openlib (must have been for Lua 5.0), although the commit log indicates there was a compatibility file for 5.1. Probably your version of mysql.so was built for 5.0. Version 2.3 uses luaL_setfuncs which is only in Lua 5.2, so there is again probably a build setting you have to use to tell the compiler to use 5.1 headers and link to 5.1.

Oliver
  • 27,510
  • 9
  • 72
  • 103