16
49 18 * * * mpv ~/Musik/Donau.mp3

This command would play the Donau.mp3 file at exactly 6:49pm. How could I, for example, specify 6:49:50pm?

7
  • What the traditional cron does is to wake up every minute and check if there is something to be done.
    – fraxinus
    May 4 at 9:32
  • 4
    As a simple workaround you can start a shell script with cron, which will get the current time and sleep an appropriate time of seconds before starting the program. like sleep $(($(date -d "18:49:50" +%s) - $(date +%s))) && mpv ...
    – Falco
    May 4 at 15:17
  • How do you play a song from cron? The user might not even be logged in...
    – RonJohn
    May 5 at 5:42
  • 1
    @RonJohn what's special about playing a song, compared to running any other program?
    – njzk2
    May 5 at 21:25
  • @njzk2 the music needs somewhere to go. Isn't that only controlled by "desktop" processes?
    – RonJohn
    May 6 at 4:50

2 Answers 2

23

Using systemd timer: https://wiki.archlinux.org/title/Systemd/Timers

You can specify seconds as well:

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

Or like this, 'hacking' crontab:

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

Don't expect this latter solution to be precise due to how cron works.

3
  • 4
    Based on how cron work you can't be sure the 49 18 will run at 18:49:00. But the idea is interesting :) May 3 at 19:44
  • Added systemd way May 3 at 19:58
  • 3
    @RomeoNinov Nor can you be sure it will sleep for 50 seconds based on how sleep works ;-)
    – Abigail
    May 5 at 23:24
7

This command would play the "Donau.mp3" file at exactly 6:49pm.

Not exactly 6:49pm, precisely 6:49pm. This is an important distinction that actually partly explains why most cron implementations can’t do what you want.

At a high level, what crond actually does is sleep for approximately 60 seconds, then check what jobs need run and fire those off, then sleep again for approximately 60 seconds minus the amount of time it took to check and start jobs this cycle.

However, none of the mechanisms used for suspending a process for some amount of time on UNIX-like systems allow for an exact wakeup time. They only let you specify a lower bound on the wakeup time. For example, in C code, sleep(10); will sleep for at least 10 seconds, but may sleep for longer than that (actually, it will almost always sleep at least one scheduling quanta longer than that). Usually the discrepancy is less than 200ms, but it’s entirely possible for it to be significantly longer if the system is heavily loaded or the process being woken up is exceptionally low priority.

For the usual case for crond of sleeping for 60 seconds, jitter of even a few seconds is generally insignificant, because it can just adjust how long it sleeps on the next cycle to compensate. If, however, it was trying to run things every second instead, jitter of more than about half a second would be enough to cause reliability issues and possibly miss events.

This then brings up the question of why systemd lets you specify timestamps down to the second for timer units. The reality is that it doesn’t actually schedule to that precision either. Systemd offers per-second resolution because it operates in a fundamentally different way from crond, instead of checking every cycle for jobs that need to run, systemd sets timers to be woken up when a job needs to run. On an idealized system with minimal timing jitter, this enables it to actually trigger things with that level of precision. In practice though, it’s not unusual on a busy system for timer units scheduled with that precision to be a second or two late.

How could i (for example) specify 6:49'50pm?

If you truly need that level of precision, the correct answer is to use a realtime OS for whatever you’re doing, not a time-sharing OS.

You can get close to this on a Linux system by running crond with a realtime scheduling priority, but doing so safely requires a significant amount of effort to ensure that the jobs don’t inherit that priority (which would run a nontrivial risk of them causing problems for anything else running on the system), but that still won’t let you pick exact times down to the second to run jobs at.

5
  • Where exactly is the difference between 'realtime OS' and 'time-sharing OS'? May 4 at 12:03
  • 1s precision should be easy with a standard OS that's not working too hard. It's just cron that isn't built for this. It's certainly possible using a Python script (and nothing else except background tasks) under Debian on a Raspberry Pi 3. You can actually go far better. For human interaction 100ms is effectively the precision limit you need - easily doable. Pushing it further still, audio, it makes little sense to even define time increments less than about 100µs. Testing down to that level on a Pi3's GPIO showed jitter in increments of ~10µs (still better than a Win7 desktop)
    – Chris H
    May 4 at 13:18
  • 2
    @PeterAndres A realtime OS is specialized for running things at specified times. For some reason people† tend to get excited if your ABS Controller doesn't respond to the next interrupt from the brake rotation sensor. († people like regulators and lawyers.) May 4 at 15:16
  • @PeterAndres a realtime OS (such as QNX) guarantees that tasks are started at specific times and will never exceed a specific execution time (which does require that execution time to be feasible for that task though, so as a task definer / developer, you have responsibility as well). This can be important for safety-critical (control) systems. For example, ESP, ABS, and automated braking in cars (if those run on an OS rather than dedicated microcontrollers). "Normal" OSes, such as regular Windows, Linux, and macOS, don't give such guarantees
    – tjalling
    May 5 at 12:44
  • ... which is often better for regular usage (i.e. anything that's not safety-critical). For example, if you'd use a realtime OS and there was a task running with realtime priority and that task got so expensive that it would take up (almost) all execution time, your keyboard and mouse input will for example not be handled (assuming they have lower, non-realtime) priority, so you could no longer interact with the system. Similarly, non-realtime cron jobs would no longer be started, etc.
    – tjalling
    May 5 at 12:47

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .