把 syslog-only 的应用程序的日志重定向到 stdout - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Distributions
Ubuntu
Fedora
CentOS
中文资源站
网易开源镜像站
beyondstars
V2EX    Linux

把 syslog-only 的应用程序的日志重定向到 stdout

  •  
  •   beyondstars 1 天前 740 次点击

    背景

    最近在部署容器化的 MX ,其中要用到 OpenDKIM 这个 milter (负责给出站邮件附上 dkim 签名,并检查入站邮件的 dkim 签名),opendkim 有一个问题就是我不知道怎么配才能让它把日志写到 stdout ,它只会往 syslog 写日志,这就是我说的 syslog-only 应用程序。

    容器化的实例最好还是把日志写到 stdout ,方便 container supervisor 统一收集和管理,也具有通用性。我可以把宿主机的 /dev/log socket 以 bind mount 的方式挂载到容器的 mount ns ,然而这种做法破坏了容器的自包含性,会让容器部署依赖于宿主机的 syslog socket 的具体位置。并且在公有云 PaaS 或者权限受限的环境下,访问宿主机的 syslog 服务(或修改其配置让它将来着容器的日志转发到特定端点)并不总是可能的。

    什么是 syslog ? syslog 它既是一个动态链接库提供的一个函数,也是一种日志分发的方式,依赖于 syslog 打印日志的应用程序称为 syslog client ,一般通过 socket 向本机的 syslog server 通信,syslog server 决定对各个应用发来的日志作何处理。

    解决方案

    A. 挂载 (bind mount) 宿主机的 syslog socket 到容器内部,一般位于 /dev/log ,实际上在我的机器上这是一个 symbol link ,指向一个 systemd-journald 负责监听的 socket ,这样就可以让宿主机的 syslog server (systemd-journald) 扮演容器看来缺失了的 syslog server 的角色。前面说了为什么这种做法不行。

    B. 我们说了 syslog 函数一般是通过动态链接的方式实现的,也就是说 app 自己的二进制可能没有 syslog client 的实现逻辑,这个逻辑是复用动态链接库里实现好了的 syslog client 的代码,系统通过解析 syslog 函数到真正的实现(一个 PIE shared object 文件)来使得 app 能以符合 syslog client 规范的行为向 syslog socket 发送日志。理论上,可以通过 LD_PRELOAD 的方式,劫持 app 调用的 syslog 函数。我们自己实现一个仿 syslog 函数,和 app 调用的 syslog 函数的签名一样,然后把收到的日志打到 stdout 。这种方案比较复杂,需要在容器构建时,编译这个 PIE shared object 文件,对于 multi-arch 镜像,也需要为每一种 arch 编译一份 shared object 文件。还需要在容器构建过程中安装额外的 toolchain 。

    C. 在容器里启动一个轻量级的 syslog server 。这是最简单的、最合理的。既然 app 需要 syslog 才能工作,那就给他一个真的。

    思路

    1. 在构建容器的过程中,安装 syslog-ng 软件包,生成或复制一份 syslog-ng 配置文件到容器镜像内。
    2. syslog-ng 的自定义配置思想主要是把所有收集而来的日志转发到一个具名管道,透过 mkfifo 命令创建该管道,或者让 syslog-ng 自动创建。
    3. 使用自定义的容器内启动脚本,使用 --no-caps 参数启动 syslog-ng ,让 shell 读取具名管道,把内容导给一个后台运行的 cat 进程。
    4. 完成一切准备工作后才启动真正要启动的应用。

    具体实现代码

    Dockerfile:

    FROM debian:trixie RUN \ apt-get -y update && \ DEBIAN_FROnTEND=noninteractive apt-get -y --no-install-recommends install opendkim opendkim-tools syslog-ng && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* COPY <<EOF /etc/syslog-ng/syslog-ng.conf destination d_pipe { pipe("/var/log/any.log.pipe"); }; source src { system(); }; log { source(src); destination(d_pipe); }; EOF COPY <<EOF /entrypoint.sh #!/bin/bash mkfifo /var/log/any.log.pipe syslog-ng --no-caps cat </var/log/any.log.pipe & exec /usr/sbin/opendkim -f -x /etc/opendkim/opendkim.conf EOF RUN chmod +x /entrypoint.sh CMD [ "/entrypoint.sh" ] 
    第 1 条附言    11 小时 22 分钟前
    要成功复现,你需要确保容器里面的 opendkim 的自定义配置 /etc/opendkim/opendkim.conf 有下列这几行:

    ```
    Background false

    Syslog true
    SyslogSuccess true
    LogWhy true
    ```
    23 条回复    2025-11-25 17:22:34 +08:00
    defunct9
        1
    defunct9  
       1 天前   1
    容器里的 opendkim 掉了,syslog-ng 没掉,怎么办
    beyondstars
        2
    beyondstars  
    OP
       1 天前
    @defunct9 或许会考虑用 tini 作为一个轻量的 supervisor ,或者 docker run 加 --init 参数。
    beyondstars
        3
    beyondstars  
    OP
       1 天前
    还有一种方法是在 Dockerfile 编写自定义的 healthcheck ,docker 应该会自动重启 unhealthy 的容器
    defunct9
        4
    defunct9  
       1 天前
    -f
    Normally opendkim forks and exits immediately, leaving the service running in the background. This flag suppresses that behaviour so that it runs in the foreground.

    So, 一定是你某个地方配的不对。
    patrickyoung
        5
    patrickyoung  
       1 天前
    @defunct9 #4 根据搜索结果,前台运行似乎并不会输出日志到 stdout/err

    @beyondstars 请善用搜索引擎。https://github.com/instrumentisto/opendkim-docker-image
    adoal
        6
    adoal  
       1 天前
    你们这些痴迷容器的人真麻烦
    defunct9
        7
    defunct9  
       16 小时 52 分钟前
    EXPOSE 8891

    ENTRYPOINT ["/init"]

    CMD ["opendkim", "-f"]

    看了 opendkim-docker-image ,也是-f ,有什么误解么?@patrickyoung
    beyondstars
        8
    beyondstars  
    OP
       11 小时 39 分钟前
    @patrickyoung 谁都会用搜索引擎,不要再我的帖子用你的废话占用空间。另外,每个人都可以独立探索得出自己的发现,如果你擅长用搜索引擎你会发现类似的玩意还不止一个,我没工夫看别人的 Dockerfile 怎么写的,自己手挫出来只用了半个小时还加深了自己对容器和 linux 的理解。你自己的偏好是用现成的东西没问题,但是把自己的想法套在所有人身上就是你的傲慢了。

    `-f` 是让 opendkim 进程留在前台,exec 是在当前 entrypoint.sh 的进程继续执行 opendkim 的内容,而不是为 opendkim 单开一个进程。
    beyondstars
        9
    beyondstars  
    OP
       11 小时 37 分钟前
    @defunct9 我用的是 exec 命令,就是故意让 opendkim 留在前台,是你理解的不对。麻烦再仔细看一遍。
    beyondstars
        10
    beyondstars  
    OP
       11 小时 33 分钟前
    @patrickyoung 我觉得像你这样的人还真不少,遇到任何问题就只会问 AI 和搜索引擎,如果找不到答案就否定需求本身。你应该提高自己的阅读理解能力,我只是用 opendkim 举一个例子,我描述的是针对一整类 syslog-only 应用程序的日志重定向方法。如果你需要容器化 10 个不同的 syslog-only 的容器,我希望你每个都去搜一遍,最好是停止维护 4 、5 年的也继续拿来用。
    beyondstars
        11
    beyondstars  
    OP
       11 小时 30 分钟前
    而且你们难道都没理解对?`-f` 是让进程留在前台,但是和把日志打在 stdout (这属于日志输出路径)没半毛钱关系啊?
    defunct9
        12
    defunct9  
       11 小时 29 分钟前
    哈哈,我还是没理解。容器直接跑个 opendkim -f -v 不行么
    beyondstars
        13
    beyondstars  
    OP
       11 小时 25 分钟前
    要在 opendkim 的配置文件里面启用 Syslog 选项,抱歉我在正文没把这个说明白造成了一些误解。
    julyclyde
        14
    julyclyde  
       10 小时 56 分钟前
    “依赖于宿主机的 syslog socket 的具体位置”
    这不算啥吧?那个不是固定位置么

    感觉颇有点欲加之罪的意思
    julyclyde
        15
    julyclyde  
       10 小时 47 分钟前
    搜了一下,感觉 opendkim 开发组很不求上进
    https://github.com/trusteddomainproject/OpenDKIM/issues/153
    这么基本的功能居然到现在还没有
    julyclyde
        16
    julyclyde  
       10 小时 46 分钟前
    另外,我坚持认为 PRELOAD 方案由于多进程方案
    毕竟,在容器里坚持单个主进程是最佳实践,直接避免了关于( helper 进程挂了是否要整体死给你看)的哲学论题
    defunct9
        17
    defunct9  
       10 小时 15 分钟前
    结案,继续睡觉去
    patrickyoung
        18
    patrickyoung  
       10 小时 4 分钟前
    @defunct9 #7
    他打印到 stdout 的实现是 opendkim 吐到 syslogd 直接吐出 /dev/stdout 的,我要说的点不是 -f

    @beyondstars #8 目的是追求简洁 高效,你还 cat - 包一层,贴个别人写的不那么脏的实现是把你怎么了?
    beyondstars
        19
    beyondstars  
    OP
       9 小时 33 分钟前
    @patrickyoung 简洁高效不是你张口闭口定义的简洁高效,你应该自己去跑个分比对多种方案,从中找出显著差异, 来支持您的主张。

    我发现您没有没有耐心或者理解能力读完全文,我完全没有声明我的方案是效率优先的,我表达的内容是如果遇到了只会输出到 syslog 的应用,对它容器化时怎么把 syslog 日志输出重定向到 stdout 。怎么就莫名其妙和效率扯上关系了呢?

    喷子的常用诡辩逻辑时找到一个缺点,效率看起来不是最优的,就全盘否定一切。在您这里就非常明显了。
    beyondstars
        20
    beyondstars  
    OP
       9 小时 29 分钟前
    @patrickyoung 第二我有我的时间安排,是不是我得像人工智能模型那样,表达任何内容的时候,要检索整个互联网的所有资料呢?我有义务,或者我做出过任何保证,一定要提供最优的方案吗?

    我不知道长期陷入信息茧房的人是什么样的,但是从您表现出的偏执和狭隘来看,症状非常恐怖。仅从性能出发就否定一切。建议看一下心理咨询或者自测。

    另外,如果您追求效率,那么你不需要在这里显摆您的知识,应当自己去改代码让它直接打印到 stdout ,以此实践你的观点。
    beyondstars
        21
    beyondstars  
    OP
       9 小时 27 分钟前
    @patrickyoung 第三,cat 和 shell 做的只是简单的 stream 重定向,纯粹转发 byte stream ,几乎没有任何的计算或判断,这也能成为你的攻击点?这也能造成性能问题?我不理解。
    beyondstars
        22
    beyondstars  
    OP
       9 小时 26 分钟前
    @julyclyde #14 那宿主机不装 syslog server 您的容器就永远不调度到这台机子上了是吗?
    beyondstars
        23
    beyondstars  
    OP
       9 小时 21 分钟前
    @julyclyde #14 另外把 nested containerization (比如 docker in docker) 这样的情景也考虑到,有一些环境就是比较简陋没有 syslog server 和可以 bind mount 到容器内部的 syslog socket 。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1004 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 24ms UTC 18:44 PVG 02:44 LAX 10:44 JFK 13:44
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86