进一步阅读

进一步阅读

我配置了以下服务:

[Unit]
Description=SCollector
After=NetworkManager.service

[Service]  
Type=simple
ExecStart=/bin/sh -c "/opt/scollector/scollector /opt/scollector/collectors || (echo '' | /usr/bin/mail -s 'scollector died' [email protected] && exit -1)"
Restart=on-failure

[Install]
WantedBy=multi-user.target    

由于某种原因,当进程以非 0 退出时,该mail命令从不发送任何邮件。scollector当在命令行上运行、/bin/sh调用等时,这可以正常工作。我已经捕获了 STDOUT 和 STDERR mail,并且它没有抛出任何错误。里面什么都没有maillog

是什么赋予了?为什么不发送邮件?

答案1

/usr/bin/mail执行双重fork守护进程sendmail以发送电子邮件。这个sendmail进程被重新拥有init,所以通常它不会受到原始父进程发生的任何事情的影响 - 除了在 systemd 情况下,重新拥有的孙子仍然与原始服务位于同一个 cgroup 中。当systemd拆除东西时,它会杀死 cgroup 内的所有进程,包括重新拥有的sendmail进程。

mail命令本身运行良好,但sendmail在它有机会执行其操作之前就被 systemd 杀死了。

KillMode您可以通过在Unit部分中设置process(默认为)来解决此问题control-group。这将导致systemd仅终止它直接触发的进程。

有趣的是,我偶然发现这一点的方式是通过使用strace.正常情况strace下什么也没显示,但mail使用时突然开始工作strace -fstrace -f导致主要进程一直保留,直到所有的孩子和孤儿孙子都完成。

答案2

提问者已经指出了问题;但 xyr 解决方案是一个困境,并且 xyr 对力学的描述是不正确的。

mail命令确实不是执行双叉。它只分叉一次,并且 sendmail shim 进程是它的直接子进程,不会重新指定任何内容的父级。它只是waitpid()在退出之前 选择是否为该孩子服务。

sendmail shim 本身也是如此。它不会双叉。在某些 MTS 上,它甚至根本不分叉。在其他系统上,它仅分叉一次,并选择是否等待或不依赖于某些可配置的“交付模式”选项。

解决该问题的正确方法有两个:

  1. Setmailx的记录和标准化sendwait选项。通过mailx等待 sendmail shim 子进程完成,专门解决了异步排队问题。 (遗憾的是,尽管这个选项至少从 1986 年就已经存在,并且mailx在 SVID 中有记录,但 bsd-mailx 没有它。但 heirloom-mailx 有它。)
  2. 将正在使用的任何 MTS 设置为使用同步排队/传送模式(如果尚未使用)。
    • 如果使用 netqmail,则不执行任何操作。 netqmail 的 sendmail shim 始终排队且同步,直接链式加载到qmail-injectqmail-queue根本不分叉。
    • 如果使用 Postfix,则不执行任何操作。 Postfix 的 sendmail shim 始终排队且同步,分叉一次并等待postdrop完成后再退出。
    • exim 有-odf命令行选项。

进一步阅读

相关内容