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?

chicks
  • 556
  • 4
  • 14
Peter Andres
  • 196
  • 1
  • 9
  • What the traditional cron does is to wake up every minute and check if there is something to be done. – fraxinus May 04 '23 at 09: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 04 '23 at 15:17
  • How do you play a song from cron? The user might not even be logged in... – RonJohn May 05 '23 at 05:42
  • 1
    @RonJohn what's special about playing a song, compared to running any other program? – njzk2 May 05 '23 at 21:25
  • @njzk2 the music needs somewhere to go. Isn't that only controlled by "desktop" processes? – RonJohn May 06 '23 at 04:50
  • @RonJohn that would probably be the case for a process that has a graphic output, but for sound, there are music daemons that can access sound peripherals (e.g.: https://www.musicpd.org/) – njzk2 May 06 '23 at 10:14
  • @njzk2 interesting. The musicpd site didn't mention mpv, though, and (cursorily) reading the mpv page didn't seem to mention needing a daemon. It seems to work, though... – RonJohn May 06 '23 at 13:50

2 Answers2

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.

Gilles Quénot
  • 4,226
  • 1
  • 27
  • 28
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.

Austin Hemmelgarn
  • 8,960
  • 1
  • 19
  • 32
  • Where exactly is the difference between 'realtime OS' and 'time-sharing OS'? – Peter Andres May 04 '23 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 04 '23 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.) – Martin Bonner supports Monica May 04 '23 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 05 '23 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 05 '23 at 12:47