我可以使用 Linux crontab 以秒为单位指定特定时间吗?

我可以使用 Linux crontab 以秒为单位指定特定时间吗?
49 18 * * * mpv ~/Musik/Donau.mp3

此命令将Donau.mp3在下午 6:49 分准确播放文件。例如,我该如何指定下午 6:49:50?

答案1

使用systemd计时器:https://wiki.archlinux.org/title/Systemd/Timers

您也可以指定秒数:

OnCalendar=Mon,Tue *-*-01..04 18:49:50

或者像这样,“黑客攻击” crontab

49 18 * * * sleep 50; mpv ~/Musik/Donau.mp3

不要指望后一种解决方案是精确的由于如何cron工作。

答案2

该命令将在下午 6:49 准时播放“Donau.mp3”文件。

不是确切地下午6:49,恰恰下午 6:49。这是一个重要的区别,实际上它部分解释了为什么大多数 cron 实现不能满足您的要求。

从高层次上讲,crond 实际上所做的是睡眠大约 60 秒,然后检查需要运行哪些作业并启动它们,然后再次睡眠大约 60 秒减去此周期检查和启动作业所花费的时间。

然而,在类 UNIX 系统中,用于暂停进程一段时间的机制都不允许精确的唤醒时间。它们只允许您指定唤醒时间的下限。例如,在 C 代码中,sleep(10);将休眠至少10 秒,但可能休眠更长时间(实际上,它几乎总是会休眠至少一个调度量程)。通常差异小于 200 毫秒,但如果系统负载很重或被唤醒的进程优先级极低,则差异完全有可能显著延长。

对于通常的 crond 休眠 60 秒的情况,即使几秒钟的抖动通常也是微不足道的,因为它只需调整下一个周期的休眠时间即可进行补偿。但是,如果它尝试每秒运行一次,那么超过半秒的抖动就足以导致可靠性问题,并可能错过事件。

这就引出了一个问题:为什么 systemd 允许你为计时器单位指定精确到秒的时间戳。事实是它实际上也没有达到那么高的精度。Systemd 提供每秒精度,因为它的运行方式与 crond 完全不同,它不是在每个周期检查需要运行的作业,而是在作业需要运行时设置唤醒定时器。在具有最小时间抖动的理想系统上,这使它能够以这种精度触发事件。但在实践中,在繁忙的系统中,以这种精度安排的定时器单元延迟一两秒并不罕见。

我怎样才能(例如)指定下午 6:49'50?

如果你确实需要这种级别的精度,那么正确的答案就是无论做什么都使用实时操作系统,而不是分时操作系统。

你可以得到关闭在 Linux 系统上通过运行具有实时调度优先级的 crond 来实现这一点,但要安全地做到这一点需要付出大量的努力来确保作业不会继承该优先级(这会带来很大的风险,可能会导致系统上运行的任何其他程序出现问题),但这仍然不允许您选择精确到秒的时间来运行作业。

相关内容