system的单元文件问题

时间:2017-06-04 20:59:43

标签: systemd

我正在尝试使用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

1 个答案:

答案 0 :(得分:5)

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

简短回答:在IgnoreSIGPIPE=false文件的[Service]下设置.service。来自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 =&#34; $(LC_ALL = C tr -cd&#39; [:alnum:]&#39;&lt; / dev / urandom | fold -w128 |   头-n1)&#34;

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

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