【问题标题】:What is stalling my systemd user timer?是什么让我的 systemd 用户计时器停滞不前?
【发布时间】:2016-05-25 01:31:07
【问题描述】:

我使用 systemd 用户计时器作为 cron 替代品。我有一个特定的程序设置为每 20 分钟执行一次。该程序不是守护进程,它依赖于网络,并启动了许多子进程。然而,我注意到计时器经常在几个小时(或几天)后停止。计时器仍处于活动状态,但程序不再每 20 分钟执行一次。 pgrep 显示许多进程仍处于活动状态。观察到这一点后,我在 .service 文件中添加了JobTimeoutSec=3m,希望进程超时会被杀死。

systemctl status --user PROGRAM.service 现在输出以下内容,但是子进程仍在运行,计时器不再每 20 分钟执行一次程序:

2 月 13 日 15:03:45 HOSTNAME systemd[1878]:作业 PROGRAM.service/start 超时。

2 月 13 日 15:03:45 HOSTNAME systemd[1878]:启动说明超时。

2 月 13 日 15:03:45 HOSTNAME systemd[1878]:作业 PROGRAM.service/start 失败,结果为“超时”。

我猜该程序的子进程由于网络问题而停止,并且 systemd 在超时时无法杀死它们。

有任何解决此问题的建议,以便计时器按预期继续运行吗?

ExecStart=/usr/bin/timeout 20m /path/to/program 替换ExecStart=/path/to/program 似乎可以解决这个问题,但我想知道为什么单独使用systemd 不能解决这个问题。


调试信息

PROGRAM.service

[Unit]
Description=DESCRIPTION
After=network.target
PartOf=network-online.target
JobTimeoutSec=3m

[Service]
Type=oneshot
ExecStart=/path/to/program

[Install]
WantedBy=network-online.target

PROGRAM.timer

[Unit]
Description=Run PROGRAM.service every 20 minutes

[Timer]
OnCalendar=*:0/20

[Install]
WantedBy=timers.target

systemd --version 输出以下内容:

系统 219

+PAM +AUDIT +SELINUX +IMA +APPARMOR +SMACK +SYSVINIT +UTMP +LIBCRYPTSETUP +GCRYPT -GNUTLS +ACL +XZ -LZ4 -SECCOMP +BLKID -ELFUTILS +KMOD -IDN

【问题讨论】:

标签: linux systemd


【解决方案1】:

活动进程

systemd 中有两个重要的东西,我认为你在这种情况下会遇到:

  1. 当您使用systemd 启动进程时,所有子进程(至少默认情况下)都属于同一组。

  2. 如果其中任何一个孩子没有死亡,则认为该进程仍在(至少在某种程度上)运行。

这是什么意思?

timer description 说:

请注意,如果要激活的单元在计时器结束时已经处于活动状态,则不会重新启动,而只是保持运行状态。

换句话说,如果你的任何一个进程在 20 分钟后仍在运行,计时器系统将不会重新启动任何东西。

为什么这有意义?!

CRON 也在做同样的事情。如果您的进程仍在运行,它不会一遍又一遍地重新启动它(因为这只会填满内存并可能破坏许多其他事情。)但是,CRON 没有进程组的概念。因此,如果您的主进程确实死了,它假定它可以重新启动它。

systemd 解决方案是什么?

假设您不能只停止子进程(尽管由于您使用了/usr/bin/timedout,您可能可以?),一种方法是使用KillMode 选项,尽管我不推荐它:

KillMode=process

这意味着一旦主进程死亡,就认为服务停止了。

如果设置为进程,则只有主进程本身被杀死。

您可能想测试这是否真的有效,因为根据文档,它并没有说它会认为整个小组都死了......但根据我的经验,这是有效的。

那么有什么更好的解决方案?

既然我不推荐KillMode,应该还有别的解决办法。事实是,您的所有进程要么有 20 分钟的运行时间(或者在它们产生时剩余的任何时间),要么它们会阻止下一次运行的发生,这可能偶尔可以,但如果他们永远留在身边。因此,需要编辑这些进程并确保它们在一段时间后退出。

然而,在长时间之后,可能有必要杀死这些进程,如果进程本身不能退出,那么使用超时工具可能是最好的解决方案准时。虽然我会建议一个小的修改,即使用 19 分钟。超时,否则您可能会错过下一个启动窗口。

ExecStart=/usr/bin/timeout 19m /path/to/program

【讨论】:

    猜你喜欢
    • 2021-11-07
    • 1970-01-01
    • 1970-01-01
    • 2013-05-08
    • 2013-07-05
    • 2014-04-05
    • 2011-11-24
    • 2018-06-22
    • 2016-05-13
    相关资源
    最近更新 更多