Schedule a one-time task at a specific time or below defined system load using at utility.
Install the required software
This utility should be available by default, but if it isn’t, use the following command to install it.
$ sudo apt-get install at
Define users that are allowed to submit jobs
Use /etc/at.allow
or /etc/at.deny
file to allow or deny users to execute this utility.
The root with uid = 0
is above these rules and can always execute at utility.
If the /etc/at.allow
file exists, then it is used to define users that are allowed to execute at utility.
If the /etc/at.allow
does not exist, then /etc/at.deny
file is used to define users who cannot execute at utility.
Look at the following application’s source code if you have any doubts.
/* Global functions */ int check_permission() { uid_t uid = geteuid(); struct passwd *pentry; int allow = 0, deny = 1; if (uid == 0) return 1; if ((pentry = getpwuid(uid)) == NULL) { perror("Cannot access user database"); exit(EXIT_FAILURE); } allow = user_in_file(ETCDIR "/at.allow", pentry->pw_name); if (allow==0 || allow==1) return allow; /* There was an error while looking for pw_name in at.allow. * Check at.deny only when at.allow doesn't exist. */ deny = user_in_file(ETCDIR "/at.deny", pentry->pw_name); return deny == 0; }
Schedule one-time jobs at a specific time
Schedule commands to execute now.
$ at now
warning: commands will be executed using /bin/sh at> some | commands at> <EOT> job 30 at Wed Nov 15 9:53:00 2017
Schedule commands to run after two hours and do not send mail to the user.
$ at -M now + 2 hours
warning: commands will be executed using /bin/sh at> some | commands at> <EOT> job 26 at Wed Nov 15 11:54:00 2017
Schedule commands to execute at 14:00 on December 16, 2018, send mail to the user even if there was no output.
$ at -m 14:00 16.12.2018
warning: commands will be executed using /bin/sh at> some | commands at> <EOT> job 27 at Sun Dec 16 14:00:00 2018
You can specify the date using any from the following format: MMDD[CC]YY
, MM/DD/[CC]YY
, DD.MM.[CC]YY
or [CC]YY-MM-DD
.
Schedule /opt/bin/reminder.sh
shell script to execute tomorrow at 13:30.
$ at -f /opt/bin/reminder.sh 13:30 tomorrow
warning: commands will be executed using /bin/sh
job 29 at Thu Nov 16 13:30:00 2017
Use the -v
option to display the time the job will be executed before defining it.
$ at -v now + 4 hours
Wed Nov 15 13:55:00 2017 warning: commands will be executed using /bin/sh at> some | commands at> <EOT> job 30 at Wed Nov 15 13:55:00 2017
There are more possibilities as there are many time modifiers available.
now { COPY_TOK ; return NOW; } am { COPY_TOK ; return AM; } pm { COPY_TOK ; return PM; } noon { COPY_TOK ; return NOON; } midnight { COPY_TOK ; return MIDNIGHT; } teatime { COPY_TOK ; return TEATIME; } sun(day)? { COPY_TOK ; return SUN; } mon(day)? { COPY_TOK ; return MON; } tue(sday)? { COPY_TOK ; return TUE; } wed(nesday)? { COPY_TOK ; return WED; } thu(rsday)? { COPY_TOK ; return THU; } fri(day)? { COPY_TOK ; return FRI; } sat(urday)? { COPY_TOK ; return SAT; } today { COPY_TOK ; return TODAY; } tomorrow { COPY_TOK ; return TOMORROW; } next { COPY_TOK ; return NEXT; } min { COPY_TOK ; return MINUTE; } minute(s)? { COPY_TOK ; return MINUTE; } hour(s)? { COPY_TOK ; return HOUR; } day(s)? { COPY_TOK ; return DAY; } week(s)? { COPY_TOK ; return WEEK; } month(s)? { COPY_TOK ; return MONTH; } year(s)? { COPY_TOK ; return YEAR; } jan(uary)? { COPY_TOK ; return JAN; } feb(ruary)? { COPY_TOK ; return FEB; } mar(ch)? { COPY_TOK ; return MAR; } apr(il)? { COPY_TOK ; return APR; } may { COPY_TOK ; return MAY; } jun(e)? { COPY_TOK ; return JUN; } jul(y)? { COPY_TOK ; return JUL; } aug(ust)? { COPY_TOK ; return AUG; } sep(tember)? { COPY_TOK ; return SEP; } oct(ober)? { COPY_TOK ; return OCT; } nov(ember)? { COPY_TOK ; return NOV; } dec(ember)? { COPY_TOK ; return DEC; } utc { COPY_TOK ; return UTC; } [0-9]{1} { COPY_TOK ; COPY_VAL; return INT1DIGIT; } [0-9]{2} { COPY_TOK ; COPY_VAL; return INT2DIGIT; } [0-9]{4} { COPY_TOK ; COPY_VAL; return INT4DIGIT; } [0-9]{5,8} { COPY_TOK ; COPY_VAL; return INT5_8DIGIT; } [0-9]+ { COPY_TOK ; COPY_VAL; return INT; } [0-9]{1,2}\.[0-9]{1,2}\.[0-9]{2}([0-9]{2})? { COPY_TOK ; COPY_VAL; return DOTTEDDATE; } [0-9]{2}([0-9]{2})?-[0-9]{1,2}-[0-9]{1,2} { COPY_TOK ; COPY_VAL; return HYPHENDATE; } [012]?[0-9][:'h,.][0-9]{2} { COPY_TOK ; COPY_VAL; return HOURMIN; }
You can read /usr/share/doc/at/timespec
for more information.
Schedule a one-time task when the system goes below specific load average
Schedule commands to execute when the load average drops below 1.5.
$ at -b
at> some | commands at> <EOT> job 31 at Wed Nov 15 09:55:56 2017
You can alter the default value of the load average used to determine when the system load level is low enough to execute commands. To achieve this, modify the daemon’s startup parameters.
Queues
By default, jobs are assigned to a
queue and batch jobs to b
queue.
You can assign custom queues from a
to z
and from A
to Z
. Jobs in uppercase queues are treated as batch jobs at the specified time.
$ at -q F teatime
warning: commands will be executed using /bin/sh at> some | commands at> <EOT> job 32 at Wed Nov 15 16:00:00 2017
Get job details
List scheduled jobs.
$ at -l
29 Thu Nov 16 13:30:00 2017 a root 30 Wed Nov 15 13:55:00 2017 a root 26 Wed Nov 15 11:54:00 2017 a root 27 Sun Dec 16 14:00:00 2018 a root 32 Wed Nov 15 16:00:00 2017 F root
Get details for the specific job.
$ at -c 30
#!/bin/sh # atrun uid=0 gid=0 # mail root 0 umask 22 LANG=C.UTF-8; export LANG container=lxc; export container USER=root; export USER PWD=/root; export PWD HOME=/root; export HOME SHLVL=1; export SHLVL PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin; export PATH cd /root || { echo 'Execution directory inaccessible' >&2 exit 1 } some | commands
Remove jobs
Remove scheduled job.
$ at -r 9
System service
Service is configured using a systemd service file.
$ cat /etc/systemd/system/multi-user.target.wants/atd.service
[Unit] Description=Deferred execution scheduler Documentation=man:atd(8) [Service] ExecStart=/usr/sbin/atd -f IgnoreSIGPIPE=false [Install] WantedBy=multi-user.target
Use -l
option to specify the load average threshold that was mentioned earlier.
ExecStart=/usr/sbin/atd -f -l 4
Reload systemd manager configuration.
$ sudo systemctl daemon-reload
Restart service to apply changes.
$ sudo systemctl restart atd