Anacron 杀死了我任务的孩子

Anacron 杀死了我任务的孩子

我想设置一个每天anacron运行一次备份的任务(Ubuntu 20.04.3 LTS)。backintime如果您使用backintimeGUI 来安排此操作,则会使用普通的 crontab,但对于我的用例来说,这不合适:我通常在不使用计算机时让计算机处于待机状态,因此如果我不使用,则 cronjob 将被丢弃没有让计算机在确切的预定时间运行。相反,我所做的是在cron.daily目录中创建一个脚本,这样就anacron可以处理它,它还支持在待机或计算机关闭一段时间的情况下延迟执行。我添加了以下命令:

sudo -i -u samuel /usr/bin/nice -n19 /usr/bin/ionice -c2 -n7 /usr/bin/backintime backup-job >/dev/null

这正是backintime添加到 crontab 中的内容,所以我确信它在使用时会工作得很好anacron。但事实并非如此:作业开始得很好,但备份永远不会完成。系统日志输出如下:

backintime (samuel/1): INFO: Lock
backintime (samuel/1): WARNING: Inhibit Suspend failed.
backintime (samuel/1): INFO: mount ssh: [...]
backintime (samuel/1): INFO: Take a new snapshot. Profile: 1 Main profile
backintime (samuel/1): INFO: Call rsync to take the snapshot

[... around 10 seconds later ...]

anacron[1082]: Job `cron.daily' terminated (mailing output)
anacron[1082]: anacron: Can't find sendmail at /usr/sbin/sendmail, not mailing output
anacron[1082]: Can't find sendmail at /usr/sbin/sendmail, not mailing output
systemd[1]: anacron.service: Killing process 7920 (python3) with signal SIGKILL.
anacron[1082]: Normal exit (1 job run)
systemd[1]: anacron.service: Killing process 7958 (ssh-agent) with signal SIGKILL.
systemd[1]: anacron.service: Killing process 8107 (ssh) with signal SIGKILL.
systemd[1]: anacron.service: Killing process 8109 (sshfs) with signal SIGKILL.
systemd[1]: anacron.service: Killing process 8112 (python3) with signal SIGKILL.
systemd[1]: anacron.service: Killing process 8126 (rsync) with signal SIGKILL.
systemd[1]: anacron.service: Killing process 8127 (ssh) with signal SIGKILL.
systemd[1]: anacron.service: Killing process 8123 (QXcbEventQueue) with signal SIGKILL.
systemd[1]: anacron.service: Succeeded.

我觉得这种情况很奇怪,因为为什么 anacron 会故意杀死我的进程呢?所以,据我解释,我在备份脚本中执行的命令很快就会退出,因为它唯一的任务是分离一些工作进程,如 python、ssh、rsync 等,一旦它们“退出”重新在后台运行,启动器退出。到目前为止一切顺利,但anacron显然认为一旦脚本完成,就有责任杀死原始备份脚本的所有后代。但我怎样才能阻止它这样做呢?我是否真的需要在退出备份脚本之前手动查找后代 PID 并等待所有这些 PID 完成?

我在网上没有找到有关此行为的任何信息,因此如果有人对如何在此进行操作有任何建议,我将很高兴。

答案1

编辑:下面的解决方法并不是 100% 有效,所以我再次挖掘并发现根本原因不是 anacron 本身,而是它的 systemd 配置:显然 systemd 单元可以指定一个杀戮模式用于在主进程完成后清理任何生成的子进程。 Anacron 将此设置为“混合”,并将其更改为“无”成功允许我的备份任务在后台运行。请注意,对于其他类型的 anacron 任务,禁用子进程的终止可能并不理想,但对于我的用例来说,这正是我所需要的。

可以通过sudo systemctl edit anacron.service输入以下配置来更改终止模式:

[Service]
KillMode=none

--

我将保留之前的解决方法以供参考:

对于这种情况,我找到了一个或多或少可靠的解决方法:在我的具体情况下,backintime通过 SSH 进行远程备份。这是通过启动一个sshfs进程来完成的,该进程负责安装备份位置并在备份完成后退出。因此,脚本可以等待该进程再次启动和完成,以便知道备份何时完成:

sudo -i -u samuel /usr/bin/nice -n19 /usr/bin/ionice -c2 -n7 /usr/bin/backintime backup-job >/dev/null

echo "Waiting for SSHFS to start"
until pids=$(pidof sshfs)
do
    sleep 1
done

echo "Waiting for backup to finish (SSHFS [$pids] to exit)"
while ps -p "$pids" >/dev/null 2>&1
do
    sleep 5
done

echo "SSHFS process gone, exiting"

这可能不是最优雅的解决方案,但至少效果很好。

答案2

让进程在后台运行并且不修改 anacron 或其他服务单元的方法是使用systemd-run实​​用程序。默认情况下,它在干净且分离的执行环境中以 ppid=1 和简单服务类型运行新的 .service 单元中的程序。

在您的情况下,backintime创建子进程然后退出,因此您应该指定--service-type=forking或使用--scope-r选项。有关这些方法之间差异的更多详细信息,请参阅 systemd-run 和 systemd.service 手册。

相关内容