tr的systemd单位文件问题

Kri*_*ris 3 systemd

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

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

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

如果我要替换此行,random="1234"也可以在systemd中运行。我猜想'hanging'命令是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
Run Code Online (Sandbox Code Playgroud)

Tom*_*rck 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.
Run Code Online (Sandbox Code Playgroud)

详细说明

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

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

但是,当管道在下运行时systemdsystemd将的默认操作设置SIGPIPESIG_IGN,这会使管道中的进程忽略该信号。尽管该fold命令忽略了该信号,但是当它写入断开的管道时,它仍然会收到EPIPE错误。但是该fold命令不会检查任何fwrite调用的返回值,至少不在in中coreutils-8.26。这导致fold命令继续从std读入并且忽略该错误,并向std写入。这样做时,请fold保持管道tr畅通。由于还tr忽略了SIGPIPE和,并且to的管道fold是打开的,因此它将/dev/urandom永远继续从过滤器中读取数据并将字节永远写入管道。