当前位置:首页>Linux>Arm Linux 日志实战:zlog + 远程 syslog 双通道(本地文件 + 中心化收集)

Arm Linux 日志实战:zlog + 远程 syslog 双通道(本地文件 + 中心化收集)

  • 2026-09-29 09:52:30
Arm Linux 日志实战:zlog + 远程 syslog 双通道(本地文件 + 中心化收集)

工业网关 / 边缘设备最典型的日志诉求:本地留一份带轮转的详情日志方便现场排查,同时把关键错误实时送到远端日志中心做集中监控告警。

架构

        ┌──────────── app (zlog) ────────────┐
        │  category "app"                     │
        │   ├─ INFO+      ──→ /var/log/app.log│  本地文件(轮转)  ← 通道1
        │   └─ ERROR/FATAL ──→ >syslog ───────┤
        └────────────────────────────────────┘
                                │
                        本地 rsyslogd
                                │  *.* @logserver:514  (UDP)
                                ▼
                       远程日志中心 (rsyslog / ELK / Loki ...)
                                              ← 通道2
  • 通道 1(本地):zlog 把业务日志写到本地文件,带大小轮转,便于现场 tail 排障。
  • 通道 2(远程):zlog 把 ERROR/FATAL 同时送到系统 syslog,由板子上的 rsyslogd 转发到远程日志中心,做集中存储 / 告警。

1. zlog.conf:一个 category,两路输出

[global]
strict init = true
log level = DEBUG


[formats]
file_fmt = "%d(%Y-%m-%d %H:%M:%S.%ms) [%V] %m%n"   ; %V 才是级别,%p 是进程 PID
sys_fmt  = "%m"                                    ; 送 syslog 只放消息体

 [rules]
# 通道1:日常日志落本地文件,带大小轮转
app.INFO      "/var/log/app.log", 10MB * 5 ~; file_fmt
# 通道2:ERROR/FATAL 同时进系统 syslog(再被 rsyslogd 转发出去)
#        >syslog 必须带 facility,如 LOG_LOCAL0 / LOG_USER
app.ERROR     >syslog, LOG_LOCAL0 ; sys_fmt
app.FATAL     >syslog, LOG_LOCAL0 ; sys_fmt

>syslog 是 zlog 内置的输出目标:它会把日志按级别映射成 syslog 优先级(DEBUG→LOG_DEBUG、INFO→LOG_INFO……),并用 category 名作为 ident 调用系统 syslog()。无需在代码里再 openlog,zlog 自己搞定。

验证配置文件:

LD_LIBRARY_PATH=. ./zlog-chk-conf ./zlog.conf
--[./zlog.conf] syntax right


2. 板子 rsyslog:把 syslog 转发到远程

在板子的 rsyslog 配置里加一条转发规则(Debian / Yocto 系通常放 /etc/rsyslog.d/30-remote.conf):

# UDP 转发全部日志到中心服务器(@ 是 UDP,@@ 是 TCP)
*.* @192.168.1.100:514
# 只想转发 app 的 ERROR 以上,可限定设施,例如:
#   local0.* @192.168.1.100:514

busybox 轻量系统(无 rsyslogd)则改 /etc/syslog.conf 或 syslog-ng.conf 的转发语句,语义类似。

改完重启守护进程让配置生效:

# systemd 系统
systemctl restart rsyslog
# 老式 init / busybox
/etc/init.d/rsyslog restart
# 或 kill -HUP $(cat /var/run/rsyslogd.pid)

3. 应用代码(只管 zlog,双通道自动发生)

/* zlog_syslog_dual.c —— 本地文件 + 远程 syslog 双通道 */
#include <stdio.h>
#include "zlog.h"

int main(void) {
int rc;
zlog_category_t *zc;

    rc = zlog_init("zlog.conf");
if (rc) { printf("zlog_init failed\n"); return -1; }
    zc = zlog_get_category("app");
if (!zc) { zlog_fini(); return -2; }

    zlog_info(zc,  "app started, pid=%d", (int)getpid());  /* 仅本地文件 */
    zlog_warn(zc,  "config item missing, use default");    /* 仅本地文件 */
    zlog_error(zc, "db connect failed: %m");               /* 文件 + 远程syslog */
    zlog_fatal(zc, "cannot continue, going down");         /* 文件 + 远程syslog */

    zlog_fini();
return 0;
}

交叉编译(Arm Linux):

arm-linux-gnueabihf-gcc zlog_syslog_dual.c -o app -lzlog -lpthread

4. 验证远程收到

在中心服务器用 nc 抓包快速验证(UDP 514):

nc -ul 514        # 应能收到板子发来的 ERROR/FATAL 行

生产环境中心侧通常用 rsyslog 服务端、或 Vector / Filebeat 接 ELK、或 Promtail 接 Loki 做可视化与告警。


5. 想要更细的设施(facility)控制?——混合 libc syslog 方案

zlog 的 >syslog 走的是系统默认设施,若想把 app 日志单独归到 local0 以便在中心侧精准过滤,可在关键路径直接用 libc 的 syslog()(互补而非替代 zlog):

#include <syslog.h>
#include "zlog.h"

/* 初始化时挂上系统 syslog 的 ident/facility */
openlog("myapp", LOG_PID, LOG_LOCAL0);

/* 业务正常日志:zlog 管本地文件 */
zlog_error(zc, "critical op failed: %m");
/* 同一事件再同步到系统 syslog(最终被 rsyslog 转发到 local0.*) */
syslog(LOG_ERR, "critical op failed: %m");

closelog();

板子 rsyslog 侧只需转发该设施:local0.* @192.168.1.100:514。

⚠️ 两点提醒

  1. 两种方式任选其一即可,不要重复:纯 zlog >syslog 最干净;需要自定义 facility 时才用「zlog 文件 + libc syslog 双发」的混合写法。
  2. 远程用 UDP(@)零握手、低延迟但可能丢;对可靠性要求高改 TCP(@@),代价是连接断开时可能阻塞 rsyslog 队列。
如果觉得不错,欢迎 点赞、收藏、转发 ,如果想第一时间收到推送,也可以给个星标⭐~~

最新文章

随机文章