Что такое anacron
cron хорошо работает на серверах с постоянным uptime. Но что если у тебя laptop, который ты выключаешь на ночь и в выходные? Cron job 0 3 * * * (каждый день в 03:00) пропустится: VM не работает в 03:00.
anacron решает эту проблему. Идея: вместо точного «в 03:00», anacron говорит «минимум раз в N дней». Он запоминает, когда последний раз задача выполнялась, и если прошло больше N — запустит при ближайшем boot.
На современных systemd-дистрибутивах эту функцию заменяет Persistent=true в systemd timer (см. урок 03). Но anacron всё ещё распространён на:
- Ubuntu desktop (для apt-daily, apt-daily-upgrade в legacy-режиме);
- RHEL/CentOS Server с traditional cron;
- любые laptops/desktops, где systemd-timer-ы не настроили.
Для Junior DE: знать что это есть и зачем — must. Часто работать с этим напрямую не придётся.
Где живёт anacron
Установка: anacron обычно ставится автоматически с пакетом cron или отдельно (apt install anacron).
Конфиг: /etc/anacrontab.
$ cat /etc/anacrontab
# /etc/anacrontab: configuration file for anacron
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
HOME=/root
LOGNAME=root
# These replace cron's entries
1 5 cron.daily run-parts --report /etc/cron.daily
7 10 cron.weekly run-parts --report /etc/cron.weekly
@monthly 15 cron.monthly run-parts --report /etc/cron.monthly
Формат строки anacron:
PERIOD DELAY JOB-IDENTIFIER COMMAND
- PERIOD — минимальный интервал в днях (1, 7, или
@monthly). - DELAY — задержка в минутах после старта anacron (для разноса запусков по времени).
- JOB-IDENTIFIER — уникальное имя задачи (анакрон использует его как ключ для timestamp файла).
- COMMAND — что выполнить.
В примере выше:
1 5 cron.daily ...— каждый день, с задержкой 5 минут после anacron-start, выполнить все скрипты из/etc/cron.daily/.7 10 cron.weekly ...— раз в 7 дней, с задержкой 10 минут.@monthly 15 cron.monthly ...— раз в месяц, задержка 15 минут.
Как anacron работает под капотом
$ ls /var/spool/anacron/
cron.daily cron.monthly cron.weekly
$ cat /var/spool/anacron/cron.daily
20260513
В каждом файле — дата последнего успешного запуска (формат YYYYMMDD). При запуске anacron:
- Читает
/etc/anacrontab. - Для каждой job сравнивает текущую дату с timestamp в
/var/spool/anacron/JOB-NAME. - Если прошло больше PERIOD дней — добавляет в очередь на выполнение.
- После DELAY минут — запускает команды последовательно.
- После успеха обновляет timestamp.
Когда anacron запускается
На современных Ubuntu/Debian — через cron:
$ cat /etc/cron.d/anacron
30 7 * * * root [ -x /etc/init.d/anacron ] && update-rc.d anacron start ...
Или через systemd:
$ systemctl list-units --type=service | grep anacron
anacron.service loaded active running Run anacron jobs
Идея: anacron запускается раз в день (или при boot), смотрит на свой to-do список, выполняет «пропущенные».
anacron vs cron: ключевая разница
Разные модели запуска для разных типов машин.
Реальный кейс DE: laptop с локальным dev-окружением
Сценарий: у тебя на личном laptop крутится локальная Postgres, чистится /tmp, обновляется dev-данные. Хочешь, чтобы это работало даже если laptop был off ночью.
С cron 0 3 * * * /opt/cleanup.sh — не сработает: laptop спал.
С anacron в /etc/anacrontab:
1 5 dev-cleanup /opt/cleanup.sh
Через 5 минут после старта anacron (при первом boot за день), если прошло >= 1 день с прошлого запуска — выполнит /opt/cleanup.sh.
С systemd timer (современный путь):
[Timer]
OnCalendar=daily
Persistent=true
То же поведение, но в современном synthax.
at: однократное запланированное задание
at — для разового запуска: «выполни эту команду завтра в 18:00». В отличие от cron/timer, не recurring.
# Установить, если нет:
$ sudo apt install at
# Запустить at-сервис (на современной Ubuntu):
$ sudo systemctl enable --now atd
atd — daemon, который держит очередь и запускает в положенное время.
Создать запланированную задачу
# Интерактивно: вводим команды, заканчиваем Ctrl+D
$ at 18:00 tomorrow
warning: commands will be executed using /bin/sh
at> echo "Hello from at" > /tmp/at-test.log
at> /opt/etl/one-time-fix.sh
at> <EOT> # Ctrl+D
job 5 at Wed May 14 18:00:00 2026
# Через stdin:
$ echo "/opt/etl/cleanup.sh" | at 03:00 tomorrow
# Через here-doc:
$ at now + 30 minutes <<EOF
/opt/etl/run.sh
echo "done"
EOF
Форматы времени
at понимает много форматов:
at 18:00 # сегодня в 18:00 (или завтра, если уже прошло)
at 18:00 tomorrow
at 18:00 2026-05-14
at noon # 12:00
at midnight # 00:00
at teatime # 16:00 (древняя british традиция)
at now + 1 hour
at now + 30 minutes
at now + 2 days
at 18:00 next mon # следующий понедельник в 18:00
Просмотр очереди: atq
$ atq
5 Wed May 14 18:00:00 2026 a etl
6 Wed May 14 03:00:00 2026 a etl
7 Thu May 15 12:00:00 2026 a etl
# Что внутри задачи 5:
$ at -c 5
#!/bin/sh
# atrun uid=1001 gid=1001
# mail etl 0
...
echo "Hello from at" > /tmp/at-test.log
/opt/etl/one-time-fix.sh
Удалить задачу: atrm
$ atrm 5
Логи
at отправляет stdout/stderr задачи email на user-владельца (как cron). Поэтому почти всегда — redirect внутрь команды:
$ at 18:00 tomorrow <<EOF
/opt/etl/run.sh > /var/log/at-job-$(date +%s).log 2>&1
EOF
Сам atd логирует в journal:
$ journalctl -u atd --since today
May 13 12:34:56 prod-vm atd[2345]: Job 5 will be executed at Wed May 14 18:00:00 2026
DE-сценарий: запланировать data backfill на выходные
Реальная ситуация: в пятницу вечером ты обнаружил, что нужно перезапустить ETL для исторического периода. На production-VM не хочешь запускать сейчас (рабочие часы, нагрузка). Хочешь, чтобы запустилось в субботу в 03:00, когда нагрузка минимальная.
$ at 03:00 saturday <<'EOF'
cd /opt/etl
./backfill.sh --start 2026-01-01 --end 2026-04-30 >> /var/log/backfill.log 2>&1
EOF
Готово. Скрипт запустится один раз в указанное время.
Альтернативы:
- systemd timer с
OnCalendar=Sat 03:00— но это recurring (каждую субботу). Можно после первого запускаsystemctl disable timer, но это hacky. OnCalendar=2026-05-16 03:00(точная дата) — запустится только один раз. Persistent работает, но нужно потом удалять unit.at— самый чистый для one-off.
anacron vs at: разные задачи
Не путать!
Все четыре сосуществуют на современной системе. Выбор зависит от задачи:
- One-off в будущем ->
at. - Recurring + persistent + dependencies + structured logs ->
systemd timer. - Recurring, простой однострочник, нет deps ->
cron. - Recurring, intermittent uptime, нет systemd ->
anacron.
Проверка доступа
at и cron имеют allow/deny списки. Если у тебя нет права использовать at:
$ at now + 1 minute <<<'echo hi'
You do not have permission to use at.
Проверь:
$ cat /etc/at.deny
guest
nobody
# Или (если есть):
$ cat /etc/at.allow
# Если этот файл существует, разрешено только перечисленным.
Аналогично для cron: /etc/cron.deny, /etc/cron.allow. На production иногда стоит ограничить — только определённые users могут планировать задачи.
Попробуй сам
- Что у тебя в anacrontab:
cat /etc/anacrontab 2>/dev/null || echo "anacron не установлен" - Когда последние запускались anacron jobs:
ls -la /var/spool/anacron/ 2>/dev/null - Установи
atи попробуй (если ещё нет):sudo apt install at sudo systemctl enable --now atd echo "echo 'hello from at' > /tmp/at-test.log" | at now + 2 minutes atq # Через 2 минуты: cat /tmp/at-test.log - Список запланированных at-задач:
atq - Удалить at-задачу:
atrm <JOB-ID>
macOS-различия
- На macOS
atесть, ноatdне запущен по умолчанию. Активация:sudo launchctl load -F /System/Library/LaunchDaemons/com.apple.atrun.plist. Sandbox-восстановления могут сломать. anacronна macOS обычно не используется — естьperiodic(свой launchd-based аналог) иpmsetдля wake-on-schedule.- Для one-off задач на macOS часто проще
launchdjob сStartCalendarInterval.
Главное
anacron— для машин с непостоянным uptime (laptops, desktops). Гарантирует «минимум раз в N дней». В/etc/anacrontab:PERIOD DELAY JOB-ID COMMAND.- На современных systemd-дистрибутивах
Persistent=trueв timer заменяет anacron. at— для одноразовых запланированных задач. Не recurring.at TIMEзапускает interactive prompt (Ctrl+D), либо через stdin.- Форматы времени:
18:00 tomorrow,now + 30 minutes,noon,next mon. atq— очередь,atrm JOB-ID— удалить.atшлёт stdout/stderr email (как cron) — redirect внутри команды.- Выбор инструмента:
- one-off в будущем ->
at; - recurring + production-grade -> systemd timer;
- recurring simple -> cron;
- recurring intermittent + нет systemd -> anacron.
- one-off в будущем ->
- Доступ:
/etc/at.allow,/etc/at.deny, аналогично для cron.