![概括](https://linux22.com/image/200696/%E6%A6%82%E6%8B%AC.png)
概括
禁用(“静态”)且仅应由计时器触发的 systemd 服务单元在每次重新启动时运行。
背景
这是一个服务单位(在/etc/systemd/system/
),之前有一个[Install]
部门并且是systemctl enable
d。
该[Install]
部分已被删除,服务已被禁用。该服务现在由计时器触发。计时器设置为每月运行一次并且是持久的,因此它会跟踪上次运行,并且不会在重新启动时触发,除非关闭时错过了运行。
systemctl --system daemon-reload
做出改变后我就跑了。
计时器工作正常并按预期触发服务。
问题
重新启动时,服务单元始终运行,无论计时器上次运行如何,也无论计时器是否持久。我已经验证(通过systemctl list-timers
),它不是触发服务单元的计时器单元(除非list-timers
有关上次触发时间的输出是错误的)。
systemctl is-enabled <service-unit>
显示static
(又名禁用,[Install]
单元中没有部分)。
find /etc/systemd/system/*.wants -name <service-unit>
不显示先前安装/启用此服务时留下的任何已安装符号链接。
我怀疑以前安装此服务单元时存在一些“遗留”的东西,导致该服务在重新启动时启动,但不知道在哪里查找。
这是在 ubuntu 20.04 上(如果碰巧存在已知错误/问题)。
有没有办法调试 systemd 启动一个单元的原因? (例如,单元 X 启动是因为需要文件 Z 中的 Y)。
有没有办法仔细检查该服务确实不是由计时器启动的(而不是仅仅通过输出启动list-timers
)?
服务单位
# cat /etc/systemd/system/mysql_tzinfo.service
[Unit]
Description=mysql_tzinfo
Wants=mysql_tzinfo.timer
[Service]
Type=oneshot
Environment=
WorkingDirectory=/tmp
ExecStart=/bin/sh -c "/usr/bin/mysql_tzinfo_to_sql /usr/share/zoneinfo | /usr/bin/mysql --user=root mysql"
User=root
Group=root
定时器单元
# cat /etc/systemd/system/mysql_tzinfo.timer
[Unit]
Description=Timer for mysql_tzinfo.service
Requires=mysql_tzinfo.service
[Timer]
Unit=mysql_tzinfo.service
OnCalendar=*-*-05 04:00:00
AccuracySec=30s
Persistent=true
[Install]
WantedBy=timers.target
答案1
好吧,在写这篇文章的过程中,我注意到我的计时器单元部分Requires=mysql_tzinfo.service
中有一个。[Unit]
我想到启动时计时器的启动(由 systemd 进行依赖解析)可能会因此而启动服务Requires
。果然,从计时器中删除这一行并重新启动......服务不再启动。这就是我在关注“技术博客”时没有仔细检查每个配置选项所得到的结果。
对于尝试从 cron 迁移到 systemd 计时器的人来说,要点总结:
- 不要将一个
[Install]
部分添加到您的服务单元中,并且不要将您的服务单元添加systemctl enable
到您的服务单元中。 - 不要将 a 添加
Requires=<SERVICE_NAME>.service
到您的定时器单元。 - 如果您希望计时器记住它何时运行并在启动时运行错过的运行,请添加
Persistent=true
到您的计时器。 - 计时器在启动时运行得相当早,因此您应该
After=
向服务单元(您的计时器单元运行)添加必要的要求,以确保服务单元在所有必需的服务(网络、数据库等)都在线之前不会运行。否则很可能会失败。