⏰ Linux at Command

Schedule One-Time Tasks - Examples by Claude

What is at?

The at command schedules one-time tasks to run at a specific time in the future. Unlike cron which runs recurring tasks, at is for jobs you want to run once. Need to restart a service at 2 AM tonight? Want to send yourself a reminder in 3 hours? The at command is your tool. It's managed by the atd daemon (at daemon) which must be running on your system.

Example 1Schedule a Simple Command

echo "echo 'Backup complete' >> /tmp/backup.log" | at 2:30 AM
Schedule a command to run at 2:30 AM today (or tomorrow if it's already past 2:30 AM). The command will append a message to a log file.
warning: commands will be executed using /bin/sh job 1 at Thu Nov 2 02:30:00 2025
Note: The job number (1 in this case) is important for managing the scheduled task later.

Example 2Interactive Mode

at 10:00 PM
Enter interactive mode where you can type multiple commands. Press Ctrl+D when finished to save the job.
at> /home/user/scripts/backup.sh
at> echo "Backup started at $(date)" | mail -s "Backup Notice" admin@example.com
at> <EOT>
job 2 at Thu Nov  2 22:00:00 2025
Pro Tip: Interactive mode is great for complex tasks with multiple commands. Each line is a separate command.

Example 3Schedule with Relative Time

echo "systemctl restart apache2" | at now + 30 minutes
Schedule a command to run 30 minutes from now. Relative time specifications are incredibly flexible and natural.
job 3 at Thu Nov 2 14:45:00 2025
Time Formats: now + 1 hour, now + 2 days, now + 3 weeks, now + 1 month, now + 1 year

Example 4View Pending Jobs

atq
List all pending at jobs. Shows job number, scheduled time, queue, and user. The command 'atq' is short for "at queue".
1 Thu Nov 2 02:30:00 2025 a craig 2 Thu Nov 2 22:00:00 2025 a craig 3 Thu Nov 2 14:45:00 2025 a craig
Pro Tip: You can also use 'at -l' which does the same thing as atq.

Example 5View Job Details

at -c 3
Display the full details and commands for job number 3. This shows the complete script that will be executed, including environment variables.
#!/bin/sh # atrun uid=1000 gid=1000 # mail craig 0 umask 22 # ... environment variables ... cd /home/craig || { echo 'Execution directory inaccessible' >&2 exit 1 } systemctl restart apache2

Example 6Remove a Scheduled Job

atrm 3
Remove (delete) job number 3 from the queue. Use this to cancel scheduled tasks you no longer need.
Pro Tip: You can also use 'at -r 3' or 'at -d 3' to remove jobs. All three commands do the same thing.

Example 7Schedule from a Script File

at 3:00 AM -f /home/user/scripts/nightly_backup.sh
Execute an entire script file at 3:00 AM. The -f flag tells at to read commands from a file instead of stdin.
job 4 at Fri Nov 3 03:00:00 2025
Note: The script must be readable by the at daemon. Make sure permissions are correct!

Example 8Specific Date and Time

echo "reboot" | at 2:00 AM 12/25/2025
Schedule a task for a specific date and time. Useful for planned maintenance windows or scheduled events.
job 5 at Wed Dec 25 02:00:00 2025
Warning: Be careful with reboot commands! Make sure this is what you really want to do.

Example 9Natural Time Specifications

echo "tar -czf /backup/home.tar.gz /home" | at midnight
Use natural language time specifications. "midnight", "noon", "teatime" (4 PM), "tomorrow", "next week", etc.
job 6 at Fri Nov 3 00:00:00 2025
Fun Fact: "teatime" = 4:00 PM. Very British, but it works on all Linux systems!

Example 10Schedule for Tomorrow

echo "df -h | mail -s 'Disk Space Report' admin@example.com" | at 9:00 AM tomorrow
Explicitly schedule for tomorrow at 9:00 AM. Perfect for setting up morning reports or maintenance tasks.
job 7 at Fri Nov 3 09:00:00 2025

Example 11Schedule for Next Week

echo "apt update && apt upgrade -y" | at 11:00 PM next Tuesday
Schedule system updates for next Tuesday at 11:00 PM. You can specify days of the week with relative terms.
job 8 at Tue Nov 7 23:00:00 2025

Example 12Use Different Queue

echo "nice -n 19 /usr/bin/updatedb" | at -q b now + 1 hour
Use the -q flag to specify a different queue (a-z, with 'a' being highest priority, 'z' lowest). Lower priority jobs are "nicer".
job 9 at Thu Nov 2 15:30:00 2025
Note: Queue 'a' is default. Use lower priority queues (b, c, etc.) for resource-intensive tasks.

Example 13Batch Processing Queue

echo "/home/user/process_large_files.sh" | batch
The 'batch' command is a special form of 'at' that runs when system load is low (typically below 0.8). Perfect for CPU-intensive tasks.
job 10 at Thu Nov 2 14:30:00 2025
Pro Tip: batch is equivalent to 'at -q b now'. It waits for low system load before executing.

Example 14Multiple Commands at Once

at now + 5 minutes << END
cd /var/log
gzip *.log
mv *.gz /backup/logs/
echo "Log compression complete" | logger
END
Use here-document syntax (<<) to schedule multiple commands in one go. Everything between 'END' markers becomes the job.
job 11 at Thu Nov 2 14:35:00 2025

Example 15Check atd Service Status

systemctl status atd
Verify that the at daemon is running. The at command won't work if atd isn't active.
● atd.service - Deferred execution scheduler Loaded: loaded (/lib/systemd/system/atd.service; enabled) Active: active (running) since Thu 2025-11-02 08:00:00 EST Main PID: 1234 (atd) Tasks: 1 Memory: 1.2M CGroup: /system.slice/atd.service └─1234 /usr/sbin/atd -f
Warning: If atd is not running, start it with: sudo systemctl start atd

📚 Additional Information

Time Specification Examples

Format Example Description
HH:MM 14:30 2:30 PM today (or tomorrow if past)
HH:MM AM/PM 2:30 PM 2:30 PM with explicit AM/PM
midnight midnight 12:00 AM
noon noon 12:00 PM
teatime teatime 4:00 PM
now + time now + 3 hours 3 hours from now
tomorrow 10:00 AM tomorrow Tomorrow at 10:00 AM
next week next Monday Next occurrence of Monday
MMDDYY 122525 December 25, 2025
MM/DD/YYYY 12/25/2025 December 25, 2025

Common at Command Options

Option Description
-f file Read commands from file instead of stdin
-q queue Use specified queue (a-z)
-l List pending jobs (same as atq)
-d Delete jobs (same as atrm)
-r Remove jobs (same as atrm)
-c job Show job details
-m Send mail even if no output
-M Never send mail
-v Show time job will execute

Related Commands

Command Purpose
at Schedule one-time tasks
atq List pending at jobs
atrm Remove at jobs
batch Schedule low-priority tasks (runs when load permits)
cron Schedule recurring tasks
systemd timers Modern alternative to cron

Access Control

The at command uses two files to control access:

  • /etc/at.allow - If exists, only users listed here can use at
  • /etc/at.deny - If at.allow doesn't exist, users listed here cannot use at
  • If neither file exists, only root can use at (most restrictive)
  • If only at.deny exists and is empty, all users can use at (most permissive)

Real-World Use Cases

  • Scheduled Reboots: Restart systems during maintenance windows
  • Delayed Processing: Start resource-intensive tasks during off-hours
  • Reminders: Send yourself notifications at specific times
  • Temporary Tasks: One-time backups or data processing
  • Testing: Schedule test scripts to run at specific times
  • Auto-cleanup: Delete temporary files after a delay

Best Practices

  • Use absolute paths: at jobs may have different PATH variables
  • Test first: Schedule test jobs in 1-2 minutes to verify they work
  • Check atq regularly: Monitor pending jobs to avoid surprises
  • Use batch for heavy tasks: Prevents system overload
  • Mail notifications: at will email output by default (if mail is configured)
  • Document your jobs: Add comments in scripts for future reference

Troubleshooting

Problem: "You do not have permission to use at"
Solution: Check /etc/at.allow and /etc/at.deny. Add your username to at.allow or remove from at.deny
Problem: Jobs not executing
Solution: Check if atd is running: systemctl status atd. Start it if needed: sudo systemctl start atd
Problem: "Can't open /var/run/atd.pid"
Solution: atd is not running. Start the service: sudo systemctl start atd
Problem: Job ran but nothing happened
Solution: Check your mail for error messages: mail. Jobs output is emailed by default.

Environment Variables

at jobs inherit the environment from when they were scheduled, including:

  • Current directory (cd to specific directory if needed)
  • Environment variables (SHELL, PATH, HOME, etc.)
  • User permissions (jobs run as the user who scheduled them)

at vs. cron: When to Use Which?

Use at when... Use cron when...
Task runs once Task runs repeatedly
Specific date/time Regular schedule (daily, weekly, etc.)
Ad-hoc scheduling Permanent automation
Delayed execution Routine maintenance
Testing/temporary tasks Production automation

Advanced Examples

# Schedule script with output logging
echo "/home/user/backup.sh >> /var/log/backup.log 2>&1" | at 2:00 AM

# Chain multiple at jobs
echo "echo '/second/script.sh' | at now + 2 hours" | at now + 1 hour

# Conditional execution
echo "[ -f /tmp/ready ] && /usr/local/bin/process.sh" | at now + 30 minutes

# Schedule with multiple queues for prioritization
echo "critical_task.sh" | at -q a now + 10 minutes    # High priority
echo "normal_task.sh" | at -q b now + 10 minutes      # Normal priority
echo "low_priority.sh" | at -q c now + 10 minutes     # Low priority

# Schedule system maintenance
cat <<EOF | at 3:00 AM Sunday
apt update
apt upgrade -y
apt autoremove -y
systemctl reboot
EOF

# Monitor and alert if disk space low
echo "df -h | awk '\$5 > 90 {print}' | mail -s 'Disk Alert' admin@example.com" | at now + 1 hour

# Delayed cleanup after deployment
echo "rm -rf /tmp/deployment_files/*" | at now + 24 hours

# Schedule database backup at specific time
echo "mysqldump -u root -p'password' mydb > /backup/mydb_\$(date +%Y%m%d).sql" | at 11:30 PM

Security Considerations

  • File permissions: Ensure scripts called by at have appropriate permissions
  • Path safety: Use absolute paths to avoid PATH hijacking
  • Credential management: Don't hardcode passwords in at jobs; use credential files with proper permissions
  • Review jobs: Regularly check atq to ensure no unauthorized jobs are scheduled
  • Audit logging: Monitor /var/log/syslog for at job execution

Practical Sysadmin Scenarios

# Delayed service restart after configuration change
echo "systemctl restart nginx" | at now + 5 minutes

# Schedule certificate renewal for 3 AM
echo "certbot renew --quiet" | at 3:00 AM tomorrow

# Test website response time
echo "curl -o /dev/null -s -w '%{time_total}\n' https://example.com" | at now + 15 minutes

# Schedule firewall rule removal (temporary access)
echo "iptables -D INPUT -s 192.168.1.100 -j ACCEPT" | at now + 2 hours

# Automated log rotation
echo "gzip /var/log/application.log && mv /var/log/application.log.gz /backup/logs/" | at midnight

# System health check before maintenance
echo "/usr/local/bin/pre-maintenance-check.sh" | at 11:00 PM Friday

Integration with Other Tools

# Schedule with notify-send (desktop notification)
echo "notify-send 'Backup Complete' 'Your scheduled backup has finished'" | at now + 3 hours

# Integration with logger
echo "logger -t at-job 'Scheduled maintenance complete'" | at 4:00 AM

# Send Slack notification
echo "curl -X POST -H 'Content-type: application/json' --data '{\"text\":\"Scheduled task complete\"}' SLACK_WEBHOOK_URL" | at now + 1 hour

# Update monitoring system
echo "curl -X POST https://monitoring.example.com/checkin/job-123" | at now + 30 minutes
Pro Tip for Beginners: Start with simple tasks scheduled 1-2 minutes in the future. Use atq to watch them appear, and check your mail for output. This builds confidence before scheduling critical tasks.
Pro Tip for Sysadmins: Create a wrapper script that logs all at job activity. This helps with troubleshooting and provides an audit trail for compliance.

Fun Facts

  • The 'at' command dates back to Unix Version 7 (1979)
  • "teatime" as a time specification is a nod to the British tradition of afternoon tea
  • The 'batch' command is essentially 'at' with load-aware scheduling
  • at jobs survive reboots - they're stored in /var/spool/cron/atjobs/
  • The output of at jobs is emailed to you automatically (if mail is configured)