Обратите внимание, что сценарий использует команду sudo для вызова команды date с привилегиями root, что наглядно демонстрирует листинг 6.5. Вводя неправильный пароль в ответ на запросы sudo, вы можете экспериментировать со сценарием, не боясь получить неожиданные результаты.
Листинг 6.5.Тестирование интерактивного сценария setdate
$ setdate
year [2017]:
month [05]:
day [07]:
hour [16]: 14
minute [53]: 50
Setting date to 201705071450. You might need to enter your sudo password:
passwd:
$
№ 47. Завершение процессов по имени
В Linux и в отдельных версиях Unix имеется удобная команда killall, позволяющая завершать все работающие приложения, имена которых соответствуют заданному шаблону. Это может пригодиться, например, для завершения всех девяти демонов mingetty или даже просто для отправки сигнала SIGHUP демону xinetd, чтобы заставить его перечитать файл конфигурации. В системах, не имеющих команды killall, можно эмулировать ее с помощью сценария командной оболочки, использующего команду ps для идентификации процессов и их завершения отправкой заданного сигнала.
Самую большую сложность в этом сценарии представляют различия в выводе команды ps в разных операционных системах. Например, давайте посмотрим, насколько различаются выводы по умолчанию команды ps в FreeBSD, Red Hat Linux и OS X.
Сначала посмотрим, что выводится в FreeBSD:
BSD $ ps
PID TT··STAT····TIME COMMAND
792··0··Ss·· 0:00.02 −sh (sh)
4468··0··R+·· 0:00.01 ps
Сравните с выводом в Red Hat Linux:
RHL $ ps
··PID TTY········ TIME CMD
8065 pts/4·· 00:00:00 bash
12619 pts/4·· 00:00:00 ps
И, наконец, с выводом в OS X:
OSX $ ps
··PID TTY··········TIME CMD
37055 ttys000·· 0:00.01 −bash
26881 ttys001·· 0:00.08 −bash
Что еще хуже, вместо того чтобы смоделировать типичную Unix-команду ps, GNU-версия команды ps принимает флаги в стиле BSD, в стиле SYSV и в стиле GNU. Полная каша!
К счастью, некоторые из этих несоответствий в данном конкретном сценарии можно обойти, использовав флаг cu, что позволяет получить единообразный вывод, включающий в себя владельца процесса, полное имя команды и — что особенно важно — числовой идентификатор процесса.
Кроме того, данный сценарий — первый, в котором мы по-настоящему используем всю мощь команды getopts, позволяющей работать с самыми разными параметрами командной строки и даже подставлять значения по умолчанию. Сценарий в листинге 6.6 имеет четыре начальных флага, три из которых имеют обязательные аргументы: −s SIGNAL, −u USER, −t TTY и −n. Вы увидите их в первом блоке кода.
Листинг 6.6.Сценарий killall
#!/bin/bash
# killall — посылает указанный сигнал всем процессам, имена которых
#·· соответствуют заданному шаблону.
# По умолчанию завершает только процессы, принадлежащие текущему
#·· пользователю, только если не запущен с привилегиями root.
#·· Используйте −s SIGNAL, чтобы указать сигнал, посылаемый процессам;
#·· −u USER, чтобы указать пользователя; −t TTY, чтобы указать устройство
#·· tty; и −n, чтобы только получить список процессов, которые могли бы
#·· быть завершены, но без их завершения.
signal="-INT"······# Сигнал по умолчанию — прерывание.
user=""·· tty=""·· donothing=0
while getopts "s: u: t: n" opt; do
··case "$opt" in
····# Обратите внимание на хитрый трюк ниже: фактическая команда kill ожидает
····#·· получить имя сигнала в виде −SIGNAL, но сценарий требует
····#·· указать его без дефиса: SIGNAL, поэтому мы просто
····#·· добавляем "-" в начало полученного имени сигнала.
····s) signal="-$OPTARG";;;
····u) if [! -z "$tty"]; then
··········# Логическая ошибка: нельзя одновременно указать пользователя
··········#·· и устройство TTY
··········echo "$0: error: −u and −t are mutually exclusive." >&2
··········exit 1
········fi
········user=$OPTARG;;;
····t) if [! -z "$user"]; then
··········echo "$0: error: −u and −t are mutually exclusive." >&2
··········exit 1
········fi
········tty=$2;;;
····n) donothing=1;;;
····?) echo "Usage: $0 [-s signal] [-u user|-t tty] [-n] pattern" >&2
········exit 1
··esac
done
# Завершить обработку всех начальных флагов с помощью getopts…
shift $(($OPTIND — 1))
# Если пользователь не указал начальных аргументов
Читать дальше