我正在编写一个简单的 systemd 服务,它通过 websocket 写入输出vmstat
,以便对另一个应用程序进行一些 CPU 利用率测试。我将输出传输vmstat
到wscat
如下位置:
vmstat -n 1 | wscat localhost:1234
vmstat -n 1
每秒向标准输出一条状态行。
只要我的 Web 套接字服务器在 stat 服务启动时已在监听,一切就都正常了。但如果服务器未在监听,我希望我的stat-test
服务失败,然后每 10 秒自动重试一次。
但是,当我将其作为服务运行时,它wscat
永远不会退出(即使失败了),所以我的服务永远不会重新启动。起初我以为出了问题,但即使我将输出通过管道传输到wscat
,它仍然会挂起。vmstat
nonfunction
为了简单起见,我仅发布这个最小的失败测试用例。
stat-test.sh
:
#!/bin/bash
vmstat -n 1 | nonfunction
echo Exited with $?
stat-test.service
:
[Unit]
Description=Stat-Test
[Service]
ExecStart=/bin/bash /path/stat-test.sh
Restart=always
RestartSec=10000ms
[Install]
WantedBy=multi-user.target
当我./stat-test.sh
直接从终端运行时,我得到:
stat-test.sh: line 3: nonfunction: command not found
Exited with 127
但是,当我将其作为服务运行时systemctl start stat-test
,我得到:
systemd[1]: Started Stat-Test.
bash[32168]: /path/stat-test.sh: line 3: nonfunction: command not found
请注意,它从不打印出退出代码。出于某种原因,失败的命令在作为服务运行时从不退出并继续运行。
但是,如果我将其更改为:echo 1 | nonfunction
,服务将正常失败。因此,看起来vmstat
永远运行的事实以某种方式导致它所传输的命令永远不会退出,但只有在作为服务运行时才会退出。
为什么会发生这种情况?我怎样才能使我的服务正常失败?
答案1
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.
阅读那里的完整答案以获得解释。 在你的情况下vmstat
忽略了SIGPIPE
,而你不想这样做。
应用解决方案后,请echo
从脚本中删除它,因为它会影响退出状态。