Дейв Тейлор - Сценарии командной оболочки. Linux, OS X и Unix. 2-е издание
- Название:Сценарии командной оболочки. Linux, OS X и Unix. 2-е издание
- Автор:
- Жанр:
- Издательство:Питер
- Год:2017
- Город:СПб.
- ISBN:978-5-496-03029-8
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Дейв Тейлор - Сценарии командной оболочки. Linux, OS X и Unix. 2-е издание краткое содержание
Цель этой книги — продемонстрировать практические приемы программирования сценариев на bash и познакомить с самыми распространенными утилитами на коротких и компактных примерах, не вдаваясь в излишние подробности. Экспериментируйте с этими сценариями — ломайте, исправляйте и приспосабливайте их под свои нужды, чтобы понять, как они работают. Только так вы сможете решать самые сложные задачи.
Сценарии командной оболочки. Linux, OS X и Unix. 2-е издание - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
····#·· то есть любое число в форме "X" по умолчанию считается допустимым.
····if ["$num" = "X"]; then
······return 0
····elif [! -z $(echo $num | sed 's/[[: digit: ]]//g')]; then
······# Отбросить все цифры и проверить остаток. Не пустой? Плохо.
······return 1
····elif [$num −gt $max]; then
······# Числа больше максимального значения недопустимы.
······return 1
····else
······return 0
····fi
··}
··validDay()
··{
····# Возвращает 0, если аргумент содержит допустимое название дня недели;
····#·· 1 — если нет.
····case $(echo $1 | tr '[: upper: ]' '[: lower: ]') in
······sun*|mon*|tue*|wed*|thu*|fri*|sat*) return 0;;
······X) return 0;;··# Особый случай, это замена "*"
······*) return 1
····esac
··}
··validMon()
··{
····# Возвращает 0, если аргумент содержит допустимое название месяца;
····#·· 1 — если нет.
····case $(echo $1 | tr '[: upper: ]' '[: lower: ]') in
······jan*|feb*|mar*|apr*|may|jun*|jul*|aug*) return 0;;
······sep*|oct*|nov*|dec*)····················return 0;;
······X) return 0;; # Особый случай, это замена "*"
······*) return 1········;;
····esac
··}
··fixvars()
··{
····# Преобразует все '*' в 'X', чтобы обойти конфликт с механизмом
····#·· подстановки в командной оболочке. Оригинал сохраняется
····#·· в "sourceline" для включения в сообщение об ошибке.
····sourceline="$min $hour $dom $mon $dow $command"
····min=$(echo "$min" | tr '*' 'X')····# Минуты
····hour=$(echo "$hour" | tr '*' 'X')··# Часы
····dom=$(echo "$dom" | tr '*' 'X')····# День месяца
····mon=$(echo "$mon" | tr '*' 'X')····# Месяц
····dow=$(echo "$dow" | tr '*' 'X')····# День недели
··}
··if [$# −ne 1] || [! -r $1]; then
····# Если имя файла crontab не задано или если он недоступен сценарию
····#·· для чтения, завершить работу с выводом сообщения.
····echo "Usage: $0 usercrontabfile" >&2
····exit 1
··fi
··lines=0·· entries=0·· totalerrors=0
··# Выполнить обход строк в файле 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.
Запуск сценария
Этот сценарий легко запускается: просто передайте ему единственный аргумент с именем файла crontab. В листинге 6.9 приводится пример проверки существующего файла crontab.
Читать дальшеИнтервал:
Закладка: