cron (Русский)

From ArchWiki
Jump to: navigation, search

Tango-preferences-desktop-locale.pngЭта страница нуждается в сопроводителеTango-preferences-desktop-locale.png

Статья не гарантирует актуальность информации. Помогите русскоязычному сообществу поддержкой подобных страниц. См. Команда переводчиков ArchWiki

Из Википедии:

cron - классический демон-планировщик задач в UNIX-подобных операционных системах, использующийся для периодического выполнения заданий в определённое время. Регулярные действия описываются инструкциями, помещенными в файлы crontab и в специальные директории.

Установка

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

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

Настройка

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

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

Текущие активные задания расположены в папках вроде /etc/cron.daily/ и запуск службы cron активирует их все.

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

Обработка ошибок в заданиях

cron регистрирует стандартный вывод из stdout и stderr и пытается отправить его на электронную почту пользователя используя команду sendmail. В cronie такие сообщения на электронную почту отключены, если отсутствует файл /usr/bin/sendmail. Для того, чтобы электронные письма направлялись пользователю, в системе должен быть запущен smtp-демон, например opensmtpd. Также вы можете установить пакет, который предоставляет команду sendmail и настроить его на отсылку почту удаленному адресату. Ну и наконец, вы можете вести лог при помощи команды -m и скрипта.


Пример с msmtp

Tango-view-fullscreen.pngThis article or section needs expansion.Tango-view-fullscreen.png

Reason: How exactly do I make sure it detects the new sendmail command? (Discuss in Talk:Cron (Русский)#)

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

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

MAILTO=your@email.com

либо создайте файл /etc/msmtprc и напишите в него строку:

aliases /etc/aliases

Создайте файл /etc/aliases:

your_username: your@email.com
# Optional:
default: your@email.com

Затем измените конфигурацию демона cronie заменив команду ExecStart на:

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

Пример с esmtp

Установите esmtp и procmail.

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

/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 user_name < message.txt 

Затем:

$ cat /var/spool/mail/user_name

Вы должны увидеть тестовое сообщение, а также время и дату его отправки.

Поток ошибок всех активных заданий теперь перенаправлен в /var/spool/mail/user_name.

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

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

Выполните следующую команду, чтобы дать необходимые права:

$ chmod 710 ~/.esmtprc

Затем повторите тест с отправкой message.txt точно так же, как описано выше.

Пример с opensmtpd

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

Отредактируйте /etc/smtpd/smtpd.conf. Следующая конфигурация подходит для локальной доставки почты:

listen on localhost
accept for local deliver to mbox

Можете начинать тестировать ее. Для начала запустите smtpd.service. Затем:

$ echo test | sendmail user

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

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

Note:
  • На момент написания статьи пакет opensmtpd не создает все необходимые папки в /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
chronic запускает команду и организовывает ее стандартные потоки вывода и ошибок так, что отображается только неправильный результат работы программы (выход с ненулевым значением или сбой). Если команда выполнена успешно, любые дополнительные выходные данные будут скрыты.
sponge
sponge получает стандартный входной поток и пишет его в специальный файл. В отличие от перенаправления командной строки, sponge аггрегирует весь свой входной поток в выходной файл. Если выходной файл не указан, sponge выводит данные в stdout.

Даже если это не указано явно, chronic буферизирует выходные данные команды перед тем, как открыть stdout (как и sponge)

Формат 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 AM до 4:55 PM по будням (уточнить, неделя может начинаться с воскресенья) кроме летних месяцев (июнь, июль, август). Больше примеров и дополнительные настройки могут быть найдены ниже.

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

Crontabs никогда не редактируются напрямую; вместо этого пользователи должны использовать crontab утилиту для работы со своими crontabs. Чтобы получить доступ к этой утилите, пользователь должен быть членом группы users (смотри команду gpasswd).

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

$ crontab -l

Для редактирования своих crontabs:

$ crontab -e
Note: По умолчанию команда crontab использует редактор vi. Чтобы изменить это, экспортируйте EDITOR или VISUAL, или укажите редактор напрямую: EDITOR=vim crontab -e.

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

$ crontab -r

Если пользователь имеет сохранённые crontab и хочет полностью перезаписать свои старые crontab, он может воспользоваться:

$ crontab saved_crontab_filename

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

$ crontab - 

Чтобы отредактировать чьи-либо ещё crontab, вызовите следующую команду из под root:

# crontab -u username -e

Этот же формат (присоединяя -u username к команде) работает так же для чтения и удаления crontabs.

Примеры

Запись:

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

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

Аналогично:

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

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

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

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

вызывает скрипт i_love_cron.sh в пятиминутные интервалы с 9 AM до 5 PM (не включая 5 PM) каждый будний день каждого месяца, кроме летних.

Periodical settings can also be entered as in this crontab template:

# Chronological table of program loadings                                       
# Edit with "crontab" for proper functionality, "man 5 crontab" for formatting
# User: johndoe

# mm  hh  DD  MM  W /path/progam [--option]...  ( W = weekday: 0-6 [Sun=0] )
  21  01  *   *   * /usr/bin/systemctl hibernate
  @weekly           $HOME/.local/bin/trash-empty

Default editor

To use an alternate default editor, define the EDITOR environment variable in a shell initialization script as described in Environment variables.

As a regular user, su will need to be used instead of sudo for the environment variable to be pulled correctly:

$ su -c "crontab -e"

To have an alias to this printf is required to carry the arbitrary string because su launches in a new shell:

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

run-parts issue

cronie uses run-parts to carry out script in cron.daily/cron.weekly/cron.monthly. Be careful that the script name in these won't include a dot (.), e.g. backup.sh, since run-parts without options will ignore them (see: run-parts(8)).

Running X.org server-based applications

Cron does not run under the X.org server therefore it cannot know the environmental variable necessary to be able to start an X.org server application so they will have to be defined. One can use a program like xuserrunAUR[ссылка недействительна: сохранено в aur-mirror] to do it:

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

Or then can be defined manually (echo $DISPLAY will give the current DISPLAY value):

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

If done through say SSH, permission will need be given:

# xhost +si:localuser:$(whoami)

Asynchronous job processing

If you regularly turn off your computer but do not want to miss jobs, there are some solutions available (easiest to hardest):

Cronie

cronie comes with anacron included. The project homepage reads:

Cronie contains the standard UNIX daemon crond that runs specified programs at scheduled times and related tools. It is based on the original cron and has security and configuration enhancements like the ability to use pam and SELinux.

Dcron

Vanilla dcronAUR supports asynchronous job processing. Just put it with @hourly, @daily, @weekly or @monthly with a jobname, like this:

@hourly         ID=greatest_ever_job      echo This job is very useful.

Cronwhip

cronwhipAUR is a script to automatically run missed cron jobs; it works with the former default cron implementation, dcron. See also the forum thread.

Anacron

Anacron is a full replacement for dcron which processes jobs asynchronously.

It is provided by cronie. The configuration file is /etc/anacrontab. Information on the format can be found in the anacrontab(5) man page. Running anacron -T will test /etc/anacrontab for validity.

Fcron

Like anacron, fcron assumes the computer is not always running and, unlike anacron, it can schedule events at intervals shorter than a single day which may be useful for systems which suspend/hibernate regularly (such as a laptop). Like cronwhip, fcron can run jobs that should have been run during the computer's downtime.

When replacing cronie with fcron be aware the spool directory is /var/spool/fcron and the fcrontab command is used instead of crontab to edit the user crontabs. These crontabs are stored in a binary format with the text version next to them as foo.orig in the spool directory. Any scripts which manually edit user crontabs may need to be adjusted due to this difference in behavior.

A quick scriptlet which may aide in converting traditional user crontabs to fcron format:

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

See also the forum thread.

Ensuring exclusivity

If you run potentially long-running jobs (e.g., a backup might all of a sudden run for a long time, because of many changes or a particular slow network connection), then flock (util-linux) can ensure that the cron job won't start a second time.

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

cronie

Long time users of vixie-cron (traditional cron) will be confused by how cronie is set up. Here is the relevant file hierarchy:

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


Note that the crontab file is not created by default, but jobs added here will be run if you wish to use this file. Cronie provides both cron and anacron functionality. The difference is that cron will run jobs at particular time intervals (down to a granularity of one minute) if the machine is on at the particular time specified, while anacron runs jobs (with a minimum daily granularity) without assuming that the machine is turned on all the time. When the machine is on, anacron will check to see if there are any jobs that should have been run and will run them accordingly. The /etc/cron.d and /etc/cron.hourly directories are associated with cron functionality, while the /etc/anacrontab file and /etc/cron.daily, /etc/cron.weekly, and /etc/cron.monthly directories are associated with anacron functionality. The /etc/cron.deny file is there so that any user who is not specifically prohibited can create their own cron jobs.

To implement a system-wide cron job, create a crontab-like file for it and place it in the /etc/cron.d directory or add the job to /etc/crontab. Any executable (these are almost always shell scripts) in /etc/cron.hourly will be run every hour.

Anacron functionality is implemented similarly, however using the /etc/cron.daily, /etc/cron.weekly, or /etc/cron.monthly directories, depending on how frequently you want the job to be run. The anacron job files are also executables; i.e. not in crontab-format. Anacron is triggered at the beginning of every hour by the crontab file /etc/cron.d/0hourly which runs the executables in /etc/cron.hourly including the file /etc/cron.hourly/0anacron - deleting these will prevent anacron running any daily, weekly or monthly tasks.

Note: the output of systemctl status cronie might show a message such as crond[<PID>]: (root) CAN'T OPEN (/etc/crontab): No such file or directory. However, this is not an error as of cronie 1.4.8. See this discussion.

Dcron

The cron daemon parses a configuration file known as crontab. Each user on the system can maintain a separate crontab file to schedule commands individually. The root user's crontab is used to schedule system-wide tasks (though users may opt to use /etc/crontab or the /etc/cron.d directory, depending on which cron implementation they choose).

/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

These lines exemplify one of the formats that crontab entries can have, namely whitespace-separated fields specifying:

  1. @period
  2. ID=jobname (this tag is specific to dcron)
  3. command

The other standard format for crontab entries is:

  1. minute
  2. hour
  3. day
  4. month
  5. day of week
  6. command

The crontab files themselves are usually stored as /var/spool/cron/username. For example, root's crontab is found at /var/spool/cron/root

See the crontab man page for further information and configuration examples.

See also