VMware ESXi and vSphere Cluster Management
Schedule One-Time Jobs with the Linux at Command
Learn how to schedule one-time Linux commands with at, use absolute and relative times, submit scripts, inspect queues, cancel jobs, and troubleshoot execution.
The Linux at command queues a command or group of commands for one execution at a future time. It is useful when a task should happen once rather than repeatedly.
This lesson assumes familiarity with shell commands, file paths, redirection, services, and basic permissions.
When to Use at
An at job is a queued one-time task. After it runs, it is removed from the pending queue. Common uses include:
- Running a delayed cleanup operation.
- Starting a script during a maintenance window.
- Deferring a backup, data export, or other administrative action.
- Sending a notification at a particular time.
cron is a separate scheduler intended primarily for recurring tasks, such as running a command every day or every five minutes. anacron also handles recurring jobs, with behavior intended for systems that may be powered off when a periodic job would normally run. systemd timers are another option, especially when a service needs systemd-specific dependencies and logging.
How at Works
The at command accepts a time specification, which tells it when to run. It then reads commands from standard input, known as stdin. The commands are stored as a queued job and later processed by atd.
atd is the daemon, or background service, that watches the queue and executes due jobs. The package and service names vary slightly by Linux distribution. The command may be provided by a package named at, and the service may be called atd or at.
Check the Scheduling Service
systemctl status atd
systemctl status at
Use the service name that exists on your distribution. On a systemd-based system, an administrator can enable and start the daemon with:
sudo systemctl enable --now atd
If that unit does not exist, try the distribution's alternative service name. If at is not installed, check for it with:
command -v at
Install the distribution's at package if the command is unavailable.
Basic Interactive Scheduling
The general form is:
at TIME_SPECIFICATION
Running this command opens an input prompt. Enter one or more shell commands, one command per line. Press Ctrl+D on an empty line to signal end-of-input. This saves the job and places it in the queue.
at now + 2 minutes
echo "scheduled test completed" >> /tmp/at-test.log
Ctrl+D
The terminal normally reports a job number and the time at which the job will run. The job number is its job ID, a numeric identifier used to inspect or remove it.
Absolute Time Specifications
An absolute time identifies a particular clock time and, optionally, a calendar date. A clock-only specification such as 18:20 schedules the job for that time according to the command's date parsing rules. The resulting moment must be in the future.
at 18:20 July 26 2030
/usr/local/bin/maintenance-task.sh >> /var/log/maintenance-task.log 2>&1
Ctrl+D
Writing the month name, day, and year makes the intended date clear. Check the accepted date syntax on the target system if a date is ambiguous, and make sure the system clock and time zone are correct.
Relative Time Specifications
A relative time expresses a delay from the current time. The common form is now + NUMBER UNIT.
at now + 2 minutes
at now + 1 hour
at now + 3 days
at now + 2 weeks
Relative scheduling is convenient for delayed commands and for testing the installation. Other useful expressions include:
Submit a Job Without the Interactive Prompt
Pipe a command into at when the job contains one line:
echo '/usr/bin/touch /tmp/at-ran' | at now + 5 minutes
The outer shell runs echo immediately and supplies its output as stdin to at. The command text produced by echo is saved for later execution.
Quoting and Expansion
Shell expansion can occur at submission time or execution time depending on how the command text is constructed. Single quotes prevent the current shell from expanding variables, command substitutions, and wildcard patterns while creating the queued input:
echo 'echo "started at $(date) for $USER"' | at now + 5 minutes
Here, the command substitution and variable expansion are part of the queued command and are evaluated when the job runs. With double quotes around the argument to the outer echo, those expansions would normally happen while submitting the job instead.
echo "echo \"submitted at $(date) for $USER\"" | at now + 5 minutes
Redirection and wildcard expansion also need attention. Protect command text from the submitting shell when it must be interpreted later, and quote paths containing spaces. Test complicated commands interactively before queueing them.
Submit Commands from a File
The -f option tells at to read job commands from a specified file:
at -f /path/to/commands.txt TIME_SPECIFICATION
For example, create a file containing multiple commands:
cat > /home/bob/at_example.txt
/usr/bin/find /home/bob/tmp -type f -delete
echo "cleanup completed: $(/usr/bin/date)" >> /home/bob/log.txt
Ctrl+D
at -f /home/bob/at_example.txt 18:37 July 26 2030
The content of the file is submitted into the queued job when the job is created. Deleting /home/bob/at_example.txt afterward does not necessarily prevent that queued job from running. However, scripts, data files, and executables referenced by those commands must still exist when the job executes.
Use absolute paths for scripts, executables, input files, and log files whenever possible:
/usr/local/bin/maintenance-task.sh >> /var/log/maintenance-task.log 2>&1
View Pending Jobs
Use atq to list pending jobs. at -l is commonly equivalent:
atq
at -l
Queue output usually includes the job ID, scheduled date and time, queue letter, and submitting user. The exact formatting varies by implementation.
Remove a Queued Job
First find the job ID with atq, then pass that number to atrm:
atq
atrm 3
The common equivalent is:
at -r 3
Only a job that has not started can be removed from the queue. Once execution has begun, cancellation requires managing the resulting process rather than removing the queued job.
Execution Environment and Output
A scheduled job runs without an interactive terminal. It may not have the same working directory, PATH, shell startup files, environment variables, terminal, or permissions that were present when the job was submitted.
- Use absolute paths such as
/usr/bin/dateand/usr/local/bin/backup.sh. - Use absolute paths for input and output files.
- Set required variables explicitly in the submitted commands.
- Select a shell explicitly when the job depends on shell-specific behavior.
SHELL=/bin/bash
PATH=/usr/local/bin:/usr/bin:/bin
/usr/local/bin/backup.sh >> /var/log/backup-at.log 2>&1
stdout is standard output and stderr is standard error. If output is not redirected, implementations may attempt to deliver it through local mail to the submitting user when a local mail system is available. Mail may not be configured, so redirect output deliberately when it matters.
echo '/usr/local/bin/backup.sh >> /var/log/backup-at.log 2>&1' | at now + 1 hour
The >> operator appends standard output to the log. The 2>&1 portion sends standard error to the same destination.
Permissions and Access Control
A user can generally view and remove that user's own jobs. Administrative privileges may be required to inspect or manage jobs belonging to other users.
On systems that use them, /etc/at.allow and /etc/at.deny control which users may submit at jobs. Their presence, precedence, and default behavior vary by distribution. An administrator can inspect the local policy with:
sudoedit /etc/at.allow
sudoedit /etc/at.deny
Permission problems can also come from the scheduled command itself. The user running the job must be able to execute the script and access its files and destination directories.
Safe Testing and Verification
Test with a harmless command before scheduling destructive maintenance:
at now + 2 minutes
echo "scheduled test completed" >> /tmp/at-test.log
Ctrl+D
Confirm that the job was queued:
atq
After the scheduled time, verify the result:
cat /tmp/at-test.log
A useful diagnostic job records the time and user:
echo 'date; id; echo "test complete"' | at now + 2 minutes
Use a test copy of a cleanup script before queueing commands that delete files, stop services, or modify production data.
Troubleshooting at Jobs
at Is Not Found
- Install the distribution's package that provides
at. - Check whether the command is available with
command -v at. - Confirm that the executable is in the current user's
PATH.
A Job Remains in atq but Does Not Run
- Check
systemctl status atdor the distribution-specific service name. - Check the system clock, time zone, and scheduled date.
- Remember that a powered-off machine cannot run a job at its scheduled moment. Test again with a harmless job a few minutes ahead.
Files or Commands Cannot Be Found
The non-interactive environment may lack the expected PATH or working directory. Replace relative paths with absolute paths, set required variables, and redirect diagnostics to a log.
No Output Is Visible
- Output may have been sent to local mail.
- No redirection may have been configured.
- The error may be on stderr rather than stdout.
Use >> /path/to/log 2>&1 and include diagnostic commands such as date and id.
Permission Is Denied
Check the local at.allow and at.deny policy with an administrator. Manage only your own jobs unless administrative access is appropriate, and verify permissions on the scheduled scripts, source files, and target directories.
The Command File Was Deleted
With at -f, the file's command content is submitted when the job is created. Deleting the source file afterward normally does not remove that content from the queue. This does not apply to scripts or data files that the queued commands will try to read later; those referenced files must remain available.
Choosing a Linux Scheduler
Exam-Relevant Notes
atqueues one-time work;cronis primarily for recurring work.atdmust be installed and running for queued jobs to execute.Ctrl+Dends interactive stdin and submits the job.atqlists pending jobs andatrm JOB_IDremoves one that has not started.at -lcommonly lists jobs, andat -r JOB_IDcommonly removes one.-freads commands from a file at submission time.- Scheduled commands should use absolute paths and explicit output redirection when reliable logging is required.