Once you’ve scheduled a handful of one-time jobs with at, you need a way to see what’s actually still pending — that’s the entire job of atq. It’s a small command, but it’s the one that stops “did that job actually get scheduled?” from being a mystery.
What atq Actually Is
atq lists the jobs currently waiting in the at queue for the invoking user (or, for root, every user’s jobs). It’s part of the same at package as at, atrm, and the atd daemon, and it’s really just a formatted read of the job spool directory plus the daemon’s internal queue state. In fact, atq is functionally identical to running at -l — they’re two names for the same operation.
Basic Syntax
atq [options] [job_id ...]
Run with no arguments, it lists all pending jobs for the current user.
A Basic Example
atq
3 Fri Jul 31 22:00:00 2026 a john
4 Sat Aug 1 09:00:00 2026 a john
7 Sun Aug 2 03:30:00 2026 c john
The output columns are:
- Job number — the unique ID assigned when the job was created with
at(used later withatrmorat -c). - Scheduled date and time — when
atdwill actually execute the job. - Queue letter —
ais the default queue;bis reserved forbatch; other letters (cthroughz, and uppercaseA–Z) represent user-defined priority queues, with later letters running at lower priority (higher nice value). - Owning username — whose job this is.
Options
-v show completed but not-yet-deleted jobs as well
-q queue restrict listing to a specific queue letter
-V print version information
Filtering by Queue
atq -q c
Shows only jobs scheduled in queue c, useful if you deliberately separate routine jobs from higher-priority ones.
Showing Completed Jobs
atq -v
On some implementations, jobs that have finished executing but haven’t yet been cleaned up from the spool are shown with this flag, along with their completion status — handy for a quick “did it actually run” sanity check right after the scheduled time passes.
As Root: Seeing Everyone’s Jobs
A regular user only ever sees their own pending jobs. Root sees the queue for every user on the system:
sudo atq
3 Fri Jul 31 22:00:00 2026 a john
5 Fri Jul 31 23:15:00 2026 a maria
6 Sat Aug 1 01:00:00 2026 a backup-svc
This is genuinely useful during incident response or audits — “what’s actually scheduled to run on this box tonight, by anyone” is a question atq answers instantly as root, whereas hunting through crontabs for the same information takes considerably longer.
Combining atq with Other Commands
Inspecting the actual command a queued job will run:
atq
# note job number, e.g. 3
at -c 3
at -c dumps the full captured environment and shell commands for that job — pairing it with atq gives you both “what’s scheduled” and “what will it actually do” in two quick steps.
Counting pending jobs (useful in monitoring scripts):
PENDING=$(atq | wc -l)
if [ "$PENDING" -gt 20 ]; then
echo "Warning: unusually large at queue ($PENDING jobs)" | mail -s "at queue alert" admin@example.com
fi
Clearing every pending job for the current user:
atq | awk '{print $1}' | xargs -r atrm
Checking for a specific script before scheduling a duplicate:
if at -c $(atq | awk '{print $1}') 2>/dev/null | grep -q "nightly_report.sh"; then
echo "nightly_report.sh already scheduled, skipping duplicate."
else
echo "/usr/local/bin/nightly_report.sh" | at 23:00
fi
Where the Data Actually Comes From
atq doesn’t maintain its own separate database — it reads the same spool directory that at writes to and atd monitors, typically:
/var/spool/cron/atjobs/
Each file in that directory represents one queued job, and its filename encodes the job number, queue letter, and scheduled execution time, which is exactly the information atq parses and formats into its human-readable table.
Real-World System Administration Use Cases
Pre-deployment sanity check — before kicking off a deployment pipeline that itself uses at to schedule follow-up verification steps, check nothing conflicting is already queued:
echo "Currently scheduled at-jobs for this host:"
atq
Monitoring/alerting integration — a Nagios/Zabbix-style check script that flags if a critical recurring one-off (e.g., a certificate renewal job scheduled nightly via a wrapper) has silently disappeared from the queue:
#!/bin/bash
if ! atq | grep -q "cert_renew"; then
echo "CRITICAL: cert_renew at-job missing from queue"
exit 2
fi
echo "OK: cert_renew job present"
exit 0
(Note: since atq output doesn’t include the command text itself, this pattern usually needs to be paired with at -c on each job number, or with a consistent naming/queue convention, to actually match against a known job.)
Daily operational report:
#!/bin/bash
# report_at_queue.sh
{
echo "=== at queue as of $(date) ==="
atq
echo
echo "Total pending jobs: $(atq | wc -l)"
} > /var/log/at_queue_report.log
Troubleshooting
atq shows nothing, but you know you scheduled a job — you may be looking at the wrong user’s queue; only root sees everyone’s jobs, so double-check you scheduled it as the same user you’re now querying as.
Job appears in atq but never executes — check the atd daemon is actually running: systemctl status atd. If it’s stopped, jobs will sit in the queue indefinitely without executing, and atq will happily keep listing them as still pending.
“atq: command not found” — the at package isn’t installed; install via apt install at or dnf install at.
Time shown looks wrong / in the wrong timezone — atq displays times using the system’s configured timezone (timedatectl to check/set), so a mismatch usually means the server’s timezone configuration, not atq itself, needs fixing.
Security and Access Considerations
atq respects the same /etc/at.allow / /etc/at.deny access control as at and atrm — if a user isn’t permitted to use at, they generally can’t query the queue either. As with cron, it’s worth periodically auditing (as root) what’s actually queued across all users on shared or multi-tenant systems, since a forgotten or malicious one-time job is just as capable of causing damage as a persistent cron entry, and is easy to overlook precisely because it’s not sitting visibly in a crontab file.
Comparison to Related Commands
at -l— functionally identical to plainatq; both list the pending queue.atrm— the natural pairing partner; you list withatq, then remove specific jobs by ID withatrm.crontab -l— the cron equivalent for viewing recurring schedules, as opposed toatq‘s one-time job queue.systemctl list-timers— the systemd-native equivalent for viewing scheduled timer units, showing both recurring and one-shot transient timers with next-run times.
atq‘s output format and behavior are effectively identical across Debian, Ubuntu, RHEL, CentOS, Fedora, and SUSE, since they all ship the same upstream at package implementation. The only common variance is whether the at package is installed by default (frequently it isn’t on minimal server images).
Summary
atq is a small, single-purpose command, but it’s the visibility layer that makes the whole at job-scheduling system trustworthy — without it, you’d be scheduling one-time jobs into a black box. Pair it with at -c to inspect job contents and atrm to clean up, and you have a complete, lightweight toolkit for one-time task scheduling and auditing.
References
man atq,man at,man atdon your local system- GNU/Linux
atpackage documentation - Debian Administrator’s Handbook, “Task Scheduling: cron and atd”