Журнал LinuxFormat - перейти на главную

LXF144:DrBrown3

Материал из Linuxformat
Перейти к: навигация, поиск

Содержание

Запуск по расписанию

Взглянем поближе на некоторые уровни файлов настройки Cron и Anacron, пары утилит для создания расписания запуска регулярных задач.

В этом месяце у меня урок из серии «назад к основам» – я расскажу все о Cron. Просмотрев предыдущие 37 статей из моих «Рецептов», я удивился, что не рассказывал об этом прежде.

С помощью трех утилит Cron, Anacron и at можно запланировать выполнение задач на будущее. Cron и Anacron – демоны: они прячутся в фоновом режиме, периодически просыпаясь и проверяя, не пора ли выполнить запланированную задачу. Оба позволяют планировать запуск задач через равные интервалы времени. Их названия происходят от имени греческого бога времени Хроноса. Это корень таких слов, как «хронология», «хронометр» и «хроника». at – нечто иное: это утилита командной строки, и с ее помощью можно запланировать однократный запуск программы в заданный момент времени в будущем. Однако и у at есть свой демон – atd, который отвечает за запуск задачи в соответствующий момент времени. Cron написал Пол Викси [Paul Vixie], также известный как автор Bind (DNS-сервер). Его другая более сомнительная попытка получить известность – рекорд по количеству сообщений CERT [безопасность] на одного автора.

Итак, я займусь Cron (и немного – Anacron). Более того, я сосредоточусь не на пользовательских таблицах crontab, а на системных заданиях Cron. Системные задания Cron могут выполняться от имени любого пользователя, но обычно запускаются от имени root. Эти задания определяются в файле /etc/crontab, хотя, как мы увидим позже, во многих дистрибутивах есть файлы второго уровня с самими описаниями заданий.

На рисунке [к сожалению в статье отстутствующем] показан синтаксис задачи в crontab. Как видите, время запуска задания указывается очень гибко. Единственное реальное ограничение – то, что минимальная степень точности – минута, и вы не сможете заставить свое задание выполняться каждые десять секунд. На другом конце временной шкалы можно указать день недели или месяца, хотя на практике вы вряд ли будете указывать то и другое одновременно. Если вы это сделаете, задание будет выполняться при соблюдении любого из условий, но надо ли вам запускать что-то «третьего числа каждого месяца и по понедельникам»?

LXF144 52 1.jpg

Файл /etc/anacrontab в RHEL5. Обратите внимание, что во втором поле заданы задержки, чтобы задачи не передрались за то, кому запускаться первым.

Задания можно записать прямо в файл /etc/crontab – и, честно говоря, в этом нет ничего постыдного. Это простое решение, и с ним все системные задания Cron можно увидеть, просто заглянув в один файл. Однако ни один современный дистрибутив Linux так не делает. Вместо этого в них задания Cron разбиваются на разные файлы – с часовыми, ежедневными, еженедельными и ежемесячными заданиями. На рисунке показан пример /etc/crontab, взятый из RHEL 5. На рисунке вы видите, что (например) каждое утро в 4:02 Cron вызывает команду run-parts с каталогом /etc/cron.daily в качестве аргумента. run-parts – это скрипт. Он сканирует все файлы в указанном каталоге и выполняет найденные в них команды. Эти команды – обычно тоже скрипты, но я не вижу причины, по которой в те же каталоги нельзя было бы поместить скомпилированные исполняемые файлы. Современные версии Cron также поддерживают обозначения @hourly, @daily и @weekly на месте временных параметров.

Схема с отдельными каталогами для часовых, ежедневных, еженедельных и ежемесячных заданий обладает лучшей масштабируемостью по сравнению со схемой, когда все команды записываются в файл /etc/crontab. Например, она позволяет установщикам пакетов класть скрипты в cron.daily, а Cron их подхватывает. Недостаток схемы в том, что разобраться, что Cron на самом деле запускает, можно только заглянув в несколько каталогов, набитых скриптами. Теряется и гибкость, так как нельзя распределить нагрузку, разделив выполнение четырех крупных задач на разные моменты в течение дня – все дневные задания будут стартовать в одно и то же время. Тем не менее, таков прогресс.

С ним пришел Anacron

Одна из вещей, усложняющих жизнь Cron в современных дистрибутивах Linux – появление конкурирующей утилиты под названием Anacron. Cron предназначен для компьютеров, работающих постоянно. Например, в Ubuntu ежедневные задания Cron по умолчанию выполняются в 6:25 утра. Если компьютер в это время не включен, задания вообще не выполнятся.

Для персональных компьютеров, которые бывают выключены, это не лучший вариант. Anacron гарантирует, что эти ежедневные, еженедельные и ежемесячные задания будут запущены, если компьютер включится хоть в какой-то момент в течение дня, недели или месяца. В отличие от Cron, Anacron не гарантирует, что задачи будут запущены в заданный момент времени, и с ним нельзя запланировать запуск какой-либо задачи чаще раза в день. Файл настройки Anacron/etc/anacrontab.

LXF144 53 1.jpg

Этот файл crontab, взятый из Ubuntu, заботится о том, чтобы Cron и Anacron не запустили одно и то же задание дважды.

Чтобы гарантировать слаженную совместную работу Cron и Anacron, нужна небольшая синтаксическая гимнастика. Во-первых, нужно убедиться, что одно и то же задание не запланировано дважды – и в Cron, и в Anacron. Решение, которое предлагает Ubuntu 10.04 в файле /etc/crontab, показано на рисунке выше.

По сути это работает точно так же, как и конфигурация RHEL 5, но здесь проводятся дополнительные проверки: если Anacron есть, то ежедневные, еженедельные и ежемесячные задания не выполняются – предполагается, что их запуск обеспечит Anacron. (Пояснения по синтаксису см. ниже в «Условия в командах оболочки».) Ежечасные задания Cron запускаются точно так же, как в RHEL 5 – путем запуска команд в /etc/cron.hourly.

В некоторых дистрибутивах, включая RHEL 6 и Fedora 14, файл /etc/crontab пуст, не считая нескольких комментариев. В более поздних версиях Cron, используемых в этих дистрибутивах, файлы в каталоге /etc/cron.d также проверяются на наличие заданий. Вы обнаружите, что часовые задания определены в /etc/cron.d/0hourly, который запускает команды из /etc/cron.hourly – это возвращает нас к изначальной модели поведения. Один из файлов в cron.hourly (0anacron) запускает Anacron. (Следите за моей мыслью, нет? – будьте внимательны!) В результате именно Anacron отвечает за запуск ежедневных, еженедельных и ежемесячных заданий.

Создаем собственные задания

Добавляя собственные задания в Cron, помните, что они запускаются без терминала, поэтому обязательно перенаправьте стандартный вывод в файл. Также немного подумайте об окружении, в котором будет запускаться задание. ID пользователя, конечно, будет соответствовать определенному в crontab (обычно это root, хотя с точки зрения безопасности лучше всего запускать задачу под пользователем, у которого есть минимум прав, достаточный для ее выполнения). Но как насчет пути поиска, текущего каталога и даже оболочки, в которой будет запускаться скрипт? Часто эти параметры задаются явно в crontab – снова взгляните на наш пример из RHEL5. Простой и быстрый способ проверить окружение выполнения Cron – добавить в crontab строку вроде этой:

* * * * * root env > /tmp/cronenv

подождать одну минуту и проверить содержимое /tmp/cronenv. (Не забудьте затем удалить строку из crontab.) После этого не нужно перезапускать Cron или отправлять ему сигнал HUP, чтобы сказать, что вы изменили crontab – он заметит изменения сам, когда проснется в следующий раз. Но помните, что если вы поместили свои задания для Cron в /etc/cron.d, они не унаследуют параметры окружения из /etc/crontab. Если у вас есть какие-то сомнения по поводу окружения, задайте его явно в начале скрипта и старайтесь указывать полные пути везде, где это возможно.

Отладка заданий Cron

Для каждого запускаемого задания Cron записывает строку в файл журнала. Вот фрагмент этого файла с одним из моих маленьких заданий env и с Anacron, запускающим еженедельные задания:

Feb 3 17:10:01 fedora14 CROND[2790]: (root) CMD (env > /tmp/cronenv)
Feb 3 17:10:02 fedora14 anacron[2165]: Job `cron.weekly’ started
Feb 3 17:10:02 fedora14 run-parts(/etc/cron.weekly)[2795]: starting 99-raid-check
Feb 3 17:10:02 fedora14 run-parts(/etc/cron.weekly)[2805]: finished 99-raid-check
Feb 3 17:10:02 fedora14 anacron[2165]: Job `cron.weekly’ terminated
Feb 3 17:10:02 fedora14 anacron[2165]: Normal exit (2 jobs run)

В Fedora файл журнала по умолчанию – /var/log/cron, а в Ubuntu – /var/log/syslog. В этих файлах появятся сообщения о синтаксических ошибках в crontab – например, о выходе временного параметра за пределы диапазона.

Также можно попросить Cron оповещать вас о любых проблемах по электронной почте, добавив в crontab строку:

MAILTO=root

Cron также будет отправлять по почте весь стандартный вывод задания, если вы забыли перенаправить его. Туда же придут и сообщения о синтаксических ошибках в скриптах – хотя, перед тем как запускать скрипт в Cron, вы должны были его проверить, правда?

О чем я не рассказал, но что заслуживает упоминания для полноты картины – то, что у отдельных пользователей могут быть собственные файлы crontab, в каталоге /var/spool/crontab/crontabs. Эти файлы нужно обновлять командой crontab -e, а не редактировать напрямую. Их синтаксис аналогичен синтаксису системного crontab, но в них нет поля «запустить от имени пользователя» [user to run as]. Из пользовательских файлов crontab можно запускать задания только от имени соответствую щего пользователя.

Варианты применения

Вот несколько примеров рутинных процедур, для выполнения которых системные администраторы могут воспользоваться Cron:

  • Ротация файлов журнала.
  • Обобщение файлов журнала с помощью утитит типа Logwatch и Webalizer.
  • Автоматическая проверка репозиториев дистрибутивов на наличие обновлений.
  • Повторная сборка базы данных locate (это база данных всех имен файлов системы, используемая командой locate).
  • Создание резервных копий файловой системы.
  • Удаление старых файлов из каталогов вроде /tmp.
  • Запуск процедуры обнаружения вторжений с помощью утилит типа Tripwire.
  • Запуск ночной сборки ПО.
  • Размещение фрагментов ваших файловых систем на удаленных компьютерах с помощью утилиты Rsync.

Условия в командах оболочки

В скриптах часто используются операторы && и ||, как условное обозначение операторов if/else. Вот как они работают.

Команда:

grep -q chris /etc/passwd && echo chris has an account

запускает первую команду (grep). Если она завершается успешно, запускается вторая команда (echo).

По-другому это можно записать так:

if grep -q chris /etc/passwd
 then
   echo chris has an account
 fi

но здесь уже четыре строки, а не одна – а, как известно, символы перевода строки в большом дефиците.

Другой пример. Команда:

grep -q xyzzy /etc/passwd || echo no such account

запускает первую команду, и если она завершается неудачно (в данном случае, если grep не находит xyzzy в файле passwd), вызывается вторая команда.

Применительно к задачам Cron и Anacron, обсуждаемым в данной статье, команда:

test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )

запускает run-parts только в том случае, если Anacron не найден.

Эти конструкции часто применяются при написании скриптов, но отражают стиль программирования «во какой я умный – я написал это с меньшим количеством строк, чем ты».

Персональные инструменты
купить
подписаться
Яндекс.Метрика