【问题标题】:Openresty Lua script only works one timeOpenresty Lua 脚本只能运行一次
【发布时间】:2018-01-30 06:55:06
【问题描述】:

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

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 没有工作(只是不得不尝试)。

【问题讨论】:

  • 同时发布 nginx 配置和 loadCheckfile
  • 在 nginx.conf 中添加 lua_code_cache off 解决了这个问题。然而,我非常怀疑这是否适合工作环境。

标签: nginx lua openresty


【解决方案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,'exports' 仍然需要)。

【讨论】:

  • 谢谢。您的回答帮助我理解了我在原始问题中的错误。我从来没有返回模块末尾的函数,只是函数本身中的表。
【解决方案2】:

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

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

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

【讨论】:

  • 我收到local checklist = checkFile.loadCheckfile("/home/myname/code/workbench/src/check.lst") 行的错误,声明尝试索引本地'checkFile'(布尔值)
  • 将此添加到您的文件顶部module("loadCheckfile", package.seeall),更改其他文件的名称并查看它是否有效
  • 它仍在尝试索引本地“checkFile”(一个布尔值)。
  • 在问题中发布您更新的代码以及错误详细信息
  • 完成。感谢您的努力,我真的觉得我在这种情况下抓住了愚蠢-.-
【解决方案3】:

注意

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

原答案:

我的问题的解决方案是通过 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)

【讨论】:

    猜你喜欢
    • 2022-10-16
    • 1970-01-01
    • 1970-01-01
    • 2011-02-26
    • 2021-04-02
    • 1970-01-01
    • 2013-09-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多