LFCS 66 ๐ง At Jobs โ One-Time Scheduling
The at command is the standard Linux utility for scheduling a command to run exactly once at a specified future time. Unlike cron, which repeats jobs on a schedule, at is designed for one-off tasks: a backup that needs to run in an hour, a reminder that must fire tomorrow morning, or a maintenance script that should execute after business hours. For the LFCS exam, this distinction mattersโthe “Manage or schedule jobs for executing commands” objective requires knowing when to reach for at and when cron is the correct tool.
This chapter covers the at command family: the daemon that must be running, the time specification syntax, the companion commands for listing and deleting jobs, and the access control files that determine which users may schedule jobs at all.
Key point: at jobs will not run if the atd daemon is not enabled and started. Installing the package is not sufficient; the service must be active.
Why at exists
The one-time scheduling problem. Cron is a repeating scheduler. Its smallest granularity is one minute, and its design assumes a job should run again and again. Some tasks do not fit that model. You need to run a command once, at a specific moment, and never again. Forcing that into cron requires scheduling a job and then remembering to remove itโa fragile pattern. at exists precisely for this case: submit a job with a time, and the system runs it once and discards it.
The interactive submission problem. Many scheduled tasks are composed on the fly. An administrator decides at 2:15 PM that a service should be restarted at 3:00 PM. There is no crontab entry to edit; there is a single command to run once. at accepts commands from standard input or a file, making it natural to type a quick job at the shell and submit it without opening an editor.
The load-aware execution problem. The companion command batch reads commands the same way at does, but instead of running at a fixed time, it runs when system load permits . This is useful for non-urgent jobs that should not compete with interactive work. batch is part of the same package and shares the same submission model.
The accountability problem. Every at job is assigned a job number and queued in a specific letter queue. The atq command lists pending jobs with their numbers, dates, and owners. The atrm command deletes a job by number. This gives administrators a clear inventory of what is scheduled and the ability to cancel a job that is no longer needed. A cron job, by contrast, is identified only by its line in a file.
a. Installation and the atd Daemon
The at package provides the at, batch, atq, and atrm commands. On Debian and Ubuntu systems it is installed with apt; on RHEL-family systems, with dnf or yum.
# Debian/Ubuntu: install the at package
sudo apt update
sudo apt install at
# RHEL/Fedora: install the at package
sudo dnf install at
Installation alone is not enough. The atd daemon is responsible for monitoring the job queue and executing jobs when their time arrives. It must be enabled so it starts at boot, and started immediately so it runs in the current session .
# Enable atd to start on boot and start it immediately
sudo systemctl enable --now atd
# Verify that the daemon is active
sudo systemctl status atd
If atd is not running, at will accept and queue jobs, but they will never execute. This is the most common reason a scheduled job “disappears” silently. Checking systemctl status atd should be the first diagnostic step whenever an at job fails to run.
b. Time Specification Syntax
The at command accepts a remarkably flexible time syntax. The simplest form is a 24-hour time, HH:MM. If that time has already passed today, at assumes the job should run at that time tomorrow .
# Schedule a job for 3:30 PM today (or tomorrow if 15:30 has passed)
at 15:30
Named times are accepted: midnight, noon, and teatime (4 PM) . AM and PM suffixes work as expected.
# Schedule for 10:00 AM tomorrow
at 10am tomorrow
# Schedule for noon on a specific date
at noon July 31
Relative times use the form now + count unit. Units can be minutes, hours, days, or weeks . This is the most common form in practice because it does not require calculating an absolute timestamp.
# Run a job five minutes from now
at now + 5 minutes
# Run a job three days from now at 4 PM
at 4pm + 3 days
Dates can be specified in several formats: month-name day with optional year, MMDD[CC]YY, MM/DD/[CC]YY, DD.MM.[CC]YY, or [CC]YY-MM-DD . The date must follow the time.
Once the time is entered, at presents an interactive prompt (at>). Commands are typed line by line, and the job is submitted by pressing Ctrl+D on an empty line.
# Submit a job interactively
at now + 10 minutes
at> /usr/local/bin/cleanup.sh
at> echo "Cleanup finished" >> /var/log/cleanup.log
at> <Ctrl+D>
For non-interactive use, the -f option reads commands from a file. This is the preferred approach in scripts.
# Submit a job from a script file
at -f /opt/scripts/maintenance.sh now + 1 hour
The -m option sends mail to the user after the job completes, even if there is no output . By default, at mails the user only if the job produces output.
# Send mail on completion regardless of output
at -m now + 2 hours
c. Managing the Job Queue
Every submitted job receives a numeric job number. The atq command lists the current user’s pending jobs; when run by root, it lists everyone’s jobs . The output columns are job number, date, hour, queue, and username.
# List pending at jobs for the current user
atq
# As root, list all users' pending jobs
sudo atq
Jobs can be deleted by number with atrm. A user can only delete their own jobs; root can delete any job .
# Delete job number 5
atrm 5
# Alternative form using at -r
at -r 5
The queue designation is a single letter, a through z or A through Z. The default queue for at is a. Higher-letter queues run with increased niceness (lower priority). Uppercase queues are treated like batch: the job runs when system load permits after the specified time . For most LFCS tasks, the default queue is sufficient.
# Submit a job to queue b (slightly lower priority than default a)
at -q b now + 30 minutes
The -l option is an alias for atq, and -d is an alias for atrm. These exist for convenience but the dedicated commands are clearer.
Complete Example Session
# ============================================
# PART 1: VERIFY THE AT PACKAGE IS INSTALLED
# ============================================
# Check whether the at command exists
which at
# If no output, install the package
# Debian/Ubuntu:
sudo apt install at
# RHEL/Fedora:
sudo dnf install at
# ============================================
# PART 2: ENABLE AND START THE ATD DAEMON
# ============================================
# atd must be running for jobs to execute
sudo systemctl enable --now atd
# Confirm it is active (look for "active (running)")
sudo systemctl status atd
# ============================================
# PART 3: SUBMIT A JOB INTERACTIVELY
# ============================================
# Schedule a simple disk usage report
at now + 5 minutes
at> df -h > /tmp/disk-report.txt
at> echo "Report generated at $(date)" >> /tmp/disk-report.txt
at> <Ctrl+D>
# Output confirms the job number and scheduled time
# job 3 at Fri Oct 20 14:35:00 2026
# ============================================
# PART 4: SUBMIT A JOB FROM A FILE
# ============================================
# Create a script to run later
cat > /tmp/backup-job.sh <<'EOF'
#!/bin/bash
tar -czf /backups/etc-$(date +%F).tar.gz /etc
EOF
chmod +x /tmp/backup-job.sh
# Schedule it for 2 AM tomorrow
at -f /tmp/backup-job.sh 2am tomorrow
# ============================================
# PART 5: LIST PENDING JOBS
# ============================================
# Show the current user's queued jobs
atq
# Example output:
# 3 Fri Oct 20 14:35:00 2026 a root
# 4 Sat Oct 21 02:00:00 2026 a root
# ============================================
# PART 6: DELETE A JOB
# ============================================
# Remove job number 3 (no longer needed)
atrm 3
# Verify it is gone
atq
# ============================================
# PART 7: INSPECT A JOB'S CONTENTS
# ============================================
# View the commands queued for job 4
at -c 4
# This prints the script that will run, useful for verification
# ============================================
# PART 8: CHECK ACCESS CONTROL FILES
# ============================================
# Determine who can use at
ls -l /etc/at.allow /etc/at.deny 2>/dev/null
# If at.allow exists, only listed users may submit jobs
# If only at.deny exists, listed users are blocked
# If neither exists, only root may use at
# ============================================
# PART 9: RESTRICT ACCESS TO A USER
# ============================================
# As root, create at.deny and add a user
echo "baduser" | sudo tee /etc/at.deny
# baduser can no longer submit at jobs
# ============================================
# PART 10: USE BATCH FOR LOAD-AWARE JOBS
# ============================================
# Submit a job that runs when load is low, not at a fixed time
batch
at> /usr/local/bin/heavy-index.sh
at> <Ctrl+D>
# batch uses queue b and waits for load to drop below the threshold
The ten parts trace the full lifecycle: installation, daemon activation, interactive and file-based submission, queue inspection, deletion, access control, and the batch alternative. The critical dependency is atd; without it, every step after installation produces a queued job that never runs.
Quick Reference
At Command Options
| Option | Purpose |
|---|---|
-f file | Read commands from file instead of stdin |
-m | Mail user on completion even without output |
-q queue | Submit to a specific letter queue (default a) |
-l | Alias for atq |
-d | Alias for atrm |
-c job | Print the commands of a queued job |
Time Specification Forms
| Form | Example | Meaning |
|---|---|---|
| Absolute time | 15:30 | 3:30 PM today or tomorrow |
| Named time | midnight, noon, teatime | Fixed times of day |
| AM/PM | 10am | 10:00 AM |
| Relative | now + 5 minutes | Five minutes from now |
| Relative with time | 4pm + 3 days | 4 PM three days from now |
| Date | 10am Jul 31 | 10 AM on July 31 |
| Tomorrow | 1am tomorrow | 1 AM next day |
Companion Commands
| Command | Purpose |
|---|---|
atq | List pending jobs (own jobs; all jobs as root) |
atrm <job> | Delete job by number |
batch | Run when system load permits |
at -c <job> | Display the commands of a job |
Access Control Files
| File Exists | Behavior |
|---|---|
/etc/at.allow exists | Only listed users may use at |
No at.allow, at.deny exists | Listed users are blocked |
| Neither file exists | Only root may use at |
Best Practices
โ Do This:
# Enable atd and verify it is running
sudo systemctl enable --now atd # โ
# Use -f for scripted job submission
at -f /opt/scripts/backup.sh 2am tomorrow # โ
# List jobs before deleting to confirm the job number
atq && atrm 5 # โ
# Use at -c to verify a job's contents before it runs
at -c 4 # โ
# Use batch for non-urgent heavy jobs
batch < /opt/scripts/reindex.sh # โ
# Restrict at usage with at.allow when security matters
echo "admin" | sudo tee /etc/at.allow # โ
โ Don’t Do This:
# Install at but forget to start atd
sudo apt install at # โ
# Submit a job without checking the scheduled time
at now + 5 minutes # โ (verify with atq)
# Delete a job without listing first
atrm 5 # โ
# Assume a job ran; check mail or output
# No verification of execution # โ
# Use at for repeating jobs
at 2am # โ (use cron)
# Leave at.deny empty when restriction was intended
sudo touch /etc/at.deny # โ (empty deny allows all)
Common Pitfalls
| Pitfall | Why It Happens | Fix |
|---|---|---|
| Job never executes | atd daemon not running | sudo systemctl enable --now atd |
| Job output is lost | No redirection in the command | Redirect stdout/stderr to a file |
| Cannot submit job as a user | Access restricted by at.allow/at.deny | Check files; ask admin to add user |
| Time is misinterpreted | Past time assumes next day | Use now + or verify with atq |
| Job runs but environment differs | at retains limited environment | Set variables explicitly in the job |
| Deleting the wrong job | No listing before atrm | Always atq first |
at not found | Package not installed | sudo apt install at or sudo dnf install at |
Real-World Examples
1. Schedule a One-Time Backup
at -f /opt/scripts/backup.sh 2am tomorrow
2. Run a Cleanup in Ten Minutes
at now + 10 minutes
at> /usr/local/bin/cleanup.sh
at> <Ctrl+D>
3. List All Pending Jobs as Root
sudo atq
4. Delete a Job by Number
atrm 7
5. Inspect a Job’s Commands
at -c 7
6. Mail Notification on Completion
at -m now + 1 hour
7. Submit to a Lower-Priority Queue
at -q b -f /opt/scripts/nightly.sh 1am
8. Restrict a User from at
echo "contractor" | sudo tee -a /etc/at.deny
9. Run When Load Is Low
batch < /opt/scripts/index-rebuild.sh
10. Schedule with a Specific Date
at 9am Dec 31
Visual
The At Job Lifecycle
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ USER SUBMITS JOB โ
โ โ
โ at now + 5 minutes โ
โ at> command โ
โ at> <Ctrl+D> โ
โ โ โ
โ โผ โ
โ โโโโโโโโโโโโโโโโโโโ โ
โ โ Job queued โ Job number assigned โ
โ โ in /var/spool/ โ Queue letter (default a) โ
โ โ cron/at/ โ โ
โ โโโโโโโโโโฌโโโโโโโโโ โ
โ โ โ
โ โผ โ
โ โโโโโโโโโโโโโโโโโโโ โ
โ โ atd daemon โ Monitors the queue โ
โ โ running? โ โ
โ โโโโโโโโโโฌโโโโโโโโโ โ
โ โ YES โ
โ โผ โ
โ โโโโโโโโโโโโโโโโโโโ โ
โ โ Time reached โ atd executes the job โ
โ โ โ using /bin/sh โ
โ โโโโโโโโโโฌโโโโโโโโโ โ
โ โ โ
โ โผ โ
โ โโโโโโโโโโโโโโโโโโโ โ
โ โ Output mailed โ If -m or if output exists โ
โ โ Job discarded โ One-time: never runs again โ
โ โโโโโโโโโโโโโโโโโโโ โ
โ โ
โ If atd is NOT running, the job stays in the queue forever. โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Access Control Decision Flow
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ USER ATTEMPTS TO RUN at โ
โ โ
โ โโโโโโโโโโโโโโโโโโโ โ
โ โ Is user root? โโโโโโบ YES: Allowed, always โ
โ โโโโโโโโโโฌโโโโโโโโโ โ
โ โ NO โ
โ โผ โ
โ โโโโโโโโโโโโโโโโโโโ โ
โ โ /etc/at.allow โโโโโโบ EXISTS: Only listed users allowed โ
โ โ exists? โ (if not listed, denied) โ
โ โโโโโโโโโโฌโโโโโโโโโ โ
โ โ NO โ
โ โผ โ
โ โโโโโโโโโโโโโโโโโโโ โ
โ โ /etc/at.deny โโโโโโบ EXISTS: Listed users denied โ
โ โ exists? โ Others allowed โ
โ โโโโโโโโโโฌโโโโโโโโโ โ
โ โ NO โ
โ โผ โ
โ โโโโโโโโโโโโโโโโโโโ โ
โ โ Only root โ Default state when neither file โ
โ โ allowed โ exists โ
โ โโโโโโโโโโโโโโโโโโโ โ
โ โ
โ Empty at.deny = everyone allowed (default). โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
At Versus Cron
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ AT (one-time) CRON (repeating) โ
โ โ
โ โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ โ
โ โ Runs once โ โ Runs on scheduleโ โ
โ โ then discarded โ โ indefinitely โ โ
โ โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ โ
โ โ
โ โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ โ
โ โ Submitted via โ โ Edited in โ โ
โ โ command line โ โ crontab file โ โ
โ โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ โ
โ โ
โ โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ โ
โ โ Time: relative โ โ Time: five-fieldโ โ
โ โ or absolute โ โ schedule syntax โ โ
โ โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ โ
โ โ
โ โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ โ
โ โ Identify by โ โ Identify by โ โ
โ โ job number โ โ crontab line โ โ
โ โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ โ
โ โ
โ Use at for: backups in 1 hour, reminders, maintenance. โ
โ Use cron for: daily logs, hourly syncs, weekly reports. โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Time Specification Parsing
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ INPUT INTERPRETATION โ
โ โ
โ 15:30 Today 3:30 PM โ
โ (or tomorrow if past) โ
โ โ
โ now + 5 minutes Five minutes from now โ
โ โ
โ 4pm + 3 days 4 PM three days from now โ
โ โ
โ 10am Jul 31 10 AM on July 31 โ
โ โ
โ 1am tomorrow 1 AM next day โ
โ โ
โ midnight Start of next day โ
โ โ
โ noon Next 12:00 PM โ
โ โ
โ teatime Next 4:00 PM โ
โ โ
โ Dates must follow times. โ
โ Relative forms use "now +" for clarity. โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Summary
| Item | Value |
|---|---|
| Package | at (provides at, batch, atq, atrm) |
| Daemon | atd, enabled via systemctl enable --now atd |
| One-time scheduling | at <time> then commands, Ctrl+D |
| File submission | at -f script.sh <time> |
| List jobs | atq or at -l |
| Delete job | atrm <job> or at -r <job> |
| View job | at -c <job> |
| Mail on completion | at -m |
| Access control | /etc/at.allow, /etc/at.deny |
| Load-aware alternative | batch |
Key takeaways:
atdmust be running. Installing the package queues jobs but does not execute them.sudo systemctl enable --now atdis mandatory. Verify withsystemctl status atd.- Time syntax is flexible but past times roll forward.
at 2pmsubmitted after 2 PM schedules for tomorrow. Usenow + 5 minuteswhen you need a guaranteed future time. - Jobs are identified by number.
atqlists them;atrmdeletes them. Always list before deleting to confirm the number. - Access is controlled by
at.allowandat.deny. Ifat.allowexists, only listed users may useat. If onlyat.denyexists, listed users are blocked. If neither exists, only root may useat. batchis the load-aware sibling. It queues jobs the same way but runs them when system load drops, making it suitable for non-urgent heavy work.atis for one-time jobs;cronis for repeating jobs. Choosing the wrong tool creates maintenance burden or missed executions. The LFCS objective expects this distinction.
Remember: The at command answers a specific question: “Run this once, at this time.” It is not a replacement for cron, and cron is not a replacement for at. The daemon dependency is the detail that separates a working setup from a silent failureโa queued job with no atd process is invisible until the deadline passes and nothing happens. Enable the daemon first, verify with atq, and use at -c to inspect what will actually run. For the LFCS exam, the command family, the daemon name, the time syntax, and the access control file precedence are the core facts to retain.
Stop using slow, ad-bloated tool sites! ๐คฎ
๐ Search “KandZ Tools” on Google to use many professional utilities for free.
KandZ.me is the ultimate minimalist hub for:
โ
Finance (Mortgage, Interest, Inflation)
โ
Tech (Base64, JSON, Dev Suite, IP)
โ
Health (BMI, BMR, TDEE)
โ
Productivity (Timer, Workspace, QR)
โก๏ธ Fast & Private
๐ No data leaves your device
๐ 100% Free
๐ Use it now: https://tools.kandz.me
๐ Bookmark itโyouโll need it later!