我正在尝试使用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)
编辑:使说明更清晰,并添加了新信息。
答案很简单:设置IgnoreSIGPIPE=false下[Service]的在.service文件中。从systemd.exec手册中:
Run Code Online (Sandbox Code Playgroud)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:]'</ dev / urandom | fold -w128 | head -n1)”
当head从接收到第一个换行符后命令退出时fold,它将关闭打开的文件描述符。当fold命令稍后尝试写入管道时,它将收到一个SIGPIPE信号。此信号的默认操作是终止过程。通常,这应该导致fold命令的终止,并且同样导致命令的后续终止tr。
但是,当管道在下运行时systemd,systemd将的默认操作设置SIGPIPE为SIG_IGN,这会使管道中的进程忽略该信号。尽管该fold命令忽略了该信号,但是当它写入断开的管道时,它仍然会收到EPIPE错误。但是该fold命令不会检查任何fwrite调用的返回值,至少不在in中coreutils-8.26。这导致fold命令继续从std读入并且忽略该错误,并向std写入。这样做时,请fold保持管道tr畅通。由于还tr忽略了SIGPIPE和,并且to的管道fold是打开的,因此它将/dev/urandom永远继续从过滤器中读取数据并将字节永远写入管道。
| 归档时间: |
|
| 查看次数: |
485 次 |
| 最近记录: |