wenn eine einzige Ausführung genügt
Nicht jede geplante Aufgabe muss wiederkehrend sein. Für einmalige Aktionen zu einem bestimmten Zeitpunkt oder abhängig von der Systemlast sind at und batch die schlankeren Werkzeuge gegenüber cron und systemd-Timern. Dieser Leitfaden erklärt Syntax, Zeitangaben, Job-Verwaltung mit atq und atrm sowie die Berechtigungssteuerung über at.allow und at.deny.
Inhaltsverzeichnis
- 1. Wann at und batch die bessere Wahl sind
- 2. Installation und der atd-Daemon
- 3. Grundlegende at-Syntax und Zeitangaben
- 4. Jobs verwalten: atq, atrm und at -c
- 5. batch: Ausführung abhängig von der Systemlast
- 6. Umgebungsvariablen und Arbeitsverzeichnis in at-Jobs
- 7. Berechtigungen steuern: at.allow und at.deny
- 8. Praxisbeispiel: verzögertes Wartungsfenster
- 9. at/batch im Vergleich zu cron und systemd-Timern
- 10. Zusammenfassung
- 11. FAQ
1. Wann at und batch die bessere Wahl sind
Cron und systemd-Timer sind für wiederkehrende Aufgaben gebaut: ein Backup jede Nacht, eine Log-Rotation jede Woche, ein Zertifikats-Check zweimal täglich. Sobald eine Aufgabe aber genau einmal ausgeführt werden soll, etwa in drei Stunden oder morgen um 14 Uhr, ist eine dauerhafte Crontab-Zeile oder eine eigene systemd-Timer-Unit unnötiger Verwaltungsaufwand. Genau für diesen Fall existiert das at Kommando: Es plant eine Ausführung zu einem konkreten Zeitpunkt in der Zukunft, ohne dass danach ein dauerhafter Eintrag im System verbleibt.
Ein typisches Szenario: Ein Wartungsfenster beginnt in zwei Stunden, ein Dienst soll dafür automatisch heruntergefahren werden, ohne dass jemand die ganze Zeit am Terminal wartet. Statt eine temporäre Crontab-Zeile anzulegen und nach der Ausführung wieder zu entfernen, plant at diesen einen Vorgang direkt und verschwindet nach der Ausführung von selbst aus der Warteschlange. Das batch Kommando, der Zwilling von at, verfolgt einen anderen Ansatz: Es führt einen Job aus, sobald die Systemlast unter einen bestimmten Schwellwert fällt, unabhängig von einem festen Zeitpunkt, was sich für ressourcenintensive Einmalaufgaben eignet, die nicht mit dem laufenden Betrieb konkurrieren sollen.
Beide Werkzeuge ergänzen cron und systemd-Timer, statt sie zu ersetzen. Für wiederkehrende Aufgaben bleibt cron oder ein systemd-Timer die richtige Wahl, für einmalige, nicht wiederkehrende Aktionen sind at und batch das schlankere Werkzeug, weil kein dauerhafter Konfigurationseintrag gepflegt werden muss und die Job-Warteschlange sich nach jeder Ausführung selbst aufräumt.
2. Installation und der atd-Daemon
Auf vielen minimalen Serverinstallationen ist das Paket at nicht vorinstalliert und muss zunächst über den Paketmanager nachgerüstet werden. Debian und Ubuntu nutzen dafür apt install at, RHEL-basierte Systeme dnf install at. Nach der Installation läuft im Hintergrund der Daemon atd, der die Warteschlange der geplanten Jobs periodisch prüft und fällige Aufträge zum richtigen Zeitpunkt startet. Ohne einen laufenden atd-Prozess werden geplante at-Jobs zwar in der Warteschlange gespeichert, aber niemals ausgeführt, weshalb ein Blick auf systemctl status atd der erste Schritt bei jedem Problem mit at-Jobs sein sollte.
Der Daemon selbst prüft die Warteschlange standardmäßig einmal pro Minute, wodurch Jobs mit hoher Präzision zum geplanten Zeitpunkt starten, aber nicht mit Echtzeitgarantien wie bei einem dedizierten Scheduler. Für die allermeisten administrativen Aufgaben, etwa ein verzögerter Neustart oder eine einmalige Datenbereinigung, ist diese Genauigkeit vollkommen ausreichend. Nach der Installation empfiehlt sich zusätzlich systemctl enable atd, damit der Daemon auch nach einem Neustart des Servers automatisch wieder startet und keine geplanten Jobs unbemerkt liegen bleiben.
#!/usr/bin/env bash
# Install at/atd and verify the daemon is active
set -euo pipefail
apt-get update -qq
apt-get install -y at
systemctl enable --now atd
systemctl status atd --no-pager
# Quick smoke test: schedule a trivial job one minute from now
echo 'echo "at is working" >> /tmp/at-test.log' | at now + 1 minute
3. Grundlegende at-Syntax und Zeitangaben
Der Aufruf at ZEITANGABE öffnet eine interaktive Eingabeaufforderung, in der Befehle zeilenweise eingegeben und mit Strg+D abgeschlossen werden. In Skripten ist die Pipe-Variante praktischer: echo "befehl" | at ZEITANGABE übergibt den Befehl direkt, ohne interaktive Eingabe. Die Zeitangaben von at sind erstaunlich flexibel und lesen sich fast wie natürliche Sprache: at now + 1 hour, at 14:00, at teatime für 16 Uhr, at midnight, at noon tomorrow oder at 09:00 next monday sind alle gültige Ausdrücke.
Für exakte Zeitpunkte in der Zukunft eignet sich die Kombination aus Uhrzeit und Datum, etwa at 14:00 2026-08-15. Relative Zeitangaben wie at now + 3 days oder at now + 2 weeks sind besonders praktisch für Aufgaben, deren genauer Zeitpunkt sich nach dem aktuellen Moment richtet, statt nach einem festen Kalenderdatum. Ein wichtiges Detail: at interpretiert Zeitangaben immer in der lokalen Systemzeitzone, weshalb bei Servern mit unklarer Zeitzonenkonfiguration ein vorheriger Blick auf timedatectl Missverständnisse vermeidet.
#!/usr/bin/env bash
# at accepts a wide range of natural-language time expressions
set -euo pipefail
# Relative time from now
echo "systemctl restart nginx" | at now + 30 minutes
# Specific clock time today (or tomorrow, if already past)
echo "/usr/local/bin/generate-report.sh" | at 23:30
# Named times
echo "/usr/local/bin/nightly-cleanup.sh" | at midnight
echo "/usr/local/bin/send-reminder.sh" | at teatime
# Specific date and time
echo "/usr/local/bin/cert-renewal-check.sh" | at 09:00 2026-08-15
# Relative days/weeks
echo "/usr/local/bin/decommission-old-host.sh" | at now + 2 weeks
4. Jobs verwalten: atq, atrm und at -c
Sobald mehrere Jobs eingeplant sind, verschafft atq einen Überblick über die aktuelle Warteschlange: Jede Zeile zeigt eine Job-Nummer, den geplanten Zeitpunkt und die Warteschlange, der der Job zugeordnet ist. Diese Job-Nummer ist der Schlüssel für alle weiteren Operationen. Zum Entfernen eines eingeplanten, aber noch nicht ausgeführten Jobs dient atrm JOBNUMMER, was besonders dann wichtig wird, wenn sich Pläne kurzfristig ändern und ein bereits geplanter Vorgang doch nicht mehr stattfinden soll.
Für die Fehlersuche ist at -c JOBNUMMER unverzichtbar: Der Befehl gibt den vollständigen Inhalt eines geplanten Jobs aus, inklusive aller zum Planungszeitpunkt eingefrorenen Umgebungsvariablen und des tatsächlich auszuführenden Befehls. Das ist besonders hilfreich, wenn ein at-Job nicht wie erwartet funktioniert, denn oft liegt die Ursache in einer Umgebungsvariable, die zum Zeitpunkt der Planung anders gesetzt war als zum Zeitpunkt der Ausführung erwartet.
#!/usr/bin/env bash
# Inspect, list, and remove pending at jobs
set -euo pipefail
# List all pending jobs with their job number and scheduled time
atq
# Example output:
# 3 Fri Aug 15 09:00:00 2026 a root
# 4 Sat Aug 16 00:00:00 2026 a root
# Show the exact frozen environment and command of job 3
at -c 3
# Remove a job that is no longer needed
atrm 4
# Confirm removal
atq
5. batch: Ausführung abhängig von der Systemlast
Während at einen festen Zeitpunkt verlangt, verzichtet batch komplett auf eine Zeitangabe und wartet stattdessen, bis die Systemlast unter einen konfigurierten Schwellwert fällt, standardmäßig einen Load-Average-Wert von 1,5 auf den meisten Distributionen. Das eignet sich hervorragend für ressourcenintensive Einmalaufgaben wie eine große Datenbank-Reindexierung, eine umfangreiche Bildkonvertierung oder eine Log-Analyse über mehrere Gigabyte, die nicht mit dem laufenden Produktivbetrieb um CPU-Zeit konkurrieren sollen.
Der Aufruf funktioniert syntaktisch identisch zu at, nur ohne Zeitangabe: echo "befehl" | batch. Der Schwellwert selbst lässt sich über den Parameter -l beim Start des atd-Daemons anpassen, üblicherweise über eine Init-Konfigurationsdatei oder einen systemd-Override. Auf Servern mit durchgehend hoher Grundlast, etwa stark ausgelasteten Datenbankservern, lohnt sich eine bewusste Anpassung dieses Schwellwerts, da batch-Jobs sonst nie zur Ausführung kommen, wenn die Load-Average dauerhaft über dem Standardwert liegt.
#!/usr/bin/env bash
# batch: run when system load drops below the configured threshold
set -euo pipefail
# Schedule a resource-intensive reindex job to run when load permits
echo "/usr/local/bin/reindex-search-catalog.sh" | batch
# batch jobs show up in the same queue as at jobs
atq
# Check current load average to understand when batch will fire
uptime
# Adjust the load-average threshold atd uses for batch jobs
# (Debian/Ubuntu: edit /etc/default/atd or the systemd unit override)
# ExecStart=/usr/sbin/atd -b -l 3.0 -f
6. Umgebungsvariablen und Arbeitsverzeichnis in at-Jobs
Ein häufiger Stolperstein: at friert die Umgebungsvariablen und das aktuelle Arbeitsverzeichnis exakt zum Zeitpunkt der Planung ein, nicht zum Zeitpunkt der späteren Ausführung. Wird ein at-Job in einer interaktiven SSH-Sitzung mit gesetzten Umgebungsvariablen geplant, aber die Sitzung endet vor der Ausführung, bleiben genau diese eingefrorenen Werte erhalten, selbst wenn sich zwischenzeitlich systemweite Umgebungsvariablen geändert haben. Das unterscheidet at fundamental von cron, wo Jobs standardmäßig mit einer minimalen, definierten Umgebung starten, unabhängig davon, wer die Crontab wann bearbeitet hat.
Für Skripte, die auf bestimmte Umgebungsvariablen angewiesen sind, empfiehlt es sich daher, diese explizit innerhalb des geplanten Befehls zu setzen, statt sich auf die zum Planungszeitpunkt eingefrorene Umgebung zu verlassen. Das Arbeitsverzeichnis wird ebenfalls eingefroren: Ein at-Job, der relative Pfade verwendet, referenziert immer das Verzeichnis, aus dem heraus at ursprünglich aufgerufen wurde, nicht das Home-Verzeichnis oder ein anderes Standardverzeichnis zum Ausführungszeitpunkt.
#!/usr/bin/env bash
# Explicit environment inside the scheduled command,
# instead of relying on the frozen environment from planning time
set -euo pipefail
echo "cd /var/www/html && APP_ENV=production /usr/bin/php artisan cache:clear" | at now + 1 hour
# Verify what got frozen: working directory and environment
at -c "$(atq | tail -1 | awk '{print $1}')" | head -20
7. Berechtigungen steuern: at.allow und at.deny
Standardmäßig darf jeder lokale Benutzer eigene at-Jobs anlegen, was auf einem Mehrbenutzersystem oder einem Server mit mehreren Deploy-Accounts nicht immer erwünscht ist. Die Dateien /etc/at.allow und /etc/at.deny steuern diese Berechtigung zentral: Existiert at.allow, dürfen ausschließlich die dort aufgeführten Benutzer at-Jobs anlegen, alle anderen werden abgewiesen. Existiert keine at.allow, aber eine at.deny, dürfen alle Benutzer außer den dort explizit gesperrten Konten at nutzen.
Für produktive Server mit striktem Berechtigungskonzept ist eine explizite at.allow-Datei mit genau den Accounts, die at-Jobs anlegen dürfen, die sichere Variante nach dem Prinzip der minimalen Rechtevergabe. Root behält unabhängig von beiden Dateien immer Zugriff auf at, diese Einschränkung betrifft ausschließlich reguläre Benutzerkonten. Nach jeder Änderung an diesen Dateien ist kein Neustart des Daemons nötig, da atd die Berechtigungsdateien bei jedem Aufruf von at direkt neu einliest.
# /etc/at.allow — if this file exists, ONLY listed users may use at/batch
# One username per line, comments not supported by all implementations
deploy
backup-operator
# /etc/at.deny — used only when at.allow does NOT exist
# Explicitly blocks listed users, everyone else is allowed
# guest
# nobody
# Root can always schedule at/batch jobs regardless of either file.
# Changes take effect immediately, atd re-reads these files per invocation.
8. Praxisbeispiel: verzögertes Wartungsfenster
Ein realistisches Szenario aus dem Betriebsalltag: Ein geplantes Wartungsfenster beginnt in zwei Stunden. Ein Deployment-Skript soll den Server automatisch in den Wartungsmodus versetzen, ohne dass jemand die ganze Zeit wartet, um den Befehl manuell auszuführen. Mit at lässt sich dieser einmalige Vorgang exakt zum richtigen Zeitpunkt einplanen, inklusive einer automatischen Benachrichtigung, dass das Wartungsfenster begonnen hat.
Kombiniert mit einem Rollback-Mechanismus, der bei Bedarf ebenfalls per at eingeplant wird, entsteht ein vollständiges, zeitlich begrenztes Wartungsszenario ohne dauerhafte Cron-Einträge. Der große Vorteil gegenüber einer temporär angelegten Cron-Zeile: Nach der Ausführung verschwindet der at-Job automatisch aus der Warteschlange, es bleibt kein Aufräumschritt für einen manuell wieder zu entfernenden Cron-Eintrag übrig.
#!/usr/bin/env bash
# schedule-maintenance.sh — schedule maintenance start and automatic rollback
set -euo pipefail
readonly MAINTENANCE_START="now + 2 hours"
readonly MAINTENANCE_END="now + 4 hours"
# Enter maintenance mode and notify the team when the window begins
{
echo "touch /var/www/html/maintenance.flag"
echo "systemctl reload nginx"
echo 'curl -fsS -X POST -d "Maintenance window started" https://hooks.example.com/notify'
} | at "$MAINTENANCE_START"
# Automatic rollback: exit maintenance mode after the window closes,
# even if nobody is available to run the command manually
{
echo "rm -f /var/www/html/maintenance.flag"
echo "systemctl reload nginx"
echo 'curl -fsS -X POST -d "Maintenance window ended" https://hooks.example.com/notify'
} | at "$MAINTENANCE_END"
atq
9. at/batch im Vergleich zu cron und systemd-Timern
Die Wahl zwischen at, batch, cron und systemd-Timern hängt vor allem davon ab, ob eine Aufgabe einmalig oder wiederkehrend ist, und ob ein fester Zeitpunkt oder die Systemlast den Ausführungszeitpunkt bestimmen soll.
| Werkzeug | Wiederholung | Auslöser | Typischer Einsatz |
|---|---|---|---|
| at | Einmalig, kein Wiederholen | Fester Zeitpunkt | Verzögerter Neustart, geplantes Wartungsfenster |
| batch | Einmalig, kein Wiederholen | Systemlast unterschreitet Schwellwert | Ressourcenintensive Einmaljobs |
| cron | Wiederkehrend nach Zeitplan | Feste Zeitfelder in crontab | Tägliche Backups, Log-Rotation |
| systemd-Timer | Wiederkehrend, flexibel | OnCalendar, OnBootSec, OnUnitActiveSec | Wiederkehrende Jobs mit Journal-Integration |
| Temporäre Crontab-Zeile | Manuelles Anlegen und Entfernen nötig | Fester Zeitpunkt | Unnötiger Verwaltungsaufwand gegenüber at |
Als Faustregel gilt: Wiederkehrende Aufgaben gehören in cron oder einen systemd-Timer, einmalige Aufgaben mit festem Zeitpunkt gehören zu at, und ressourcenintensive Einmalaufgaben ohne festen Zeitpunkt gehören zu batch. Eine temporär angelegte und nach Gebrauch wieder entfernte Crontab-Zeile für einen einmaligen Vorgang ist in praktisch jedem Fall die schlechtere Lösung gegenüber einem einzigen at-Aufruf.
Mironsoft
Deployment-Automatisierung und Scheduling-Konzepte für Linux-Server
Einmalige Aufgaben ohne dauerhafte Cron-Einträge?
Wir analysieren bestehende Wartungs- und Deployment-Skripte und richten passende at-, batch- oder systemd-Timer-Lösungen ein, inklusive Berechtigungssteuerung über at.allow und at.deny.
Scheduling-Audit
Bewertung bestehender Cron-Einträge auf tatsächlichen Wiederholungsbedarf
at/batch-Integration
Wartungsfenster und Einmalaufgaben sauber in Deployment-Pipelines einbetten
Berechtigungskonzept
at.allow und at.deny nach dem Prinzip der minimalen Rechtevergabe konfigurieren
10. Zusammenfassung
at und batch schließen eine Lücke, die cron und systemd-Timer bewusst offen lassen: einmalige, nicht wiederkehrende Aufgaben ohne dauerhaften Konfigurationseintrag. at ZEITANGABE plant einen Vorgang zu einem konkreten Zeitpunkt in natürlicher Zeitsprache, batch wartet stattdessen auf niedrige Systemlast. atq zeigt die Warteschlange, atrm entfernt einzelne Jobs, at -c zeigt die eingefrorene Umgebung eines geplanten Jobs zur Fehlersuche.
Berechtigungen lassen sich über /etc/at.allow und /etc/at.deny zentral steuern, ohne dass ein Neustart des atd-Daemons nötig wäre. Für verzögerte Wartungsfenster, einmalige Rollbacks oder ressourcenintensive Einmaljobs sind at und batch das schlankere Werkzeug gegenüber einer temporär angelegten und später wieder zu entfernenden Crontab-Zeile.
at und batch, das Wichtigste auf einen Blick
Einmalig statt wiederkehrend
at und batch sind für genau eine Ausführung gedacht, cron und systemd-Timer für wiederkehrende Zeitpläne.
Flexible Zeitangaben
at now + 1 hour, at teatime, at 09:00 next monday lesen sich fast wie natürliche Sprache.
Job-Verwaltung
atq listet, atrm entfernt, at -c zeigt die eingefrorene Umgebung eines Jobs.
batch für Last-Schonung
batch wartet auf niedrige Systemlast statt auf einen festen Zeitpunkt, ideal für ressourcenintensive Einmaljobs.