#·· (предыдущая проверка в ветке —?)
if [$# −eq 0]; then
··echo "Usage: $0 [-s signal] [-u user|-t tty] [-n] pattern" >&2
··exit 1
fi
# Теперь нужно создать список числовых идентификаторов процессов,
#·· соответствующих заданному устройству TTY, пользователю или текущему
#·· пользователю.
if [! -z "$tty"]; then
··pids=$(ps cu −t $tty | awk "/ $1$/ { print \$2 }")
elif [! -z "$user"]; then
··pids=$(ps cu −U $user | awk "/ $1$/ { print \$2 }")
else
··pids=$(ps cu −U ${USER:-LOGNAME} | awk "/ $1$/ { print \$2 }")
fi
# Нет совпадений? Тогда все просто!
if [-z "$pids"]; then
··echo "$0: no processes match pattern $1" >&2
··exit 1
fi
for pid in $pids
do
··# Послать сигнал $signal процессу с идентификатором $pid: kill при этом
··#·· может вывести сообщение, если процесс уже завершился, если пользователь
··#·· не имеет прав завершить процесс и так далее, но это нормально. Свою
··#·· работу мы сделали.
··if [$donothing −eq 1]; then
····echo "kill $signal $pid" # Флаг −n: "показать и ничего больше не делать"
··else
····kill $signal $pid
··fi
done
exit 0
Так как этот сценарий выполняет агрессивную операцию и потенциально опасен, мы постарались минимизировать ложные совпадения с шаблоном, чтобы шаблон, например sh, не совпадал с такими строками в выводе ps, как bash или vi crashtest.c. Это достигается включением в шаблон префикса в команде awk (
,
,
).
Добавление ведущего пробела перед шаблоном $1 и завершающего якорного метасимвола $ заставляет сценарий выполнять поиск в выводе команды ps не по шаблону 'sh', а по шаблону ' sh$'.
Этот сценарий имеет несколько начальных флагов, позволяющих управлять его поведением. Флаг −s SIGNAL позволяет указать сигнал, который должен посылаться найденному процессу или процессам вместо сигнала по умолчанию SIGINT. Флаги −u USER и −t TTY удобны в первую очередь для пользователя root, поскольку дают ему возможность послать сигнал всем процессам, связанным с указанным пользователем или устройством TTY соответственно. А флаг −n позволяет заставить сценарий вывести список найденных процессов без отправки любых сигналов. Наконец, должен быть указан шаблон для поиска процессов.
Теперь завершить все процессы csmount в OS X можно с помощью сценария killall, как показано в листинге 6.7.
Листинг 6.7.Завершение всех процессов csmount с помощью сценария killall
$./killall −n csmount
kill −INT 1292
kill −INT 1296
kill −INT 1306
kill −INT 1310
kill −INT 1318
Усовершенствование сценария
Иногда при работе сценария возникает маловероятная, но возможная ошибка. Чтобы обеспечить более полное совпадение с заданным шаблоном, команда awk выводит идентификаторы только для процессов, имена которых содержат шаблон в конце, плюс ведущий пробел. Но теоретически возможна ситуация, когда в системе имеется два процесса: один с именем bash и другой с именем emulate bash. Если вызвать сценарий killall с шаблоном bash, оба процесса совпадут с ним, хотя только первое совпадение будет истинным. Решить эту проблему и обеспечить непротиворечивые результаты во всех системах очень непросто.
Если вы заинтересованы в этом, напишите на основе killall свой сценарий, который позволял бы изменять приоритет процессов с помощью команды renice по их именам, а не по числовым идентификаторам. В этом случае потребуется только вызвать renice вместо kill. Команда renice изменяет относительные приоритеты выполняющихся программ, позволяя, к примеру, уменьшать приоритет процесса, занимающегося передачей большого файла, и увеличивать приоритет видеоредактора, которым в данный момент пользуется начальник.
№ 48. Проверка записей в пользовательских файлах crontab
Одним из самых удобных механизмов во вселенной Linux является планировщик cron, позволяющий планировать выполнение заданий в произвольные моменты времени в будущем или автоматически запускать их каждую минуту, каждые несколько часов, раз в месяц или даже раз в год. Каждый хороший системный администратор имеет свой комплект сценариев, запускаемых из файла crontab.
Читать дальше