Skip to content
DevOps AI ToolKit
Newsletter
All guides
AI for Automation By James Joyner IV · · 7 min read

at Error: 'Can't open /var/run/atd.pid to signal atd. No atd running?' — Cause, Fix, and Troubleshooting Guide

Quick answer

Fix 'Can't open /var/run/atd.pid to signal atd. No atd running?' and 'at: command not found' — atd is stopped, disabled, or the at package is missing.

  • #automation
  • #troubleshooting
  • #at
Free toolkit

Fixing errors like this? Get 500 free DevOps AI prompts

500 copy-paste AI prompts for the stack you actually run — one PDF, free.

Overview

at schedules a one-shot command to run at a future time, but the scheduling and the execution are handled by two different things. The at command only writes the job into a spool directory; the atd daemon is what wakes up and actually runs it. When you queue a job and atd is not running, at warns you immediately — and the job, though accepted, will never fire:

$ echo '/opt/jobs/report.sh' | at now + 5 minutes
warning: commands will be executed using /bin/sh
job 7 at Sun Jul 12 09:35:00 2026
Can't open /var/run/atd.pid to signal atd. No atd running?

The job is queued (you can see it in atq), but the Can't open /var/run/atd.pid line means there is no daemon to run it. A related, earlier failure is when the package is not installed at all:

$ at now + 5 minutes
-bash: at: command not found

Both are common on minimal cloud images and containers, where at and its daemon are not installed or not enabled by default. The scheduled job silently never runs, which is worse than a hard failure because nothing alerts you at the scheduled time.

Symptoms

  • Can't open /var/run/atd.pid to signal atd. No atd running? after queuing a job.
  • at: command not found when the at package is not installed.
  • atq lists jobs that never execute — their scheduled time passes with no effect.
  • systemctl status atd shows inactive (dead) or disabled.
  • The same script runs fine when invoked manually but never runs when scheduled with at.

Common Root Causes

1. The atd daemon is stopped

The at package is installed and at queues jobs, but the atd service is not running, so nothing dispatches queued jobs. This is the exact condition behind the No atd running? message.

2. The atd service is disabled at boot

atd was stopped and never re-enabled, so it is down after every reboot. Jobs pile up in the queue unrun.

3. The at package is not installed

On minimal Debian/Ubuntu, RHEL/Alma/Rocky, or container base images, neither at nor atd ships by default, producing at: command not found.

4. Job scheduled while the daemon was down

Even a correctly configured system will not run a job queued during a window when atd was stopped, until the daemon comes back and re-scans the queue.

5. User denied by /etc/at.allow or /etc/at.deny

at access is gated by /etc/at.allow (allowlist) and /etc/at.deny (denylist). A user not permitted cannot queue jobs, which can masquerade as a daemon problem.

How to Diagnose

First confirm the command exists at all — this separates “not installed” from “daemon down”:

command -v at atd
/usr/bin/at

If atd prints nothing (only at resolves, or neither does), the daemon binary or the whole package is missing. Check the service state:

systemctl status atd --no-pager | head -5
● atd.service - Deferred execution scheduler
     Loaded: loaded (/lib/systemd/system/atd.service; disabled; preset: enabled)
     Active: inactive (dead)

inactive (dead) and disabled together explain both the missing PID file and why jobs never run. Confirm that your jobs are actually queued (so you know the problem is dispatch, not scheduling):

atq
7	Sun Jul 12 09:35:00 2026 a myuser

The job is in the queue but will sit there until a daemon runs it. Check the access-control files if a specific user cannot queue at all:

ls -l /etc/at.allow /etc/at.deny 2>/dev/null
cat /etc/at.deny 2>/dev/null | grep -w myuser
-rw-r----- 1 root daemon 144 Jun  1 12:00 /etc/at.deny
myuser

A username listed in /etc/at.deny (and no /etc/at.allow) means that user is blocked.

Fixes

Install the package if it is missing — it provides both at and the atd daemon:

# Debian / Ubuntu
sudo apt-get update && sudo apt-get install -y at
# RHEL / Alma / Rocky / Fedora
sudo dnf install -y at

Enable and start the daemon in one step, then confirm it is active:

sudo systemctl enable --now atd
systemctl status atd --no-pager | head -3
● atd.service - Deferred execution scheduler
     Loaded: loaded (/lib/systemd/system/atd.service; enabled; preset: enabled)
     Active: active (running) since Sun 2026-07-12 09:31:02 UTC; 2s ago

Any jobs already sitting in the queue will now be picked up at (or immediately after) their scheduled time. Verify end to end by queuing a quick job and watching it run:

echo 'date >> /tmp/at-test.log' | at now + 1 minute
atq
job 8 at Sun Jul 12 09:33:00 2026
8	Sun Jul 12 09:33:00 2026 a myuser

After the minute elapses, confirm it fired:

cat /tmp/at-test.log
Sun Jul 12 09:33:00 UTC 2026

If a user is blocked by access control, remove them from /etc/at.deny (or add them to /etc/at.allow if that file governs access):

sudo sed -i '/^myuser$/d' /etc/at.deny
# or, if using an allowlist:
echo 'myuser' | sudo tee -a /etc/at.allow

In containers, where there is no systemd, start atd directly (or install a proper init) — note the daemon must stay running for the queue to be serviced:

atd            # start the daemon in the foreground of an init/entrypoint
atd -f &       # or background it in a wrapper

What to Watch Out For

  • Queuing a job succeeds even when atd is down — at returns a job number regardless. The No atd running? warning is the only signal that it will never fire, so do not treat a job number as confirmation it will run.
  • at uses /bin/sh, not your login shell, and runs with a minimal environment. Use absolute paths and set any PATH/HOME your script needs inside the job itself.
  • On minimal images and containers, atd is frequently installed but disabled. Bake systemctl enable --now atd (or an equivalent supervisor entry) into your provisioning so a reboot does not silently break scheduled jobs.
  • Jobs are per-user and stored in a spool directory. Queue as the user that should own the execution context, since the job runs with that user’s identity and permissions.
  • atq shows queued jobs but not why they did not run. Check atd’s state and journalctl -u atd for dispatch, and route job output to a log — otherwise a failed run is invisible.
Free download · 368-page PDF

Get 500 Battle-Tested DevOps AI Prompts — Free

500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.

  • 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
  • Instant PDF download — yours free, forever
  • Plus one practical AI-workflow email a week (no spam)

Single opt-in · unsubscribe anytime · no spam.