Lua非阻塞写日志
用nginx-lua搭的服务需要写日志,一般采用nginx自带的accesslog加logrotate脚本来实现,但是无法满足一次请求需要写多条日志的需求
之前用C和GO实现过类似的代码,思路是主进程写管道,子进程读管道并交由apache-rotatelogs写日志
这里用Lua也实现了一下--
-- Rlog is an non-blocking logging based on pipe.
-- Rotatelogs of Apache is recommanded to be the output of pipe.
-- Before using Rlog, you should install luaposix.
--
local posix = require("posix")
local os = require("os")
-- input of pipe
local pipe_in
-- init rlog
-- @param pipe_cmd pipe operator and the reveiver command.
-- e.g. "| rotatelogs -l %Y%m%d%H.logfile 3600"
-- @return true when success, false when fail
local function init(pipe_cmd)
-- if already inited, do nothing
if pipe_in then return true end
-- if pipe_cmd is not start with pipe operator, return false
if string.sub(pipe_cmd, 1, 1) ~= "|" then return false end
-- create pipe
local pout, pin = posix.pipe()
-- fork process to execute cmd
if posix.fork() == 0 then
-- close stdin
io.close(io.stdin)
-- set output of pipe as stdin
posix.dup2(pout, posix.fileno(io.stdin))
-- close input and output of pipe
posix.close(pout)
posix.close(pin)
-- execute cmd
os.execute(string.sub(pipe_cmd, 2, -1))
end
-- get input of pipe
pipe_in = pin
-- close output of pipe
posix.close(pout)
return true
end
-- write log
local function log(log_str)
-- write log into pipe
posix.write(pipe_in, log_str .. "\n")
end
return {
init = init,
log = log
}
下边是它的测试程序
local rlog = require("rlog")
-- init
ret = rlog.init("| rotatelogs -l %Y%m%d%H.log 3600")
if not ret then
print("init fail")
end
-- log
rlog.log("Hello Rlog")
由于posix.write写管道是原子的,所以无须担心多进程或多线程写混乱的问题
不过这段代码依赖luaposix库,使用前需要安装一下。
Lua 的详细介绍:请点这里
Lua 的下载地址:请点这里