May 17, 2015

Scheduling jobs with at and sched

I like to let large downloads run at night. “Easy, use the Unix at command”, you say. Unfortunately the at command has been horribly mangled in OSX Yosemite 10.10.3, but it can be made to behave itself. You will have to be able to run it as su, or using sudo, but here we go…

Enabling at, by enabling atrun

at on OSX depends on atrun, which is not enabled by default. From the at man page:

Note that at is implemented through the launchd(8) daemon periodically invoking atrun(8), which is disabled by default. See atrun(8) for information about enabling atrun.

So the first thing you will have to do is:

launchctl load -w /System/Library/LaunchDaemons/com.apple.atrun.plist

(See man atrun for more details.)

At needs sudo

If you try to just schedule a job without sudo, or being the su, it will complain that it is unable to regain privileges. So the format is thus:

sudo at HHMM

(you can also use HH:MM, if you please, check man at for the permutations.)

This will open a blank line on your terminal, at which you can enter:

sudo -u <username> curl -O http://foo.bar/baz.iso

then ^D to quit and save the job. If you want to save the output from the job, you can use:

sudo -u <username> curl -O http://foo.bar/baz.iso > /Users/username/at_output.txt 2>&1

The sudo in the job command won’t require a password, so the job will run unattended. Once you have a job or jobs set up you can run sudo atq to view the queued jobs and sudo atrm # to delete a specific job by number.

Using sched

If you’re fortunate, and clever, enough to be using the Z-shell, you can use zsh’s builtin sched command. Sched does not need superuser privileges. sched by itself lists queued jobs, while something like:

sched -o HH:MM curl -O http://foo.bar/baz.iso

will queue up a task. (Note the colon in the HH:MM, this is required.) The -o flag is recommended for jobs which will output information to the terminal; from the man page:

This (the -o flag) should be used with any scheduled event that produces visible output to the terminal; it is not needed, for example, with output that updates a terminal emulator’s title bar.

Running sched -# will remove a job. If I want a job to run overnight I just use something like sched 02:00, and sched will figure out that it’s the next 0200, not the previous one!

More detail can be found in the unreasonably large man zshall, search for ZSH/SCHED.