Rsyslog模板是解决日志混乱的核心手段,支持传统字符串模板和新式RainerScript对象模板两种定义方式,用于按主机名分目录存储和输出结构化JSON日志,并需注意定义顺序、语法验证与调试方法。

Rsyslog 的模板功能不是锦上添花的选项,而是解决日志混乱问题的核心手段。当你面对多台服务器共用一个日志文件、排查故障耗时费力时,真正有效的办法是让日志从源头就按需组织——靠的就是模板。
模板定义方式与语法要点
rsyslog 支持两种主流定义方式,适用场景不同,不能混用:
-
传统字符串模板:用
$template开头,适合路径动态生成或简单格式拼接
例如:$template HostPath,"/var/log/%hostname%/%programname%.log" -
新式对象模板(RainerScript):用
template(name="xxx" type="list")声明,支持嵌套、条件、JSON 输出等高级能力
例如:template(name="jsonout" type="list") { property(name="timereported" format="json") constant(value=",") property(name="hostname" format="json" outname="host") }
注意:%hostname% 这类占位符叫“属性”,不是变量名,大小写敏感;属性后可加过滤器,如 %hostname:1:3% 表示取主机名前3个字符。
按主机名自动分目录存储
这是最常用也最实用的模板落地场景。目标是每台机器的日志独立成目录,避免交叉污染。
- 先定义模板:
template(name="ByHost" type="string" string="/var/log/rsyslog/%hostname%/%$year%-%$month%-%$day%.log") - 再绑定规则:在 rules 区域添加
*.* ?ByHost(?表示使用模板命名的输出路径) - 确保目录可写:rsyslog 不会自动创建多级目录,需提前
mkdir -p /var/log/rsyslog/web01或配合 logrotate 初始化
如果主机名含下划线或点号,建议用 %hostname:R,REPLACE:_.:/ 替换非法路径字符,防止写入失败。
结构化日志输出(JSON 格式)
对接 ELK、Loki 等日志平台时,原始文本日志解析困难,JSON 是更稳妥的选择。
- 使用
type="list"模板,每个property对应一个字段,constant插入分隔符 - 关键字段推荐包含:
timereported(带时区)、hostname、programname、severity-text、msg - 避免直接输出
%msg%,改用property(name="msg" format="json"),自动转义引号和换行符
输出到文件时,一行一条 JSON,便于后续工具逐行读取;转发到远程 TCP 端点时,同样适用该模板。
模板生效与调试技巧
配置写完不生效?常见卡点在这里:
- 模板必须定义在
rules规则之前,否则引用时报错 - 修改配置后执行
sudo rsyslogd -N1验证语法(-N1 表示只做一次配置检查) - 启用调试日志:
export RSYSLOG_DEBUG="debug on" && sudo rsyslogd -d -n,观察模板是否被解析、属性是否为空 - 测试模板效果:用
logger "test message"发送日志,立刻检查目标路径或内容格式
模板本身不处理日志筛选,它只管“怎么写”;筛选逻辑由 selector(如 auth.*)控制,两者需配合使用。

















