linux - 管道中的 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=
指令的事实被认为是: 0
systemd 让我想到了set -o pipefail
我们用来使 bash 脚本将管道错误理解为全局错误的 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.
推荐阅读
- javascript - 当 rowGroup 为真时,AgGrid 行计数
- spring - 如何测试 Spring Data JPA 项目
- java - getIdentifier 没有给出正确的 id
- django - 哪个更有意义,在 django 中编写模型或创建表然后自动生成模型?
- python - 条纹错误:无法使用此时间戳创建使用记录,因为时间戳必须早于订阅的当前周期结束时间
- c++ - 从类中访问 char 数组
- python - AttributeError:模块“枚举”没有属性“IntFlag”-fastai 安装
- javascript - 访问身份验证-令牌生成找不到变量令牌的错误
- javascript - 在列表中使用 Modal 似乎会选择列表的最后一个值
- ios - 从网络调用收到的输入计算结果后推送 iOS 通知的最佳方式?