Openresty Lua脚本只能运行一次

时间:2017-08-22 06:05:05

标签: nginx lua openresty

以下代码按预期工作,但只有一次。

require("loadCheckfile")  
require("checkValPairs")
local checklist = loadCheckfile("/home/myname/code/workbench/src/check.lst")

local keyList = {}
local valList = {}

-- Load GET arguments into tables
local args = ngx.req.get_uri_args()
for key, val in pairs(args) do
    table.insert(keyList, key)
    table.insert(valList, val)
end

-- show values in table (just for testing)
ngx.say(unpack(keyList))
ngx.say(unpack(valList))


local key1

-- search for keywords and look them up in the checklist
for i = 1, table.maxn(keyList) do
    if keyList[i] == "user" then
        key1 = i
        for j = 1, table.maxn(keyList) do
            if keyList[j] == "pass" then
                doesFit = checkValPairs(checklist, keyList[key1], valList[key1], keyList[j], valList[j])
            end
        end
    end
end

-- Show wether the combination fits or not
ngx.say(doesFit)

在第二次运行时,即使是从新的浏览器窗口,我也会收到以下错误:

  

* 1 lua入口线程中止:运行时错误:/home/myname/code/workbench/src/handler.lua:3:尝试调用全局'loadCheckfile'(零值)

nginx.conf(仅用于开发,而不是最后的开发):

user root;

worker_processes 1;
daemon off;
error_log /dev/stdout warn;

events {
    worker_connections 32;
}

http {
    default_type text/html;
    access_log off;

    lua_package_path '/home/myname/code/workbench/src/?.lua;;';
    server {
       listen 80;

       location / {
            content_by_lua_file /home/myname/code/workbench/src/handler.lua;
        }
    }
}

loadCheckfile.lua:

local function fillChecklistTable(checklist, valueLine) 
    repeat
        firstValLength = string.find(valueLine,"=")
        firstVal = string.sub(valueLine, 1, firstValLength-1)

        valueLine = string.sub(valueLine, firstValLength+1)

        secondValLength = string.find(valueLine, ",")

        if secondValLength ~= nil then
            secondVal = string.sub(valueLine, 1, secondValLength-1)
        else
           secondVal = valueLine
        end

        if checklist[firstVal] == nil then
            checklist[firstVal] = {secondVal}
        else
            table.insert(checklist[firstVal], secondVal)
        end

        if secondValLength ~= nil then
            valueLine = string.sub(valueLine, secondValLength+1)
        else
            valueLine = nil
        end

     until valueLine == nil
end

checklist = {}

function loadCheckfile(checkfile)
    local values = io.open(checkfile)
    local valueLine = values:read()

    while valueLine ~= nil do
        fillChecklistTable(checklist, valueLine)
        valueLine = values:read()
    end
    return checklist
end

任何人都知道这个菜鸟又错了什么?提前致谢!

更新:

handler.lua

checklist = {}

local checkFile = require("loadCheckfile")
local checkPairs = require("checkValPairs")

local checklist = checkFile.loadCheckfile("/home/myname/code/workbench/src/pw_list.txt")

local keyList = {}
local valList = {}

local args = ngx.req.get_uri_args()
for key, val in pairs(args) do
    table.insert(keyList, key)
    table.insert(valList, val)
end


ngx.say(unpack(keyList))
ngx.say(unpack(valList))


local key1

for i = 1, table.maxn(keyList) do
    if keyList[i] == "user" then
        key1 = i
        for j = 1, table.maxn(keyList) do
            if keyList[j] == "pass" then
                doesFit = checkValPairs(checklist, keyList[key1], valList[key1], keyList[j], valList[j])
            end
        end
    end
end

ngx.say(doesFit)

loadCheckfile.lua

module("loadCheckfile", package.seeall)

local function fillChecklistTable(checklist, valueLine) 
    repeat
        firstValLength = string.find(valueLine,"=")
        firstVal = string.sub(valueLine, 1, firstValLength-1)

        valueLine = string.sub(valueLine, firstValLength+1)

        secondValLength = string.find(valueLine, ",")

        if secondValLength ~= nil then
            secondVal = string.sub(valueLine, 1, secondValLength-1)
        else
            secondVal = valueLine
        end

        if checklist[firstVal] == nil then
            checklist[firstVal] = {secondVal}
        else
            table.insert(checklist[firstVal], secondVal)
        end

        if secondValLength ~= nil then
            valueLine = string.sub(valueLine, secondValLength+1)
        else
            valueLine = nil
        end

    until valueLine == nil
end

checklist = {}

function loadCheckfile.loadCheckfile(checkfile)
    local values = io.open(checkfile)
    local valueLine = values:read()

    while valueLine ~= nil do
        fillChecklistTable(checklist, valueLine)
        valueLine = values:read()
    end
    return checklist
end

根据this source,我只将模块放入loadCheckfile.lua和checkValPairs.lua。甚至把它放进去 handler.lua不起作用(只需要尝试)。

3 个答案:

答案 0 :(得分:1)

你的解决方案应该有效,但有一些事情要知道。

OpenResty为每个请求创建一个带有全新全局环境的协程(Lua绿色线程),但require()仅加载模块一次,从不再次执行其main chunk。因此,您在这些模块中设置的所有全局变量仅在第一次请求期间存在。此外,如果您的处理程序生成i / o,则会有第二个请求到达并窃取其部分全局变量的窗口,因此不会完成任何请求。准确的解决方案是永远不要在OpenResty中的模块中设置全局变量(在普通Lua中也是如此,因为破坏_G通常是一个坏主意),而是遵循标准模块习惯用语:

-- mymod.lua

local M = { }

local function private() -- for internal use
    ...
end

function M.public() -- to be 'exported'
    ...
end

return M -- this will be returned from require


-- uses_mymod.lua

local mymod = require 'mymod' -- mymod is M from above

mymod.public()

这种方式模块创建一个包含函数的表,而不是将它们设置为全局变量并将其返回到require()require()每次调用都会返回它。

如果您厌倦了本地功能的可见性规则,请引入另一个local m = { }或您喜欢的任何名称,并将所有私有内容存储在那里。在您的眼中变得丑陋之后,请选择Lua环境等高级主题(setfenv()setmetatable())。如果您不想了解详细信息,请将此行放在local M = { }之前的每个模块中:

setfenv(1, setmetatable({ }, { __index = getfenv(0) }))

您的所有全局变量都是该模块的本地变体,因此您可以避免m(但不是M,仍然需要导出')。

答案 1 :(得分:0)

使用lua_code_cache off是一个很大的性能问题,因为它会一次又一次地执行代码。试试这个

local checkFile = require("loadCheckfile")  
local checkPairs = require("checkValPairs")
local checklist = checkFile.loadCheckfile("/home/myname/code/workbench/src/check.lst")

让我知道这是否有效,我将添加解释

答案 2 :(得分:0)

<强>注意

请不要使用此解决方案。虽然它确实有效,但它并不好。 我会留在这里了解其中一个答案。

原始回答:

我的问题的解决方案是通过nginx.conf使模块全局化。

所以我在配置中插入了一个init_by_lua_file,调用一个预加载的lua文件,其中包含我需要的所有函数,在全局级别提供此函数。

.conf:

user root;

worker_processes 1;
daemon off;  #used for developing purpose
error_log /dev/stdout warn; #as well for developing

events {
    worker_connections 32;
}


http {
    default_type text/html;
    access_log off;

    lua_package_path '/home/myname/code/workbench/src/?.lua;;'; 

    init_by_lua_file '/home/myname/code/workbench/src/preLoader.lua';

    server {
        listen 80;

        location / {
            content_by_lua_file /home/myname/code/workbench/src/handler.lua;
        }
    }
}

新的preLoader.lua:

require("loadCheckfile")
require("checkValPairs")
checklist = loadCheckfile("/home/myname/code/workbench/src/check.list")

最后是handler.lua:

local keyList = {}
local valList = {}

-- Load GET arguments into tables
local args = ngx.req.get_uri_args()
for key, val in pairs(args) do
    table.insert(keyList, key)
    table.insert(valList, val)
end

-- show values in table (just for testing)
ngx.say(unpack(keyList))
ngx.say(unpack(valList))


local key1

-- search for keywords and look them up in the checklist
for i = 1, table.maxn(keyList) do
    if keyList[i] == "user" then
        key1 = i
        for j = 1, table.maxn(keyList) do
            if keyList[j] == "pass" then
                 doesFit = checkValPairs(checklist, keyList[key1], valList[key1], keyList[j], valList[j])
            end
        end
    end
end

-- Show wether the combination fits or not
ngx.say(doesFit)