redis.log仅在redis服务端eval/evalsha中有效,需用正确日志级别常量和预拼接字符串;print等标准库被沙箱禁用;替代方案可用redis.call存临时键或发pub/sub;日志是否写入取决于loglevel和logfile配置。

redis.log 能用,但只在 Redis 服务器端 EVAL/EVALSHA 上下文中生效,且必须配合正确的日志级别常量和预拼接字符串;客户端或本地 Lua 环境里调它会直接报错。
redis.log 函数的合法调用方式
它不是通用日志工具,而是 Redis 内核暴露的受限接口。第一个参数必须是 redis.LOG_DEBUG、redis.LOG_NOTICE 这类常量,第二个起必须是纯字符串(或可转为字符串的值),不支持表达式拼接。
- 错误写法:
redis.log(redis.LOG_DEBUG, "key=" .. KEYS[1])→ 报syntax error或attempt to concatenate a nil value - 正确写法:
local msg = string.format("key=%s, arg_len=%d", KEYS[1] or "MISSING", #ARGV); redis.log(redis.LOG_DEBUG, msg) - 注意:
string.format是 Redis 内置支持的,无需额外加载;但若ARGV[1]可能为nil,需先做存在性判断,否则string.format会崩
为什么不能用 print 或 io.write
Redis 的 Lua 沙箱彻底禁用了这些标准库函数。任何尝试调用 print、io.write、os.time 都会触发 Lua script attempted to access a forbidden API 错误——这不是配置问题,是内核硬限制。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 常见错误现象:
(error) ERR Error running script (call to f_): @user_script:3: user_script:3: attempt to call a nil value (global 'print') - 连大小写都敏感:
redis.LOG_DEBUG(全大写)会报错,必须是redis.LOG_DEBUG(首字母大写) - 日志是否实际写入,取决于
redis.conf中的loglevel(默认只记NOTICE及以上)和logfile路径是否可写
替代方案:用 redis.call 输出调试信息
当 redis.log 不可用(比如 loglevel 太高、logfile 权限不足),或你想把状态“带出来”供客户端检查时,就得靠 redis.call 主动写出去。
- 存临时键:
redis.call("set", "debug:" .. ARGV[1], cjson.encode({step="before_get", key=KEYS[1]})),之后用GET查 - 发 Pub/Sub:
redis.call("publish", "lua:debug", cjson.encode({ts=os.time(), msg="step_2"})),需客户端另起订阅连接收 - 用
cjson.encode而非手动拼接,避免nil或table导致崩溃;但别 encode 整个hgetall返回值——它结构扁平难读,且易超长 - 别用
lpush累积日志:脚本失败时残留数据无法回滚,污染业务键空间
错误捕获与日志联动的关键点
pcall 和 xpcall 能帮你截住运行时错误,但它们本身不产生日志——你得主动把错误信息喂给 redis.log 或 redis.call。
- 典型模式:
local ok, err = pcall(function() return redis.call("incr", KEYS[1]) end); if not ok then redis.log(redis.LOG_ERR, "incr failed: " .. tostring(err)) end - 注意:
tostring(err)必须加,因为err可能是 table;但不要直接err.msg,不同错误类型字段名不一致 - 单条日志别超 200 字符:Redis 会截断超 1024 字符的内容,且过长日志影响性能
真正容易被忽略的是日志可见性依赖服务端配置——哪怕脚本里写了 redis.log(redis.LOG_DEBUG, ...),如果 redis.conf 里 loglevel 是 notice,这条日志就永远进不了文件。调试前先确认配置已生效,比反复改脚本更省时间。










