Jump to content

cron (Русский)

From ArchWiki

Состояние перевода: На этой странице представлен перевод статьи cron. Дата последней синхронизации: 9 декабря 2025. Вы можете помочь синхронизировать перевод, если в английской версии произошли изменения.

Из Wikipedia:

cron — планировщик задач в Unix-подобных операционных системах. cron позволяет пользователям планировать задачи (команды или консольные скрипты) для периодического запуска в определённые дни, даты или интервалы. Он обычно используется для автоматизации системного обслуживания или администрирования.

Установка

Существует множество реализаций cron, но ни одна не установлена по умолчанию, так как вместо них базовая система использует таймеры systemd. Сравнение возможностей разных реализаций cron есть в Gentoo Wiki.

Доступные пакеты:

Настройка

Активация и автозапуск

После установки демон не включен по умолчанию. Установленный пакет предоставляет службу, которая управляется через systemctl. Например, cronie использует cronie.service.

Проверьте /etc/cron.daily/ и подобные каталоги, чтобы увидеть, какие задачи установлены. Активация службы cron запустит их все.

Примечание cronie предоставляет ежечасную задачу 0anacron, которая позволяет откладывать запуск других задач к примеру, если компьютер был выключен в момент выполнения.

Обработка ошибок задач

cron регистрирует вывод из stdout и stderr и пытается отправлять их по электронной почте в spools пользователя через команду sendmail. Cronie отключает отправку писем, если /usr/bin/sendmail не найден. Чтобы письмо было отправлено в spool пользователя, должен быть запущен демон smtp, например opensmtpd. В ином случае вы можете установить пакет, который предоставляет команду sendmail, и настроить в нём отправку письма на удалённый почтовый сервер. Вы также можете логировать сообщения, используя опцию -m и написав свой скрипт.

Совет Можно отправлять письма локальным пользователям, используя Postfix#Local mail.
  1. Отредактируйте юнит cronie.service.
  2. Установите esmtpAUR, msmtp, opensmtpd, sSMTP, или напишите свой скрипт.

Пример с sSMTP

sSMTP — это эмулятор sendmail, который отправляет письма с локального компьютера на сервер smtp. Хоть у него и нет активных сопроводителей, это всё ещё самый простой способ отправить письмо в настроенный почтовый центр. У него нет демонов для запуска, и для настройки достаточно просто изменить 3 строки в файле настроек (если ваш хост является доверенным и может отправлять письма без аутентификации). sSMTP не поддерживает приём писем, использование псевдонимов или управление очередями.

Установите ssmtpAUR, который создаст символическую ссылку из /usr/bin/sendmail в /usr/bin/ssmtp. Затем отредактируйте файл настроек /etc/ssmtp/ssmtp.conf — подробнее в статье sSMTP. Наличие символической ссылки /usr/bin/sendmail гарантирует, что программы вроде S-nail (или любой другой пакет, который предоставляет /usr/bin/mail) будут работать без изменений.

Перезапустите cronie.service, чтобы он обнаружил установленный /usr/bin/sendmail.

Пример с msmtp

Установите msmtp-mta, который создаст символическую ссылку из /usr/bin/sendmail в /usr/bin/msmtp. Перезапустите cronie.service, чтобы он обнаружил команду sendmail. После этого нужно настроить способ преобразования имени пользователя в почтовый адрес.

Добавьте строку MAILFROM в crontab:

MAILFROM=your@email.com
Примечание Без MAILFROM сервер smtp будет ругаться на ошибки в заголовках.

Затем добавьте строку MAILTO в ваш crontab, например как:

MAILTO=your@email.com

или создайте /etc/msmtprc и добавьте эту строку:

aliases /etc/aliases

и создайте /etc/aliases:

your_username: your@email.com
# Опционально:
default: your@email.com

Затем отредактируйте юнит cronie.service, заменив команду ExecStart на:

ExecStart=/usr/bin/crond -n -m '/usr/bin/msmtp -t'

Пример с esmtp

Установите esmtpAUR и procmailAUR.

После установки настройте маршруты:

/etc/esmtprc
identity myself@myisp.com
       hostname mail.myisp.com:25
       username "myself"
       password "secret"
       starttls enabled
       default
mda "/usr/bin/procmail -d %T"

Procmail требует права суперпользователя, чтобы работать в режиме отправки, но это не проблема, если вы запускаете задачи cron от имени root.

Для проверки работоспособности создайте файл message.txt с содержимым "test message".

В том же каталоге запустите:

$ sendmail имя_пользователя < message.txt

затем:

$ cat /var/spool/mail/имя_пользователя

Теперь вы должны увидеть тестовое сообщение со временем и датой отправки.

Вывод ошибок всех задач будет появляться в /var/spool/mail/имя_пользователя.

Из-за проблем с правами доступа отправлять письма пользователю root (к примеру su -c "") затруднительно. Вы можете попросить esmtp переадресовать все письма root к определённому пользователю с помощью:

/etc/esmtprc
force_mda="user-name"
Примечание Если тест выше не сработал, вы можете создать локальную конфигурацию в ~/.esmtprc с таким же содержимым.

Запустите следующую команду для установки корректных прав доступа к файлу:

$ chmod 710 ~/.esmtprc
Затем повторите описанный выше тест с message.txt.

Пример с opensmtpd

Установите opensmtpd.

Отредактируйте /etc/smtpd/smtpd.conf. Данная конфигурация разрешает локальную отправку:

listen on localhost
action "local" mbox alias <aliases>
match for local action "local"

Вы можете протестировать её. Сначала запустите smtpd.service. Затем выполните:

$ echo test | sendmail пользователь

пользователь может проверить свою входящую почту любым почтовым клиентом, поддерживающим формат mbox, или просто просмотреть файл /var/spool/mail/пользователь. Если всё работает как ожидалось, вы можете включить opensmtpd, чтобы он запускался при загрузке системы.

Этот подход имеет преимущество в том, что он не отправляет локальные уведомления cron на удалённый сервер. С другой стороны, вам нужно запускать отдельного демона.

Примечание
  • На момент написания статьи пакет opensmtpd в Arch не создаёт все необходимые каталоги в /var/spool/smtpd, но демон предупредит об этом, указав необходимые права доступа. Просто создайте их в соответствии с указаниями демона.
  • Несмотря на то, что предлагаемая конфигурация не принимает удалённые подключения, в качестве дополнительной меры предосторожности рекомендуется заблокировать порт 25 с помощью iptables или другого межсетевого экрана.

Долгие задачи cron

Представим, что в cron запускается такая программа:

#!/bin/sh
echo "I had a recoverable error!"
sleep 1h

Что здесь происходит:

  1. cron запускает скрипт
  2. как только cron видит вывод, он запускает программу для отправки почты и предоставляет ему заголовки. Он оставляет канал открытым, потому что задача не завершена и у неё может быть ещё вывод.
  3. программа для отправки почты подключается к postfix и оставляет соединение открытым, пока она ждёт остальное тело сообщения.
  4. postfix закрывает бездействующее соединение менее чем через час, и вы получаете примерно такую ошибку:
    smtpmsg='421 … Error: timeout exceeded' errormsg='the server did not accept the mail'

Чтобы решить эту проблему, вы можете использовать chronic или sponge из пакета moreutils. Сводка из их страниц man:

chronic(1)
chronic запускает команду, и организует отображение её стандартного вывода и стандартных ошибок только если команда завершилась неудачно (код выхода не ноль или падение). Если команда выполняется удачно, любой вывод будет скрыт.
sponge(1)
sponge читает стандартный ввод и выводит его в указанный файл. В отличие от использования переадресации в командной оболочке, sponge «впитывает» весь ввод перед открытием файла для вывода. Если файл для вывода не указан, sponge выводит в stdout.

Chronic также буферизирует вывод команды перед открытием своего стандартного вывода.

Формат crontab

Файл crontab состоит из строк в таком формате:

минуты часы день_месяца месяц день_недели команда
  • минуты могут быть от 0 до 59.
  • часы могут быть от 0 до 23.
  • день_месяца может быть от 1 до 31.
  • месяц может быть от 1 до 12.
  • день_недели может быть от 0 до 6, где 0 обозначает воскресенье.

Для разделения полей используются пробелы. Для более тонкой настройки расписания также можно использовать один из следующих символов:

Символ Описание
* Обозначает любой возможный временной интервал
, Список из нескольких значений, разделённых запятой
- Обозначает диапазон между двумя числами, разделёнными дефисом
/ Обозначает периодичность/частоту с помощью косой черты

Для примера, строка:

*/5 9-16 * 1-5,9-12 1-5 ~/bin/i_love_cron.sh

будет запускать скрипт i_love_cron.sh каждые пять минут с 9:00 до 16:55 в будние дни каждый месяц, кроме июня, июля и августа.

В дополнение, crontab имеет несколько ключевых слов:

Keyword Description
@reboot при загрузке системы
@yearly раз в год
@annually идентично @yearly
@monthly раз в месяц
@weekly раз в неделю
@daily раз в день
@midnight идентично @daily
@hourly раз в час

К примеру:

@reboot ~/bin/i_love_cron.sh

выполнит скрипт i_love_cron.sh при загрузке системы.

Читайте больше на: https://www.adminschoice.com/crontab-quick-reference

Другие примеры и продвинутые техники настройки описаны ниже.

Базовые команды

Никогда не стоит редактировать файлы crontab напрямую; вместо этого используйте команду crontab для работы с ними.

Чтобы увидеть ваши crontabs:

$ crontab -l

Чтобы отредактировать ваши crontabs:

$ crontab -e

Чтобы удалить все ваши crontabs:

$ crontab -r

Если у вас есть сохранённый crontab и вы хотите полностью переписать ваш старый crontab:

$ crontab имя_файла_сохранённого_crontab

Чтобы переписать crontab из командной строки (stdin):

$ crontab -

Чтобы отредактировать чужой crontab:

# crontab -u имя_пользователя -e

Такой же формат (применяя -u имя_пользователя к команде) работает для отображения и удаления crontabs.

Примеры

Строка:

01 * * * * /bin/echo Hello, world!

выполняет команду /bin/echo Hello, world! в первую минуту каждого часа каждого дня каждого месяца (к примеру в 12:01, 1:01, 2:01 и так далее).

Подобно:

*/5 * * jan mon-fri /bin/echo Hello, world!

выполняет ту же задачу каждые пять минут по будням на протяжении января (к примеру в 12:00, 12:05, 12:10 и так далее).

Строка (как указано в crontab(5)):

*/5 9-16 * 1-5,9-12 1-5 /home/user/bin/i_love_cron.sh

будет запускать скрипт i_love_cron.sh каждые пять минут с 9:00 до 16:55 в будние дни каждый месяц, кроме июня, июля и августа.

Периодичность также можно указать как в этом шаблоне crontab:

# Хронологическая таблица загрузки программ
# Редактируйте через "crontab" для правильной работы, "man 5 crontab" для справки по форматированию
# Пользователь: archie

# мм  чч  ДД  ММ  ДН  /путь/к/программе [--опции]...  ( ДН = день недели: 0-6 [Вс=0] )
  21  01  *   *   *   /usr/bin/systemctl hibernate
  @weekly             $HOME/.local/bin/trash-empty

Вот несколько наглядных примеров синтаксиса crontab:

30 4 echo "Сейчас 4:30."
0 22 echo "Сейчас 10 часов вечера."
30 15 31 12 echo "Сейчас 15 часов 30 минут в Новый Год."
30 3 * * * echo "Напоминание каждый день в 3 часа 30 минут."
0 * * * * echo "Это начало нового часа."
0 6 1,15 * * echo "6 часов утра 1 и 15 числа каждого месяца."
0 6 * * 2,3,5 echo "6 часов утра по вторникам, средам и пятницам."
59 23 * * 1-5 echo "Прямо перед полуночью в будние дни."
0 */2 * * * echo "Каждые два часа."
0 20 * * 4 echo "8 часов вечера в четверг."
0 20 * * Thu echo "8 часов вечера в четверг."
*/15 9-17 * * 1-5 echo "Каждые 15 минут с 9 утра до 5 вечера в будние дни."
@yearly echo "С Новым Годом!"

Редактор по умолчанию

Чтобы задать редактор, используемый при редактировании через команду crontab, задайте переменную окружения EDITOR в настройках вашей командной оболочки.

Чтобы эта переменная использовалась при редактировании от имени суперпользователя, используйте su вместо sudo:

$ su -c "crontab -e"

Чтобы сделать псевдоним для этой команды, нужно использовать printf для экранирования, потому что su выполняется в новой оболочке:

alias scron="su -c $(printf "%q " "crontab -e")"

Выполнение программ Xorg

Cron запускается не в среде Xorg, так что он не предоставляет переменные окружения, необходимые для графических приложений, поэтому вам нужно указать их самостоятельно. Можно использовать программу вроде xuserrun-gitAUR для этого:

17 02 * ... /usr/bin/xuserrun /usr/bin/xclock

Или они могут быть указаны вручную (echo $DISPLAY даст текущее значение DISPLAY):

17 02 * ... env DISPLAY=:0 /usr/bin/xclock

Если в скрипте, выполняемом через cron, используется команда notify-send для отправки уведомлений, ей необходим адрес для подключения к пользовательской шине dbus. Он находится в переменной окружения DBUS_SESSION_BUS_ADDRESS. Укажите такое же значение в crontab:

17 02 * ... env DBUS_SESSION_BUS_ADDRESS=ваш-адрес notify-send 'Пуки Каки'

Если сделано через SSH, нужно выдать разрешения:

# xhost +si:localuser:$(whoami)

Асинхронное выполнение задач

Если вы периодически выключаете ваш компьютер, но не хотите терять задачи, есть несколько решений (от простых к сложным):

Cronie

cronie поставляется с anacron. Домашняя страница проекта гласит:

Cronie содержит стандартный UNIX-демон crond, который выполняет указанные команды в запланированное время, и связанные инструменты. Он основан на оригинальном cron и имеет улучшения безопасности и конфигурации, такие как возможность использовать pam и SELinux.

Dcron

Ванильный dcronAUR поддерживает асинхронное выполнение задач. Просто укажите @hourly, @daily, @weekly или @monthly с именем задачи, вроде такого:

@hourly         ID=лучшая_задача      echo Эта задача очень полезна.

Cronwhip

cronwhipAUR — это скрипт, который автоматически выполняет пропущенные задачи cron; он работает со стандартной реализацией cron, dcron. Смотрите также тему на форуме.

Anacron

Anacron — полная замена dcron, которая выполняет задачи асинхронно.

Его предоставляет cronie. Файл настроек — /etc/anacrontab. Информация о формате доступна в anacrontab(5). Запуск anacron -T протестирует /etc/anacrontab на правильность.

Fcron

Как и anacron, fcron предполагает, что компьютер запущен не постоянно, и, в отличие от anacron, может планировать задачи с интервалами короче одного дня, что может быть полезно для систем, которые постоянно уходят в сон/гибернацию (как ноутбуки). Как и cronwhip, fcron может запускать задачи, которые должны были быть запущены в то время, пока компьютер был выключен.

При замене cronie на fcron имейте в виду, что используется каталог spool /var/spool/fcron, а для редактирования задач вместо команды crontab используется fcrontab. Задачи хранятся в бинарном формате рядом с их текстовыми версиями foo.orig в каталоге spool. Скрипты, которые самостоятельно редактируют задачи, могут требовать адаптации под fcron из-за этих различий.

Вот простой скрипт, который может помочь с конвертацией традиционных crontabs в формат fcron:

cd /var/spool/cron && (
 for ctab in *; do
  fcrontab ${ctab} -u ${ctab}
 done
)

Смотрите также тему на форуме.

Проверка единичного экземпляра

Если вы запускаете потенциально долгоиграющие задания (например, резервное копирование может выполняться очень долго из-за большого числа изменений или медленного интернет-соединения), то с помощью команды flock (предоставляется пакетом util-linux) можно предотвратить повторный запуск задачи, которая ещё не завершила свою работу.

  5,35 * * * * /usr/bin/flock -n /tmp/lock.backup /root/make-backup.sh

Cronie

Это соответствующая иерархия файлов для cronie:

   /etc/
     |----- cron.d/
              | ----- 0hourly
     |----- cron.minutely/
     |----- cron.hourly/
              | ----- 0anacron
     |----- anacrontab
     |----- cron.daily/
     |----- cron.monthly/
     |----- cron.weekly/
     |----- crontab
     |----- cron.deny

Cronie предоставляет функциональность и cron, и anacron: cron выполняет задания с указанными интервалами времени (с точностью до минуты), пока система включена, а anacron выполняет команды в интервалы, указанные в днях, и не предполагает безостановочную работу системы. При загрузке системы anacron проверяет, есть ли какие-то задачи, которые должны были быть выполнены, и занимается ими соответственно.

Задачи cron могут быть указаны в crontab-подобном файле в каталоге /etc/cron.d/ или добавлены в файл /etc/crontab. Имейте в виду, что этот файл отсутствует по умолчанию, но будет использоваться, если его создать. Как указано в /etc/cron.d/0hourly, любой исполняемый файл в каталоге /etc/cron.hourly/ будет запускаться каждый час (по умолчанию в 1 минуту часа). Файлы в каталоге /etc/cron.minutely/ выполняются каждую минуту, если указано соответствующее в /etc/cron.d/0minutely. Исполняемые файлы — это чаще всего консольные скрипты, также могут быть использованы символические ссылки на исполняемые файлы. Файл /etc/cron.deny содержит список пользователей, которым не разрешено использовать crontab; без этого файла только пользователи, указанные в файле /etc/cron.allow, смогут его использовать.

Anacron работает похожим образом, выполняя файлы в каталогах /etc/cron.daily/, /etc/cron.weekly/ и /etc/cron.monthly/, располагаемые в соответствии с нужным расписанием их запуска. Задача /etc/cron.hourly/0anacron убеждается, что anacron запускается раз в сутки, чтобы выполнить ожидающие задания.

Примечание
  • Cronie использует run-parts, чтобы исполнять скрипты из каталогов. Имена файлов не должны включать любые точки (.) из-за того, что run-parts в режиме по умолчанию будет молча их игнорировать (смотрите run-parts(8)). Имена должны состоять только из букв верхнего и нижнего регистра, цифр, нижних подчёркиваний и дефисов.
  • Вывод systemctl status cronie может содержать сообщение вроде CAN'T OPEN (/etc/crontab): No such file or directory. Впрочем, его можно игнорировать, так как наличие данного файла необязательно.
  • Для cronie важны разрешения файла /etc/cron.d/0hourly. Ни одна задача в /etc/cron.d/{hourly,weekly,daily} ... и т.д. не будет запущена (в том числе anacron лаунчер), если /etc/cron.d/0hourly повреждён или имеет неправильные разрешения. pacman -Qkk cronie может показать наличие этих проблем.
Совет Чтобы предотвратить отправку вывода и остановить почтовые оповещения, добавьте >/dev/null 2>&1 в конец строки каждой задачи cron для перенаправления вывода в /dev/null.
0 1 5 10 * /путь/до/скрипта.sh >/dev/null 2>&1
Также можно указать переменную MAILTO=”” в файле crontab для отключения почтовых оповещений.

Dcron

Демон cron проверяет файл настроек, известный как crontab. Каждый системный пользователь может поддерживать отдельный файл crontab для индивидуального планирования задач. Crontab пользователя root используется для планирования общесистемных задач (также пользователи могут опционально использовать /etc/crontab или каталог /etc/cron.d/, в зависимости от выбранной реализации cron).

/var/spool/cron/root
# Run command at a scheduled time
# Edit this 'crontab -e' for error checking, man 1 crontab for acceptable format

# <@freq>                       <tags and command>
@hourly         ID=sys-hourly   /usr/sbin/run-cron /etc/cron.hourly
@daily          ID=sys-daily    /usr/sbin/run-cron /etc/cron.daily
@weekly         ID=sys-weekly   /usr/sbin/run-cron /etc/cron.weekly
@monthly        ID=sys-monthly  /usr/sbin/run-cron /etc/cron.monthly

# mm  hh  DD  MM  W /path/command (or tags) # W = week: 0-6, Sun=0
  21  01  *   *   * /usr/bin/systemctl suspend

Каждая строка crontab является набором полей, разделённых пробелами, один из возможных форматов значений:

  1. @период
  2. ID=имязадачи (этот флаг специфичен для dcron)
  3. команда

Другой стандартный формат полей в crontab:

  1. минута
  2. час
  3. день
  4. месяц
  5. день недели
  6. команда

Файлы crontab сами по себе обычно хранятся в /var/spool/cron/имя_пользователя. Например, crontab пользователя root находится в /var/spool/cron/root

Подробнее в man-странице crontab(5).

Смотрите также

  • Gentoo Linux Cron Guide
  • crontab.guru — онлайн-редактор задач cron
  • cron-notifyAUR — совместимый с FreeDesktop.org сервис уведомлений для периодического запроса подтверждения перед выполнением команды. Команды настраиваются в отдельном файле настроек.