scheduling tasks with at
In my next article i would like to get into at and batch. Instead of describing every available command line option and syntax there is, lets show some examples and nice ways to use both to schedule tasks from the command line.
There are a couple of commands which we are going to use in order the schedule the tasks, lets walk through all of them one at a time.
at
At alllows a fairly complex time format, but lets stick with the obvious format (at least which i find obvious).
$ at now + 5 minutes
now at will accept commands from standard input, you will get a shell like prompt where you can type in your commands.
at> date > /tmp/date
at>
Now press CTRL+D, after that you will be dropped back to the shell and at will report to you at which time the command will be executed.
at> <EOT>
job 9 at Mon Mar 25 10:43:00 2007
Here you see that the command will be executed at 10:43:00, now that’s a coincident, it look like we typed our at command exactly within the first second of the 38th minute.
Let’s double check if it really works like this.
$ echo 'echo "scheduling tasks in linux" > /tmp/banner.txt' > /tmp/schedule; \
date; \
at now + 1 minute -f /tmp/schedule
Mon Mar 26 10:49:54 CEST 2007
warning: commands will be executed using /bin/sh
job 12 at Mon Mar 26 10:50:00 2007
Here we use at a little different instead of letting at read our command from standard input, we use the -f command line option to let at read our command from a file. As you can see we create this file in the beginning then we print the date and then run at.
I’m consolidating this 3 separate commands on one line in order to be sure that the three almost happen instantly, so we don’t have much time skew here.
As you can see in the output we enter our at schedule at “10:49:54″ you might have expected the execution of the at schedule to run at “10:50:54″ since we did the “now + 1 minute”. However it runs the at schedule at “10:50:00″, so be aware that it will execute it at the full minute.
Also there is another thing to note in our output “warning: commands will be executed using /bin/sh”, what this means is that. When at invokes the commands in our at schedule it will spawn a new shell for this. So don’t expect to see output come bouncing back to your shell where you invoked the at schedule. However standard output and standard error will be e-mailed to shell user invoking the at schedule. These mail message will have a subject line like
Output from your job 42
In this case the mail body will contain the Output form at job 42.
Sometimes however you would also like to get notified if a job has run, when there is no output given you can do this with the -m parameter, e.g.
$ echo 'date > /dev/null' > /tmp/jobs
$ at 10pm tomorrow -f /tmp/jobs -m
Even though this job will not output anything, at least it will be redirected to /dev/null, it will e-mail you about it.
Also you can see an other time format “10pm tomorrow”. Tomorrow is a easy way of specifying that a task as to run tomorrow, instead of looking at the exact date. There is also “today” if you want to specify today.
Lets show some other time formats, they are actually really simple to memorize because the almost read like a normal sentence.
$ at march 29 2007 -f /tmp/jobs
We just tell it the month, day and year. If you specify it like this, the task will be executed on march 29 2007 and at the hour and minute you run at. If you want a different time you can specify this as well.
$ at 6pm january 1 2008 -f /tmp/jobs
There is also a syntax which i use pretty often and that i using offsets. So let’s say you started a benchmark today and what to run it for a week you could do something like
$ at 4pm + 7 days -f /tmp/stop-benchmark
This will run the commands in /tmp/stop-benchmark, however you can even write this much better.
$ at 4pm + 1 week -f /tmp/stop-bencmark
atq
Okay now we have a tasks scheduled, now how do we see which tasks are actually scheduled? The atq command lists all the pending scheduled tasks. You could also use “at -l” to see the same results. Lets see it in action.
$ atq
25 Mon Mar 26 23:05:00 2007 a steven
26 Mon Apr 2 18:00:00 2007 a steven
Here we see i’ve got two scheduled tasks pending, the first scheduled for March 26 at 23:05 and the later on April 2 at 18:00. Now i can’t even remember what the first task was, so lets look at what it actually does.
$ at -c 25
#!/bin/sh
# atrun uid=1000 gid=1000
# mail steven 0
umask 22
USER=steven; export USER
MAIL=/var/mail/steven; export MAIL
PATH=/usr/sbin:/usr/bin:/sbin:/bin:export PATH
PWD=/home/steven; export PWD
LANG=en_US.UTF-8; export LANG
HISTCONTROL=ignoredups; export HISTCONTROL
SHLVL=1; export SHLVL
HOME=/home/steven; export HOME
LOGNAME=steven; export LOGNAME
cd /home/steven || {
echo 'Execution directory inaccessible' >&2
exit 1
}
date > /dev/null
Here you can see that at records all the SHELL ENVIRONMENT variables at the time when at was invoked. So you can set environment variables when invoking at and it will record them so they are still available when the job start running.
atrm
All the way at the bottom of the previous output we see the actual command “date > /dev/null”. This was just a bogus job, since i used it only to test out some stuff. Lets remove it right away
$ atrm 25
And it should be gone, lets verify
$ atq
26 Mon Apr 2 18:00:00 2007 a steven
Yep job 25 is gone.
batch
Lets say we need to run some maintenance scripts todo some house keeping, but currently the system is under high load, so we don’t want to stress the server out even more with our maintenance jobs. We can however schedule this commands to be run whenever the load average drops below 1.5.
$ batch
warning: commands will be executed using /bin/sh
at> updatedb
at> /usr/local/sbin/clean-database.rb
at> <EOT>
job 32 at Mon Mar 26 14:02:00 2007
This 1.5 is the compiled in value, and you can change this value with the -l paramater of atd. You might want to change this value if you are in SMP environment.
Let’s look at the pending jobs.
$ atq
32 Mon Mar 26 14:02:00 2007 b steven
26 Mon Apr 2 18:00:00 2007 a steven
There we see it, job number 32, notice that there is a “b” instead of a “a”, this column specifies in which Queue the job is. Queue a is the default queue “at” and Queue b is the default queue for “batch”.
There is also a special Queue called “=” this is queue is reserved for jobs which are currently running.
$ at now + 1 minute
warning: commands will be executed using /bin/sh
at> sleep 300
at> <EOT>
job 33 at Mon Mar 26 14:08:00 2007
Now if we wait a little and check the running queue we can see it running.
$ atq
32 Mon Mar 26 14:02:00 2007 b steven
26 Mon Apr 2 18:00:00 2007 a steven
33 Mon Mar 26 14:08:00 2007 = steven
That’s about it. There are some more advantaged features however these are the once i use the most and which seems to be the most practical once.

