Главная » Программирование для UNIX » Команда zap: уничтожение процесса по имени

0

Команда kill уничтожает только процессы, для которых указан иден тификатор. Поэтому  когда  требуется уничтожить конкретный фоновый  процесс, обычно  приходится сначала запустить ps, чтобы  опреде лить  идентификатор процесса, а потом ввести его без ошибок как аргумент для kill. Но глупо  иметь одну программу, выводящую число, которое  сразу  же  приходится  вручную вводить в  другую  программу. Почему бы не написать программу, скажем, zap, чтобы  автоматизировать эту работу?

Одна из причин заключается в том,  что уничтожающий процесс опасен,  и необходимо соблюдать осторожность, чтобы  не уничтожить не тот процесс. В качестве защитной меры  будем выполнять zap интерактивно  и выбирать жертвы при помощи команды pick.

Краткое напоминание о pick: она выводит все свои аргументы по очере ди  и ждет ответа  пользователя; если  ответ  y,  то аргумент  выводится (подробнее об этой  команде будет  рассказано в следующем разделе). Команда zap использует pick для того, чтобы  проверить, являются ли процессы, выбранные по  имени,  теми, которые пользователь хочет уничтожить:

$ cat  zap

# zap  pattern: уничтожить  процессы, соответствующие  шаблону

#  В  этой  версии  ОШИБКА PATH=/bin:/usr/bin

case  $# in

0)    echo ‘Usage:  zap pattern’  1>&2;  exit 1 esac

kill  `pick \`ps –ag | grep  "$*"\`  | awk  ‘{print $1}’`

$

Обратите внимание на вложенные кавычки, защищенные символами обратной косой черты. Программа awk выбирает указанный pick идентификатор процесса из выходных данных команды ps:

$ sleep 1000 &

22126

$ ps  -ag

PID TTY  TIME  CMD

22126 0     0:00  sleep 1000

$ zap  sleep

22126?

0? q                                     Что происходит?

$

Проблема заключается в том,  что вывод  ps разбит на слова, и команда pick воспринимает их как отдельные аргументы вместо  того, чтобы обрабатывать всю  строку целиком. Оболочка  обычно  разделяет строку на аргументы, ориентируясь на пробелы, как в

for  i in  1 2 3 4 5

В этой  программе необходимо так отрегулировать разбиение строк на аргументы (осуществляемое оболочкой), чтобы  соседние «слова» разделяли только символы новой строки.

Переменная оболочки IFS (internal field separator – внутренний разделитель  полей) –  это  строка  символов, которые разделяют  слова  на списки аргументов, такие как обратный апостроф или  операторы for. Обычно IFS содержит пробел, знак табуляции и символ новой  строки, но  его  можно и  изменить,  например,  оставив только символ новой строки:

$ echo ‘echo  $#’  >nargs

$ cx  nargs

$ who

you           tty0

Oct

1 05:59

pjw           tty2

Oct

1 11:26

$ nargs  `who`

10

Десять полей, разделенных пробелами и

разделителями строк

$ IFS=’

Только разделитель строк

$ nargs  `who`

2

Две строки, два поля

$

Если  IFS включает в себя только разделитель строк, то команда zap работает правильно:

$ cat  zap

# zap  pat: уничтожить  все  процессы, соответствующие  pat

# окончательная версия

PATH=/bin:/usr/bin IFS=’

‘       # только разделитель  строк

case  $1 in

"")   echo ‘Usage: zap [–2]  pattern’ 1>&2; exit  1 ;;

–*)  SIG=$1;  shift esac

echo ‘  PID  TTY      TIME  CMD’

kill $SIG `pick \`ps  –ag | egrep  "$*"\`  | awk  ‘{print  $1}’`

$ ps  -ag

PID TTY  TIME  CMD

22126 0     0:00  sleep 1000

$ zap  sleep

PID TTY  TIME  CMD

22126  0      0:00  sleep  1000?  y 23104  0      0:02  egrep  sleep?  n

$

В эту версию внесено  еще два полезных изменения: добавлен необязательный аргумент для указания сигнала (обратите внимание на то, что если аргумент отсутствует, то SIG не будет определен и, следовательно, будет  считаться  пустой строкой), а вместо  grep  использована  egrep  – для  того, чтобы  можно было  задавать  более  сложные шаблоны, как, например, ‘sleep|date’. Команда echo печатает заголовки колонок для  вывода ps.

Может показаться странным, что команда получила имя  zap вместо того, чтобы  называться просто  kill. Основная причина  заключается в том,  что (в отличие от примера с командой cal)  это не новая версия команды kill, ведь zap обязана быть интерактивной. К тому же нам хотелось сохранить название kill для настоящей команды. Еще одно заме чание:  zap чрезвычайно медленная команда  –  сказывается наличие всех дополнительных программ, при  этом больше всего затрат приходится на команду ps (которая, так  или  иначе, но должна выполняться).  В следующей главе будет предложена более производительная реализация.

Упражнение 5.23.  Измените zap таким образом, чтобы  выводить заголовок ps из конвейера так, чтобы  он был не чувствителен к изменениям формата вывода ps. Насколько это усложнит программу?

Источник: Керниган Б., Пайк Р., UNIX. Программное окружение. – Пер. с англ. – СПб: Символ-Плюс, 2003. – 416 с., ил.

По теме:

  • Комментарии