··done < $1 # читать файл crontab, имя которого передано
············#·· сценарию в виде аргумента
··# Обратите внимание: в самом конце цикла while выполняется перенаправление
··#·· ввода, чтобы сценарий мог исследовать файл с именем, указанным
··#·· пользователем!
··echo "Done. Found $totalerrors errors in $entries crontab entries."
··exit 0
Как это работает
Самую большую проблему тут представляет механизм подстановки в командной оболочке, стремящийся заменить звездочки в значениях полей (*). Звездочка — вполне допустимый символ для полей в записях cron и в действительности используется очень широко, но, если попытаться передать его подоболочке посредством конструкции $() или канала, командная оболочка автоматически заменит звездочку списком файлов в текущем каталоге, что, конечно же, нежелательно. Вместо того чтобы ломать голову над применением комбинаций двойных и одиночных кавычек для обхода этой проблемы, мы решили, что проще заменить все звездочки символом X, что и делает функция fixvars
Также следует отметить простоту решения, использованного для обработки списков значений, разделенных запятыми и дефисами. Знаки пунктуации просто замещаются пробелами, и каждое значение анализируется, как если бы оно было отдельным числом. Именно это делает конструкция $() в цикле for, в строках
$(echo "$dow" | sed 's/[,-]/ /g')
Она упрощает обход всех числовых значений и их проверку на принадлежность диапазону, допустимому для конкретного поля в crontab.
Запуск сценария
Этот сценарий легко запускается: просто передайте ему единственный аргумент с именем файла crontab. В листинге 6.9 приводится пример проверки существующего файла crontab.
Листинг 6.9. Запуск сценария verifycron после экспортирования текущего файла cron
$ crontab −l > my.crontab
$ verifycron my.crontab
$ rm my.crontab
Результаты
Для примера файла crontab, содержащего две ошибки и много комментариев, сценарий вывел результаты, показанные в листинге 6.10.
Листинг 6.10. Результаты проверки файла cron с ошибочными записями с помощью сценария verifycron
$ verifycron sample.crontab
Line 10: Invalid day of week value "Mou"
>>>> 10: 06 22 * * Mou /home/ACeSystem/bin/del_old_ACinventories.pl
Line 12: Invalid minute value "99"
>>>> 12: 99 22 * * 1–3,6 /home/ACeSystem/bin/dump_cust_part_no.pl
Done. Found 2 errors in 13 crontab entries.
Пример файла сценария с двумя ошибками, а также все сценарии, описываемые в этой книге, доступны для загрузки по адресу: http://www.nostarch.com/wcss2/.
Усовершенствование сценария
В этот сценарий стоило бы добавить несколько усовершенствований. Для начала — проверку допустимости комбинации число/месяц, чтобы пользователи не могли запланировать выполнение задания cron, например, на 31 февраля. Также было бы полезно проверить присутствие запланированной команды в системе, но для этого необходимо выполнить парсинг окончаний записей и обработать переменную PATH (то есть список каталогов, где происходит поиск команд, указанных в сценарии), которая может явно определяться внутри файла crontab. Это довольно непросто… Наконец, попробуйте добавить поддержку таких значений, как @hourly или @reboot, имеющих специальное назначение в cron и применяемых для обозначения времени вызова сценария.
№ 49. Запуск заданий cron вручную
До недавнего времени системы Linux предназначались для работы на серверах, действующих 24 часа в сутки, 7 дней в неделю, постоянно. Это отразилось на реализации планировщика cron: бессмысленно планировать выполнение задание на 2:17 ночи в каждый вторник, если система выключается каждый вечер в 18:00.
Однако многие современные системы Unix и Linux работают на настольных компьютерах и ноутбуках обычных пользователей, которые выключают их в конце дня. Далеко не все пользователи OS X, например, оставляют свои компьютеры включенными на ночь, на выходные или на праздники.