管道中的python进程返回异常后,Systemd单元未失败

问题描述

我们有这个 systemd 单元,它在其 ExecStart= 指令中启动两个管道 python 进程。该单元的类型为:oneshot,并且当第一个 Python 进程以某种方式引发异常时,该单元将返回到 inactive 状态。

下面是我们的单位。它没有:[Install] 部分,因为我们使用计时器触发它,或者手动使用:systemctl start my-unit.service:

[Unit]
Description=Connector
Documentation=Docs
StartLimitInterval=600
StartLimitBurst=3

[Service]
Type=oneshot
User=user
Group=group
WorkingDirectory=/home/user/dir

ExecStartPre=bash -c 'echo "Pre"'
ExecStart=bash -c 'python_1 | python_2'
ExecStartPost=bash -c 'echo "Post"'

KillMode=control-group
KillSignal=SIGTERM

StandardOutput=append:/home/user/dir/out.log
StandardError=append:/home/user/dir/err.log

TimeoutSec=21600

Restart=on-failure
RestartSec=5
RemainAfterExit=false

来自文档 systemd 不支持管道,这就是为什么我们一直在运行包含在 bash -c '...' 命令中的整个事情。

通过查看日志,我知道第一个 python 进程引发了异常:/home/user/dir/err.log。这是第一个进程引发异常后单元的状态:

● my-unit.service - Connector
     Loaded: loaded (/etc/systemd/system/my-unit.service; static; vendor preset: enabled)
     Active: inactive (dead) since Tue 2021-05-11 14:48:24 UTC; 12s ago
TriggeredBy: ● my-unit.timer
    Process: 108838 ExecStartPre=/usr/bin/bash -c echo "Pre" (code=exited,status=0/SUCCESS)
    Process: 108839 ExecStart=/usr/bin/bash -c p1 | p2 (code=exited,status=0/SUCCESS)
    Process: 108973 ExecStartPost=/usr/bin/bash -c echo "Post" (code=exited,status=0/SUCCESS)
   Main PID: 108839 (code=exited,status=0/SUCCESS)

May 11 14:48:21 ip-10-11-0-81 systemd[1]: Starting Connector...
May 11 14:48:24 ip-10-11-0-81 systemd[1]: connector-mavenlink.service: Succeeded.
May 11 14:48:24 ip-10-11-0-81 systemd[1]: Finished Connector mavenlink.

我们通常对这个单元很满意,这是它第一次出现故障,但我们真的希望它进入 Failed 状态,因为我们有可观察性工具来监控它。

有什么想法吗?

谢谢!

解决方法

所以我想我解决了我自己的问题,所以我会把它写在这里,可能在我关闭它之前把它留在这里一段时间。它确实感觉有点hacky。

status code 指令的 ExecStart= 被 systemd 认为是:0 这一事实让我想起了我们用来制作 bash 的 set -o pipefail bash 标志脚本将管道错误理解为全局错误(措辞不佳,但我认为这是它的要点)

因此,我编辑了我们的单元,在 -o pipefail 命令中添加了 bash -c '...' 标志,如下所示:

[Unit]
Description=Connector
Documentation=Docs
StartLimitInterval=600
StartLimitBurst=3

[Service]
Type=oneshot
User=user
Group=group
WorkingDirectory=/home/user/dir

ExecStartPre=bash -c 'echo "Pre"'
ExecStart=bash -c 'set -o pipefail && python_1 | python_2'
ExecStartPost=bash -c 'echo "Post"'

KillMode=control-group
KillSignal=SIGTERM

StandardOutput=append:/home/user/dir/out.log
StandardError=append:/home/user/dir/err.log

TimeoutSec=21600

Restart=on-failure
RestartSec=5
RemainAfterExit=false

... 这似乎有效:现在当第一个 python 进程引发异常时,我们的单元被发送到:failed 状态(在我们配置后重新启动几次之后)。以下是更新后的 failed 状态:

● my-unit.service - Connector
     Loaded: loaded (/etc/systemd/system/my-unit.service; static; vendor preset: enabled)
     Active: failed (Result: exit-code) since Tue 2021-05-11 15:01:28 UTC; 1s ago
TriggeredBy: ● my-unit.timer
       Docs: Docs
    Process: 109454 ExecStartPre=/usr/bin/bash -c echo "Pre" (code=exited,status=0/SUCCESS)
    Process: 109463 ExecStart=/usr/bin/bash -c set -o pipefail && p1 | p2 (code=exited,status=1/FAILURE)
   Main PID: 109463 (code=exited,status=1/FAILURE)

May 11 15:01:28 ip-10-11-0-81 systemd[1]: my-unit.service: Scheduled restart job,restart counter is at 3.
May 11 15:01:28 ip-10-11-0-81 systemd[1]: Stopped Connector.
May 11 15:01:28 ip-10-11-0-81 systemd[1]: my-unit.service: Start request repeated too quickly.
May 11 15:01:28 ip-10-11-0-81 systemd[1]: my-unit.service: Failed with result 'exit-code'.
May 11 15:01:28 ip-10-11-0-81 systemd[1]: Failed to start Connector.

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...