Библиотека сайта rus-linux.net
Kill: Завершение неконтролируемых процессов
Оригинал: Killing With Linux: A PrimerАвтор: Carla Schroder
Дата: 3 августа 2008
Свободный перевод: Алексей Дмитриев
Дата перевода: 8 сентября 2008
Вы усердно боретесь с особо заковыристым приложением Линукс. Продираясь через дебри документации, запускаете команды и правите конфигурационные файлы. Все работает, и жизнь прекрасна... Как вдруг вас ошарашивает сообщение "send the process a SIGHUP" (пошлите процессу SIGHUP).
По инерции вы движетесь дальше. Что это за SIGHUP такой, и как его посылают? Вы почти уверены, что это не команда, но, на всякий случай, пробуете. Нет, не то. Перечитываем ман к приложению:
Когда получен сигнал о том, что программа зависла - SIGHUP, sshd перечитывает
свой конфигурационный файл путем запуска самой себя с теми же именем и опциями,
с которыми была первоначально запущена, например, /usr/sbin/sshd.
Г-м-м. Хорошо.
Программисты против пользователей
Авторы страниц руководств (манов) делятся на две категории. Одни адресуются конечным пользователям, а другие - "крутым" программистам. Вот почему встречаются заявления типа:"список do будет в работе до тех пор, пока последняя команда в этом списке не выдаст ненулевой выходной статус"
. Прочитать такое также приятно и полезно, как и "пошлите процессу SIGHUP". Не переживайте, сегодня мы прольем свет на эти тайны, покрытые мраком.
Сигналы и контроль над процессами
Одной из задач опытных администраторов и пользователей является запуск, остановка и перезапуск сервисов, а также остановка сбойных и зависших процессов, причем с минимальным уроном. В различных операционных системах, а также в различных командных оболочках (шеллах) способы управления сигналами сильно рознятся. Поэтому в этой статье мы остановимся на ОС Linux и bash shell.Сигналы нужны для того, чтобы взаимодействовать с процессами и демонами. Процессом называется любое активное действие. Демоны являются фоновыми (background) процессами, и до поры скрыты. Они ждут либо события, на которое они отреагируют, либо наступления времени, назначенного для выполнения некоего задания по расписанию. О наступлении этого события они узнают, получая сигнал от какого-то другого процесса. Каждая программа должна иметь в своем коде обработчик сигналов, чтобы отслеживать (перехватывать) сигналы и правильно реагировать на них. Страница руководства man signal описывает всевозможные сигналы и их действия. Сигналы посылают при помощи команды kill ("убить"). Команда kill -l выводит список сигналов и их номеров.
Все демоны и процессы имеют Идентификатор Процесса (PID). PID процесса можно узнать при помощи команды ps:
$ ps aux USER PID %CPU %MEM TTY STAT COMMAND root 1 0.0 0.1 ? S init '2' 105 7783 0.0 0.2 ? Ss /usr/bin/dbus-daemon --system hal 7796 0.0 0.7 ? Ss /usr/sbin/hald postfix 7957 0.0 0.2 ? S qmgr -l -t fifo -u -c nagios 8371 0.0 0.2 ? SNs /usr/sbin/nagios /etc/nagios/nagios.cfg
В приведенном выше примере, вывод команды сильно сокращен - в вашей системе вы увидите куда больше строк и столбцов. Если какой-нибудь процесс "ворует" мощность вашего процессора или вашу память, вы увидите это в столбцах %CPU и %MEM.
Еще быстрее "зарвавшийся" процесс можно обнаружить при помощи команды top. В ней, по умолчанию, процессы, потребляющие больше ресурсов процессора, расположены в верхних строках таблицы. Мы можем немного поиграть с программой top при помощи команды yes:
$ yes carla is teh awesum
Эта команда станет повторять "carla is teh awesum" с большой скоростью, пока вы ее не остановите. Она загонит процент использования процессора в красную зону:
$ top ... PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 12144 carla 25 0 31592 17m 13m R 93.4 3.5 0:50.26 konsole 22236 carla 15 0 2860 468 400 S 4.3 0.1 0:00.97 yes
Интересно, что ответственность за разбазаривание мощности CPU ложится на консоль, а не на программу yes, так как yes работает внутри консоли. Если вы перейдете на "истинную" консоль (Ctrl+Alt+F2), то там увидите программу yes с большими цифрами потребления мощности процессора и использования памяти.
Существует несколько способов остановить yes. Если вы перейдете обратно в шелл, где она работает, просто нажмите Ctrl+C. Вы можете также остановить ее при помощи команды kill в другом шелле, как по PID, так и по имени:
$ kill 22236
$ killall yes
Ctrl+C посылает с клавиатуры сигнал SIGINT (2), или завершающее прерывание (terminate interrupt). kill и killall, оба, шлют по умолчанию SIGTERM (15). SIGTERM (15) может быть перехвачен и, либо игнорирован, либо интерпретирован иначе. Так что, в случае непредсказуемой работы, вы можете не добиться завершения процесса.
Применяя команду kill к родительскому процессу, вы, как правило (но не всегда), завершаете дочерний вместе с ним. Как узнать, какой процесс является дочерним? Используйте команду ps с опцией -f :
$ ps axf 22371 ? R 2:35 _ konsole 'kdeinit' 22372 pts/3 Ss 0:00 | _ /bin/bash 24322 pts/3 S+ 0:00 | | _ yes carla is teh awesum 22381 pts/4 Rs 0:00 | _ /bin/bash 24323 pts/4 R+ 0:00 | | _ ps axf
Вернемся к нашим SIGHUP'ам
SIGHUP произносится как "сиг-ап" и означает "сигнал отбоя" (signal hangup). Как послать SIGHUP? Существует несколько способов:
- # kill -HUP 'pid'
- # killall -HUP 'process-name'
- # kill -1 'pid'
- # killall -1 'process-name'
Как видите, можно использовать PID или имя процесса, а также имя или номер сигнала.
Зачем применять все эти команды, когда можно перезапустить процессы при помощи команды /etc/init.d/foo restart? Ведь предпочтительней контролировать сервисы с помощью их файлов init, так как такой контроль обычно включает санацию, проверку ошибок и другие функции. Если говорить честно, то главная причина использовать команду kill и сигналы состоит в том, чтобы остановить зависший или сбойный процесс как можно аккуратнее, и не прибегать к перезагрузке или завершению сеанса.
Применение команды kill к процессам
Как можно видеть в man signal, существуют десятки способов контролировать процессы. Вот наиболее часто применяемые:
kill -STOP 'pid'
SIGSTOP (19) останавливает процесс, не "убивая" его.
kill -CONT 'pid'
SIGCONT (18) перезапускает остановленный процесс.
kill -KILL 'pid'
SIGKILL (9) форсирует немедленное завершение процесса, и не производит никакой чистки.
kill -9 -1
Завершает все ваши процессы (которыми вы владеете).
SIGKILL и SIGSTOP не могут быть перехвачены, блокированы или игнорированы; остальные могут. Это ваше "большое ружье", последнее средство обороны.
Команда kill, встроенная в Bash
Оболочка Bash имеет встроенную команду kill, как показано в следующем листинге:
$ type -all kill
kill is a shell built-in
kill is /bin/kill
Маловероятно, что у вас возникнут конфликты или странное поведение программ, но на всякий случай выбирайте /bin/kill.
Не поленитесь получше познакомиться с большим миром команды kill, изучив приведенные ниже ресурсы. Это предоставит вам возможность решать возникающие проблемы путем тонкого хирургического вмешательства, не прибегая к перезагрузке системы при каждом сбое программы.
Ресурсы
- Глава 7 "Starting and Stopping Linux", Поваренная книга Линукс (the Linux Cookbook)
- bash (1) - GNU Bourne-Again Shell
- yes (1) - повторно выводит строку, пока не будет остановлена
- signal (7) - список сигналов
- ps (1) - мгновенный снимок идущих процессов
- kill (1) - посылает сигнал процессу
- killall (1) - "убивает" процесс по имени
- pkill (1) - ищет или дает сигнал процессам на основе имени или других атрибутов
- skill (1) - посылвет сигнал, либо рапортует о статусе процесса
- xkill (1) - "убивает" клиента по его Х ресурсу