我想安排一个命令在特定时间运行,由 Unix 时间戳标识。看起来这可以通过 systemd 来实现systemd-run
,但是它是如何工作的呢?如果在调度命令时机器断电或暂停,那么调度的命令会发生什么情况?
at
相关问题:使用from做同样的事情atd
(需要将时间戳解析回日期):是否可以使用 at 命令安排作业在给定时间戳运行?
答案1
systemd-run
可以安排命令在特定时间运行,只要:
- 系统在此之前不会断电,因为它会将瞬态计时器和服务文件写入 /run,该文件在重新启动时会被清除,并且
- 系统在该特定时间内不会暂停,除非您使用“WakeSystem”选项(见下文)。
有关重新启动持久选项,请参阅下文。
一个简单的例子systemd-run
:
# generate an arbitrary timestamp, in seconds-since-the-epoch
timestamp=$(date -d 'now + 42 seconds' +%s)
systemd-run --on-calendar "$(date -d @"$timestamp" +'%F %T')" \
--timer-property=AccuracySec=1us \
touch /tmp/done
systemd-run
使用自纪元以来的秒数时间戳的重要部分是:
- 使用
--on-calendar
和 - 在这里,使用 GNU date 将纪元时间戳以来的秒数转换为
systemd-run
可以理解的格式。您可以自己输入或转换时间戳,只要结果在OnCalendar 可以理解的格式。
OnCalendar 的当前文档表明它直接支持自纪元时间戳以来的秒数输入。添加了“@秒”支持系统版本 234(在该页面中搜索该文件src/basic/calendarspec.c
)提交 d80e5b7。您的 systemd 版本可能早于此更改;举些例子:
- RHEL 7从systemd 208开始,后来升级到版本219; RHEL 8 使用版本 239 (参考)。
- Debian 8 使用版本 215,Debian 9 使用版本 232,Debian 10 使用版本 241(参考)。
- Ubuntu 16.04 LTS 的版本为 229,Ubuntu 17.10 的版本为 234,Ubuntu 18.04 LTS 的版本为 237(参考)。
使用足够新的 systemd 版本,您可以使用以下调用:
timestamp=$(date -d 'now + 42 seconds' +%s)
systemd-run --on-calendar "@${timestamp}" \
--timer-property=AccuracySec=1us \
touch /tmp/done
我还展示了一个AccuracySec 的计时器属性,默认为 1 分钟,您应该根据文档调整其值:
为了优化功耗,请确保将该值设置得尽可能高并根据需要设置得尽可能低。
我还没有测试过它,但还有一个名为的计时器选项WakeSystem
:
使系统从挂起状态恢复(如果系统处于挂起状态且系统支持此操作)。请注意,此选项仅确保系统在适当的时间恢复,而不会在任何要完成的工作完成后再次暂停系统。
您可以将其集成到上面,如下所示:
timestamp=$(date -d 'now + 42 seconds' +%s)
systemd-run --on-calendar "$(date -d @"$timestamp" +'%F %T')" \
--timer-property=AccuracySec=1us \
--timer-property=WakeSystem=true \
touch /tmp/done
要求 systemd 在某个时间运行一个命令,其方式重启后仍然存在,并且独立于任何特定的登录会话,您需要将计时器和服务单元文件放在/etc/systemd/system/
./etc/systemd/system 是存储本地配置的位置对于系统。
示例计时器文件如下:
[Timer]
AccuracySec=1us
[Unit]
Description=2020-01-22 09:50:00 timer
[Timer]
OnCalendar=2020-01-22 09:50:00
示例服务文件是:
[Unit]
Description=my 2020-01-22 09:50:00 service
[Service]
ExecStart=
ExecStart=@/usr/bin/bash "/usr/bin/bash" "-c" "echo 2020-01-22 09:50:00 timer and service ran > /tmp/done"
然后,您可以通过重新加载文件来通知 systemd 有关这些文件的信息:
systemctl daemon-reload
...然后启用计时器:
systemctl enable foo.timer
...然后启动计时器:
systemctl start foo.timer
一旦过期的计时器和服务单元的时间过去,您可能需要定期从 /etc/systemd/system 中删除它们。