【问题标题】:systemd unit file problems with trtr的systemd单元文件问题
【发布时间】:2017-06-04 20:59:42
【问题描述】:

我正在尝试使用 systemd 执行 shell 脚本。

如果我从 bash 运行我的脚本,一切正常。但是,如果我通过 systemd 运行相同的脚本,它永远不会完成。它似乎挂起的命令是:

random="$(LC_ALL=C tr -cd '[:alnum:]' < /dev/urandom | fold -w128 | head -n1)"

如果我用random="1234" 替换这一行,它也可以与systemd 一起运行。我猜“挂起”命令是tr——它的过程永远不会结束。

这是我正在使用的 systemd 单元文件:

[Unit]
Description=my script

[Service]
Type=forking
Restart=on-failure
ExecStart=/mypath/script.sh start
ExecStop=/bin/kill $MAINPID
ExecStopPost=/bin/rm -f /mypath/RUNNING_PID

[Install]
WantedBy=multi-user.target

【问题讨论】:

  • 你的服务分叉了吗?如果不是,那么Type=fork 是错误的服务类型。有关选项,请参阅man systemd.service
  • 如果 systemd 发现脚本以非零状态退出,Restart=on-failure 将重新启动它。 random="$(LC_ALL=C tr -cd '[:alnum:]' &lt; /dev/urandom | fold -w128 | head -n1)" 是脚本中的最后一个命令吗?
  • @alvits 是的,如果服务崩溃,我想重新启动它。并且:tr 不是脚本中的最后一个命令。
  • @MarkStosberg 是的,它分叉了。

标签: systemd


【解决方案1】:

编辑:使解释更清晰并添加了新信息。

简答:在.service 文件的[Service] 下设置IgnoreSIGPIPE=false。来自systemd.exec 手册:

   IgnoreSIGPIPE=
       Takes a boolean argument. If true, causes
       SIGPIPE to be ignored in the executed process.
       Defaults to true because SIGPIPE generally is
       useful only in shell pipelines.

详细解释

random="$(LC_ALL=C tr -cd '[:alnum:]'

head 命令在从fold 接收到第一个换行符后退出时,它的打开文件描述符被关闭。当fold 命令稍后尝试写入管道时,它将收到SIGPIPE 信号。此信号的默认操作是终止进程。这通常会导致fold 命令的终止,同样会导致tr 命令的后续终止。

但是,当管道在systemd 下运行时,systemdSIGPIPE 的默认操作设置为SIG_IGN,这使得管道中的进程忽略了该信号。虽然fold 命令会忽略该信号,但它在写入损坏的管道时仍会收到 EPIPE 错误。但是fold 命令不检查任何fwrite 调用的返回值,至少在coreutils-8.26 中不检查。这导致fold 命令继续从 std in 读取并忽略错误,写入 std out。在这样做时,fold 使管道从tr 保持打开状态。由于tr 也忽略了SIGPIPE,并且到fold 的管道是打开的,它只是继续从/dev/urandom 读取并将过滤后的字节永远写入管道。

【讨论】:

  • 这个Restart=on-failure 会影响行为。你已经弄清楚了退出状态。
  • 谢谢汤姆!我查找了 IgnoreSIGPIPE,它看起来默认为 true:freedesktop.org/software/systemd/man/…。但是你之前写的——在你编辑答案之前——实际上帮助了我:)。如果我使用$(LC_ALL=C tr -cd '[:alnum:]' &lt; /dev/urandom 2&gt;/dev/null | dd bs=128 count=1 2&gt;/dev/null),它可以工作。就像您之前建议的那样,我将fold -w128 | head -n1dd bs=128 count=1 交换了。我必须添加2&gt;/dev/null 以摆脱journalctl 中的tr: write error: Broken pipe。所以我会检查你的答案是否正确:)
  • 您的原始答案是一种解决方法。但是这个修改后的答案绝对是答案。感谢您引用手册页,它对社区中的每个人都有帮助。
猜你喜欢
  • 2017-01-19
  • 1970-01-01
  • 2017-05-06
  • 1970-01-01
  • 2016-07-24
  • 2019-03-05
  • 1970-01-01
  • 2017-12-26
  • 1970-01-01
相关资源
最近更新 更多