Systemd 延迟重新启动失败的服务,似乎添加了 30 个睡眠时间

Systemd 延迟重新启动失败的服务,似乎添加了 30 个睡眠时间

(最初将其发布在 stackoverflow 上,但被要求将其移至此处。)我有一个作为服务运行的 python 守护进程,有时其中几个正在为需要相同功能的不同进程(p0、p1 等)运行。我注意到,当服务失败时,有时服务需要很长时间才能恢复,需要 2 到 3 分钟。通常我会看到服务在几秒钟内恢复正常。

kill -9我在进程上运行了一个脚本来测试 systemd 是否会重新启动服务并systemctl status myapplication@p1每 30 秒打印一次,直到服务再次运行(其中 3 个服务正在运行)。我注意到,当一个或多个服务在状态消息结束时恢复所需的时间比预期要长时,sleep 30CGroup 的末尾就会出现这个,并且它的 PID 在每次命令调用之间都会发生变化status

    * myapplication.service - my application service for p1.
     Loaded: loaded (/lib/systemd/system/[email protected]; enabled; vendor preset: enabled)
     Active: activating (start) since Fri 2022-03-25 14:48:27 UTC; 26s ago
Cntrl PID: 1335258 (myapplication)
      Tasks: 5 (limit: 9505)
     Memory: 3.3M
        CPU: 1.442s
     CGroup: /system.slice/system-myapplication.slice/[email protected]
             |-1335258 /bin/bash /path/to/application/myapplication start p1
             |-1336794 sudo -u admin -i python /path/to/application/myapplication.py start p1
             |-1336795 logger
             |-1336802 -bash --login -c python \/path\/to\/application/myapplication\.py start p1
             `-1336830 sleep 30



* myapplication.service - my application service for p1.
     Loaded: loaded (/lib/systemd/system/[email protected]; enabled; vendor preset: enabled)
     Active: activating (start) since Fri 2022-03-25 14:48:27 UTC; 56s ago
Cntrl PID: 1335258 (myapplication)
      Tasks: 5 (limit: 9505)
     Memory: 3.3M
        CPU: 1.444s
     CGroup: /system.slice/system-myapplication.slice/[email protected]
             |-1335258 /bin/bash /path/to/application/myapplication start p1
             |-1336794 sudo -u admin -i python /path/to/application/myapplication.py start
             |-1336795 logger
             |-1336802 -bash --login -c python \/path\/to\/application/myapplication\.py start p1
             `-1336919 sleep 30



* myapplication.service - my application service for p1.
     Loaded: loaded (/lib/systemd/system/[email protected]; enabled; vendor preset: enabled)
     Active: activating (start) since Fri 2022-03-25 14:48:27 UTC; 1min 26s ago
Cntrl PID: 1335258 (myapplication)
      Tasks: 5 (limit: 9505)
     Memory: 3.3M
        CPU: 1.447s
     CGroup: /system.slice/system-myapplication.slice/[email protected]
             |-1335258 /bin/bash /path/to/application/myapplication start p1
             |-1336794 sudo -u admin -i python /path/to/application/myapplication.py start p1
             |-1336795 logger
             |-1336802 -bash --login -c python \/path\/to\/application/myapplication\.py start p1
             `-1336998 sleep 30



* myapplication.service - my application service for p1.
     Loaded: loaded (/lib/systemd/system/[email protected]; enabled; vendor preset: enabled)
     Active: active (running) since Fri 2022-03-25 14:49:58 UTC; 25s ago
    Process: 1337069 ExecStart=/path/to/application/myapplication start (code=exited, status=0/SUCCESS)
   Main PID: 1337603 (python)
      Tasks: 6 (limit: 9505)
     Memory: 7.2M
        CPU: 1.541s
     CGroup: /system.slice/system-myapplication.slice/[email protected]
             |-1337603 python /path/to/application/myapplication.py start p1
             |-1337659 /bin/sh -c sudo timeout 15 sudo tcpdump -n -i lo udp port 1234 2> /tmp/capture.txt > /dev/null
             |-1337660 sudo timeout 15 sudo tcpdump -n -i lo udp port 1234
             |-1337662 timeout 15 sudo tcpdump -n -i lo udp port 1234
             |-1337663 sudo tcpdump -n -i lo udp port 6343
             `-1337664 tcpdump -n -i lo udp port 6343

我的单元文件没有任何重启延迟

[Unit]
Description=my application service for %i.

[Service]
Type=forking
ExecStart=/path/to/application/myapplication start
ExecStop=/path/to/application/myapplication stop
ExecReload=/path/to/application/myapplication restart
Restart=always

[Install]
WantedBy=multi-user.target

为什么会出现这种延迟,因为它不是定期发生的,有时会发生,有时不会?为什么睡眠的 PID 会改变?最初的想法是,这是尝试重新启动后的新睡眠,但查看输出,status没有重新启动,Active: activating (start) ...时间保持不变,直到服务重新启动。


我现在已经做了一些操作,我认为这可能是因为当我将它分离出来时,我将kill命令作为单行运行kill -9 <p1-PID> <p2-PID> <p3-PID>

kill -9 <p1-PID>
kill -9 <p2-PID>
kill -9 <p3-PID>

我不会为了服务而睡 30 个小时。仍然需要更多的测试来确定,但现在看起来就是这样。

但我还是很好奇为什么sleep 30会出现?

答案1

您的服务包含Type=forking.这意味着你的单位期望你的ExecStart=命令fork()然后退出。activating (start)只要该服务ExecStart=仍在运行,就会一直存在。当ExecStart=结束时,systemd将选择一个衍生进程(MainPID)并进入该active (running)状态。

您的ExecStart=程序似乎是一个 bash 脚本。这个脚本可能看起来像这样:

#!/bin/bash
sudo -u admin -i python /path/to/application/myapplication.py start p1 | logger &

while /bin/true; do
    sleep 30
done

该脚本有一些问题,但您应该感兴趣的部分是sleep 30最后的部分。您的主进程正在运行,但 systemdactive (running)在完成之前不会进入该状态sleep 30。您每次都会看到一个新的 PID,因为新的 PIDsleep 30不断被调用。

一个表现良好的脚本会创建您的应用程序,然后立即退出。您的脚本可能正在等待应用程序在退出之前已正确启动的反馈,这很好,但它显然没有得到它正在等待的反馈,因此您需要更深入地挖掘以找出原因不是。

但是,我认为您的脚本更有可能在退出之前等待您的应用程序退出。像这样的东西:

python myapplication.py &
PID=$!

while ps | grep -q $PID; do
    sleep 30
done

我认为这是因为听起来像是你在killing python,而不是ExecStart=剧本。这意味着该装置将一直保留到完成activating (start)为止sleep 30。然后它会检查你的 python 应用程序的 PID 是否仍然存在(不是),然后你的脚本才会停止。

该脚本的另一部分让我困扰的是sudo. sudo旨在验证交互式用户。它并不是为了验证脚本。相反,更优雅的解决方案是User=admin在您的服务中使用。

我看到两个解决方案。选项 2 是迄今为止我最喜欢的:

  1. 编辑/path/to/application/myapplication并删除该while循环。
  2. 使用简单的服务并完全跳过该脚本。看起来它是为另一个 init 系统编写的(它显式启动自己的记录器,现在不需要),然后修改为在 shell 中调用时阻止。 systemd为您完成所有这些工作,所以我敢打赌根本不需要该脚本。
[Unit]
Description=my application service for %i.

[Service]
Type=simple
ExecStart=/usr/bin/python3 /path/to/application/myapplication.py %i
User=admin
Restart=always

[Install]
WantedBy=multi-user.target

如果这没有帮助,请发布内容/path/to/application/myapplication

相关内容