使用Nginx Lua模块写入文件
我正在尝试使用 Nginx Lua 模块 进行实验。目前,我的目标只是将某些HTTP响应保存到本地磁盘文件中。
阅读了一些教程之后,我了解到可以使用 body_filter_by_lua 指令来实现这个目的。我的方法很简单,只是在 nginx.conf 文件中嵌入一些 Lua 代码,从 ngx.arg 中检索响应体,然后使用标准的 Lua io 设施将其写入磁盘。
我以前从没有用过 Lua 进行编程,但我曾经在其他脚本语言如 Python 中进行过大量编程,所以我发现学习 Lua 的基础知识相对容易。
尽管如此,我的方法并没有起作用,nginx的 error.log 表明问题在于我打开的 file 对象是 nil。
以下是我在 nginx.conf 文件中放置的 Lua 代码(经过修改以提高可读性):
location /foo {
proxy_pass http://my_upstream_proxy;
proxy_cache my_cache;
proxy_redirect default;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
body_filter_by_lua '
local resp_body = ngx.arg[1]
ngx.ctx.buffered = (ngx.ctx.buffered or "") .. resp_body
if ngx.arg[2] then
ngx.var.resp_body = ngx.ctx.buffered
end
local file = io.open("TEST.txt", "w+b")
file:write(resp_body)
file:close()
';
}
这里的想法是,nginx只需将请求转发给代理,然后将响应体写入本地文件。
我使用以下命令进行测试:
curl http://www.google.com --proxy http://localhost:80
但是nginx返回了一个空回复。
我查看错误日志,并看到:
2016/12/15 11:51:00 [error] 10056#0: *1 failed to run body_filter_by_lua*: body_filter_by_lua:9: attempt to index local 'file' (a nil value)
stack traceback:
body_filter_by_lua:9: in function <body_filter_by_lua:1> while sending to client, client: 127.0.0.1, server: test-server, request: "GET http://www.google.com/ HTTP/1.1", upstream: "http://69.187.22.138:82/", host: "www.google.com"
那么为什么我的本地 file 变量是 nil 呢?当我使用 bash 打开 Lua 控制台时,我能够轻易地打开/创建一个新的本地文件并写入文本,没有任何问题。
那么我做错了什么?起初,我认为可能是某些权限问题,nginx无法在当前工作目录中写入文件,但我理解 nginx 是以 root 身份运行的。我尝试了类似于 /home/myusername/NGINX.txt 的绝对路径,但仍然失败了,文件是 nil。我无法获得有关 file 为什么为 nil 的更具体错误。
那么我做错了什么?
我认为你应该将以下代码修改为:
local file = io.open("TEST.txt", "a")
而不是:
local file = io.open("TEST.txt", "w+b")
Permission issue
无权在该位置创建/打开 "test.txt"。对于我来说,是在/usr/local/nginx-1.14.2/sbin/中。
解决方法: 授予权限。在我的测试环境中,/usr/local/nginx-1.14.2/ sudo chomd -r 777
为了找到真正的问题,可以尝试替换您的 "io.open" 部分,如下所示:
handle_name, err = io.open(file,"w")
print(err)
使用上面的lua语句,我得到了 "permission denied" 的错误信息。
io.open 函数如果无法打开文件,则会返回 nil。你可以获取错误信息:
local file, err = io.open("TEST.txt", "w+b")
if file == nil then
print("无法打开文件: " .. err)
else
file:write(resp_body)
file:close()
end
- Lua 虚拟机加密load(string.dump(function)) 后执行失败问题如何解决
- 我想创建一个 Nginx 规则,禁止访问
- 如何将两个不同的lua文件合成一个 东西有点长 大佬请耐心看完 我是小白研究几天了都没搞定
- 如何在roblox studio中1:1导入真实世界的地形?
- 求解,lua_resume的第二次调用继续执行协程问题。
- 【上海普陀区】内向猫网络招募【Skynet游戏框架Lua后端程序员】
- SF爱好求教:如何用lua实现游戏内调用数据库函数实现账号密码注册?
- Lua实现网站后台开发
- LUA错误显式返回,社区常见的规约是怎么样的
- lua5.3下载库失败
- 请问如何实现文本框内容和某个网页搜索框内容连接,并把网页输出来的结果反馈到另外一个文本框上
- lua lanes多线程使用
- 一个kv数据库
- openresty 有没有比较轻量的 docker 镜像
- 想问一下,有大佬用过luacurl吗
- 在Lua执行过程中使用Load函数出现问题
- 为什么 neovim 里没有显示一些特殊字符?
- Lua比较两个表的值(不考虑键的顺序)
- 有个lua简单的项目,外包,有意者加微信 liuheng600456详谈,最好在成都
- 如何在 Visual Studio 2022 中运行 Lua 代码?

在 Lua 上不是专家,但在我的尝试中,我学到了将 "io.open" 调用包装在 "assert" 函数中。请参阅 assert 的文档
local file = assert(io.open("TEST.txt", "w+b"), "Inaccessible file")这可能只是证实了代码失败的位置。看着这一行,我不知道 "w+b" 中的 "b" 模式是什么。
你是指要覆盖就像在
io.open("TEST.txt", "w")中,还是追加就像在io.open("TEST.txt", "a")中?如果你用这些测试仍然出现错误,那么就意味着无法实际访问文件。