Jump to content

# cron (Русский)

From ArchWiki

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

Ссылки по теме

- systemd/Таймеры

Из Wikipedia:

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

## Установка

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

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

- cronie
- fcron
- dcronAUR
- vixie-cronAUR
- scron-gitAUR

## Настройка

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

После установки демон не включен по умолчанию. Установленный пакет предоставляет службу, которая управляется через 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 сервис уведомлений для периодического запроса подтверждения перед выполнением команды. Команды настраиваются в отдельном файле настроек.

cron (Русский)
Add topic