atrm Command in Linux: Complete Guide to Removing Scheduled Jobs and Parameters

atrm command in Linux and it perimeters

Scheduling a one-time job with at is easy. Un-scheduling one you made a mistake on — or one that’s no longer needed because the situation changed — is what atrm is for. It’s a tiny command, but it’s saved me more than once from a job firing off at 3 AM that I really didn’t want running anymore.

What atrm Actually Is

atrm removes one or more pending jobs from the at job queue, identified by the job number that at assigned when the job was scheduled (and that atq shows you). It’s part of the same at package as at, atq, and the background atd daemon. Functionally, atrm is equivalent to at -d, which does the identical operation under a different flag on the base at command.

Basic Syntax

atrm job_id [job_id ...]

You need at least one job ID. There’s no interactive mode and no confirmation prompt — atrm deletes silently and immediately, so it’s worth double-checking the job ID before you run it.

A Basic Example

First, find the job number with atq:

atq
3    Fri Jul 31 22:00:00 2026 a john
4    Sat Aug  1 09:00:00 2026 a john

Then remove it:

atrm 3

No output on success. Verify it’s gone:

atq
4    Sat Aug  1 09:00:00 2026 a john

Job 3 is no longer listed and will not execute.

Removing Multiple Jobs at Once

atrm 3 4 7

Each job ID is processed independently — if one ID doesn’t exist or belongs to another user (and you’re not root), atrm reports an error for that specific ID but still processes the rest of the list.

atrm 99
atrm: 99: No such file or directory

Options

atrm itself has essentially no options beyond the job ID list — it’s intentionally a one-trick command. The equivalent functionality via the base at command does support a couple of related flags:

at -d job_id     # identical to atrm job_id

There’s no -f (force) or -i (interactive confirm) flag on standard atrm — deletion is immediate and unconditional, which is worth remembering, especially in scripts.

Permissions and Ownership

A regular user can only remove their own jobs. If you try to remove another user’s job without root privileges:

atrm 5
atrm: 5: Permission denied

Root can remove any job on the system, from any user:

sudo atrm 5

Real-World Examples

Clearing every job you personally have pending:

atq | awk '{print $1}' | xargs -r atrm

The -r flag on xargs prevents it from running atrm with no arguments at all if atq returns nothing, which would otherwise produce an unhelpful “at least one job ID required” error.

Removing a job by matching its command content:

Since atrm only works with job numbers, and atq doesn’t show the actual command, you typically need to combine it with at -c to find the right job first:

for job in $(atq | awk '{print $1}'); do
    if at -c "$job" | grep -q "old_backup_script.sh"; then
        echo "Removing job $job (matches old_backup_script.sh)"
        atrm "$job"
    fi
done

Cancelling a scheduled maintenance action if a deployment is aborted:

#!/bin/bash
# deploy.sh
JOB_ID=$(echo "systemctl restart myapp" | at now + 20 minutes | grep -oP 'job \K[0-9]+')
echo "Scheduled restart as job $JOB_ID"

# ... later, if deployment fails and restart should be cancelled:
if [ "$DEPLOY_FAILED" = true ]; then
    atrm "$JOB_ID"
    echo "Cancelled scheduled restart (job $JOB_ID)"
fi

This pattern — capturing the job ID at scheduling time so it can be cancelled conditionally later — is one of the more valuable uses of atrm in automation, since it lets a script “undo” a previously scheduled action based on later events.

Cleaning up stale jobs older than a certain queue letter or pattern (admin housekeeping, as root):

sudo atq | awk '$5=="olduser" {print $1}' | xargs -r sudo atrm

Removes all pending jobs belonging to a user named olduser, for example as part of an account decommissioning process.

What Happens Under the Hood

Each pending at job is stored as an individual file in the spool directory (commonly /var/spool/cron/atjobs/), with a filename that encodes the job number, queue letter, and scheduled time. atrm simply locates and deletes the corresponding spool file (with appropriate permission checks first). Because the atd daemon works directly off this spool directory, removing the file is immediately effective — there’s no separate “queue database” to update or daemon to notify or restart.

Troubleshooting

“atrm: job_id: No such file or directory” — the job either already ran, was already removed, or the ID was mistyped. Double-check with atq first.

“atrm: job_id: Permission denied” — you’re trying to remove a job that belongs to a different user; you’ll need root (sudo atrm job_id).

Job still shows in atq after running atrm — very rare, but can happen if there’s a permissions issue on the spool directory itself preventing deletion; check ownership and permissions on /var/spool/cron/atjobs/ and check atd‘s logs.

“atrm: command not found” — the at package isn’t installed; install with apt install at or dnf install at — this also installs at, atq, and atd.

Accidentally removed the wrong job — there’s no undo. This is exactly why I always run atq and, for anything important, at -c job_id to confirm the contents, immediately before running atrm.

Security Considerations

  • Because atrm deletes without confirmation, avoid using loosely-matched patterns (like the “match by command content” example above) in automated scripts without a dry-run/logging step first — a bad regex match could silently cancel an unrelated critical job.
  • On shared or multi-tenant systems, restrict who can use at/atrm at all via /etc/at.allow and /etc/at.deny, since any user permitted to schedule jobs is also, by default, permitted to remove their own — and root can remove anyone’s.
  • As part of offboarding a user account, it’s good practice to check sudo atq for any jobs still owned by that username and clear them with atrm before or during account removal, so no orphaned scheduled action fires after the account is gone.

Comparison to Related Commands

  • at -d job_id — functionally identical alias for the same delete operation.
  • atq — the natural partner command; you almost always run atq first to find the job ID you need to pass to atrm.
  • crontab -r — the cron equivalent, but note the very different scope: crontab -r wipes an entire crontab in one shot, while atrm removes individual one-time jobs by ID, which is a much more surgical operation.
  • systemctl stop/disable on a transient timer unit — the systemd-native equivalent for cancelling a scheduled one-shot timer.

atrm‘s behavior is consistent across Debian, Ubuntu, RHEL, CentOS, Fedora, and SUSE — it’s the same upstream at package everywhere, so scripts using it are highly portable.

Summary

atrm is a small, blunt, and completely reliable tool: give it a job ID, and that job is gone from the queue, immediately and without ceremony. The only real skill involved is knowing which job ID you actually want to remove — which is why atq (and at -c for double-checking contents) should always be your first stop before reaching for atrm.

References

  • man atrm, man at, man atq on your local system
  • GNU/Linux at package documentation
  • Debian Administrator’s Handbook, “Task Scheduling: cron and atd”

Total
0
Shares

Leave a Reply

Previous Post
atq command in Linux and it perimeters

atq Command in Linux: Complete Guide to Viewing Scheduled Job Queue and Parameters

Next Post
crontab command in Linux and it perimeters

crontab Command in Linux: Complete Guide to Scheduling Cron Jobs and Parameters

Related Posts