Rsyslog 无“Dynamic-File”内置模块,动态文件路径需通过模板(template)结合属性替换(如%programname%、%$!app_name%)实现,依赖v8.33+版本及imfile/mmjsonparse等模块支持。

Rsyslog 的 Dynamic-File 功能本身并不存在——这是常见误解。Rsyslog 没有名为 “Dynamic-File” 的内置模块或指令。你实际想实现的是:根据日志内容(如程序名、标签、字段值等)动态生成文件路径并写入日志,这通过 模板(template)+ 属性替换(property-based filename) 实现,核心依赖 template 定义和 $!myvar 或 %$!myvar% 等动态属性语法(需启用 imfile 或使用 msg parsing 提取字段)。
确认 Rsyslog 版本与模块支持
动态路径功能在 v8.33+(尤其是支持 property replacer 和 mmfields/mmjsonparse)后更稳定。请先验证:
- 运行
rsyslogd -v,确保版本 ≥ 8.33(推荐 8.2100+ 或最新 stable) - 检查是否加载了必要模块:在
/etc/rsyslog.conf或/etc/rsyslog.d/*.conf中确认含:$ModLoad imfile(若监听文件)$ModLoad mmjsonparse或$ModLoad mmfields(若需解析结构化日志)$ModLoad omfile(输出必需)
用模板 + 属性替换实现动态路径
关键在于:定义一个 template,其 file 参数中嵌入可变属性(如 %programname%、%$!app_id%、%$!level%),rsyslog 会在每条日志写入前实时计算路径。
示例:按 programname 自动分目录存储(无需预建目录):
# 定义模板:路径含 programname,并自动创建多级目录
template(name="DynAppPath" type="string"
string="/var/log/apps/%programname%/%$year%-%$month%-%$day%.log")
<h1>应用规则:所有 facility local6 的日志走此模板</h1><p>if $syslogfacility-text == 'local6' then {
action(type="omfile" template="DynAppPath"
dirCreateMode="0755" fileCreateMode="0644")
stop
}</p>
-
%programname%是内置属性,直接取自 syslog 标头(如sshd、nginx) -
%$year%-%$month%-%$day%是 rsyslog 内置时间宏,自动展开为2024-06-15 -
dirCreateMode="0755"启用自动建目录(v8.33+ 支持,旧版需手动mkdir -p)
从日志内容中提取字段并用于路径(JSON/Key-Value 日志)
若原始日志是 JSON(如 Docker、Prometheus exporter 输出),需先解析再引用字段:
# 加载解析模块
module(load="mmjsonparse")
<h1>解析日志体(假设 $msg 是完整 JSON)</h1><p>if $parsesuccess == "OK" then {</p><h1>提取 app_name 和 env 字段(JSON 中 {"app_name":"api","env":"prod"})</h1><pre class="brush:php;toolbar:false;">set $!app_name = $.app_name;
set $!env = $.env;}
定义模板:用提取的字段构造路径
template(name="JsonAppEnvPath" type="string" string="/var/log/json/%$!app_name%/%$!env%/daily/%$year%-%$month%-%$day%.log")
路由匹配日志(例如含 "app_name" 字段的)
if $!app_name != "" then { action(type="omfile" template="JsonAppEnvPath" dirCreateMode="0755" fileCreateMode="0644") stop }
-
$.app_name表示从 JSON 根对象读取app_name字段 -
$!app_name是自定义变量名(以$!开头),可在 template 中用%$!app_name%引用 - 若字段不存在,
%$!app_name%展开为空字符串,路径可能含//—— 可加if $!app_name == "" then set $!app_name = "unknown"防错
注意事项与排错要点
-
权限问题最常见:rsyslog 进程(通常为
syslog用户)必须对父目录(如/var/log/apps)有wx权限才能创建子目录;建议chown syslog:syslog /var/log/apps && chmod 0755 /var/log/apps - 模板名不能含空格或特殊符号,且需全局唯一;调用时名字必须完全一致
-
属性名区分大小写:
%PROGRAMNAME%无效,必须用%programname% -
测试模板是否生效:临时加一条规则写入固定路径 + 原始内容,如:
*.* /tmp/rsyslog-debug.log;RSYSLOG_DebugFormat,查看实际解析出的$!xxx值 - 重启后运行
sudo rsyslogd -N1检查配置语法;用journalctl -u rsyslog -f查看启动错误











