··# Выполнить обход строк в файле crontab и проверить каждую в отдельности.
··while read min hour dom mon dow command
··do
····lines="$(($lines + 1))"
····errors=0
····if [-z "$min" −o "${min%${min#?}}" = "#"]; then
······# Если это пустая строка или начинается с символа "#", пропустить ее.
······continue··# Ничего проверять не надо
····fi
····((entries++))
····fixvars
····# В этой точке все поля в текущей строке перенесены в отдельные
····#·· переменные, все звездочки заменены символом "X" для удобства,
····#·· поэтому можно приступать к проверке полей…
····# Проверка минут
····for minslice in $(echo "$min" | sed 's/[,-]/ /g'); do
······if! validNum $minslice 60; then
········echo "Line ${lines}: Invalid minute value \"$minslice\""
········errors=1
······fi
····done
····# Проверка часов
····for hrslice in $(echo "$hour" | sed 's/[,-]/ /g'); do
······if! validNum $hrslice 24; then
········echo "Line ${lines}: Invalid hour value \"$hrslice\""
········errors=1
······fi
····done
····# Проверка дня месяца
····for domslice in $(echo $dom | sed 's/[,-]/ /g'); do
······if! validNum $domslice 31; then
········echo "Line ${lines}: Invalid day of month value \"$domslice\""
········errors=1
······fi
····done
····# Проверка месяца: нужно проверить числовые значения и названия.
····#·· Запомните, что условные инструкции вида "if! cond" проверяют
····#·· ЛОЖНОСТЬ утверждения, а не истинность.
····for monslice in $(echo "$mon" | sed 's/[,-]/ /g'); do
······if! validNum $monslice 12; then
········if! validMon "$monslice"; then
··········echo "Line ${lines}: Invalid month value \"$monslice\""
··········errors=1
········fi
······fi
····done
····# Проверка дня недели: так же может быть числом или названием.
····for dowslice in $(echo "$dow" | sed 's/[,-]/ /g'); do
······if! validNum $dowslice 7; then
········if! validDay $dowslice; then
··········echo "Line ${lines}: Invalid day of week value \"$dowslice\""
··········errors=1
········fi
······fi
····done
····if [$errors −gt 0]; then
······echo ">>>> ${lines}: $sourceline"
······echo ""
······totalerrors="$(($totalerrors + 1))"
····fi
··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.
Читать дальше