- IgorKa — Информационный ресурс
- Лекция №13 Сигналы в Linux
- Использование команд ps, kill и nice для управления процессами в Linux
- Вступление
- Как просматривать запущенные процессы в Linux
- Как использовать ps для получения списка процессов
- Примечание об идентификаторах процессов (PID)
- Как отправлять сигналы процессам в Linux
- Как отправлять процессам сигналы при помощи PID
- Как использовать сигналы для других целей
- Как отправлять сигналы процессам по имени
- Как установить приоритеты процессов
- Итоги
IgorKa — Информационный ресурс
Немного обо всем и все о немногом, или практический опыт системного администратора.
Пн | Вт | Ср | Чт | Пт | Сб | Вс |
---|---|---|---|---|---|---|
« Окт | Дек » | |||||
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 |
Лекция №13 Сигналы в Linux
Прошлая лекция была посвящена процессам в Linux. Сегодня мы поговорим о взаимодействии процессом между собой, а также о том как мы можем воздействовать на процессы. Сначала посмотрим как процессы могу взаимодействовать между собой. Мы уже писали в командной строке конструкции подобные этой: less /etc/group | grep user . В этом примере процесс less взаимодействует с процессом grep посредством механизма, который называется неименований канал или пайп (pipe — канал). Мы не будем вдаваться в подробности, просто запомните, что посредством символа |, который можно в данном случае называть “пайпом” информация (результат выполнения) процесса less идет на вход другого процесса — grep. Таким образом один процесс передал информацию другому процессу.
Еще один способ общения процессов — это именованные каналы. Изучение именованный каналов не входит в этот курс, но на практическом примере расскажу, что это. Именованный канал можно создать командой mkfifo:
igor@adm-ubuntu:
/linux$ mkfifo my_pipe
igor@adm-ubuntu:
/linux$ ls -l | grep my_pipe
prw-r–r– 1 igor igor 0 2009-11-09 17:59 my_pipe
Теперь в одной консоли выполните команду:
/linux$ echo Hello > my_pipe
Как видите команда не завершает свою работу, а ждет. Зарегистрируйтесь еще в одной консоли и выполните команду:
/linux$ cat my_pipe
Hello
Если вернуться на первую консоль, то вы увидите, что команда echo завершила свою работу. Таким образом через именованный канал my_pipe команда (процесс) echo передала информацию (слово Hello) процессу cat, который ее принял и вывел на экран.
Давайте теперь рассмотрим основной способ “общения” процессов — сигналы. Один процесс при помощи ядра может передать другому процессу специальное числовое значение сигнала. Процесс вызывает функцию передачи сигнала и передает необходимую информацию (код сигнала, PID процесса) ядру. Ядро передает сигнал процессу получателю и отслеживает как этот сигнал обрабатывается. Сигналы обозначаются цифрами или мнемоническими обозначениями. Перечень сигналов можно вывести командой kill -l.
Мнемонические имена которые вы видите (SIGTERM, SIGINT, SIGKILL) начинаются с приставки SIG. Имена в этом виде используются в языках программирования таких как С. В интерпретаторе bash используются или числа или мнемонические имена, но без приставки SIG — TERM, INT, KILL.
Часть сигналов (INT, TERM) являются перехватываемыми. Это означает, что процесс при получении такого сигнала должен перейти на специальную подпрограмму, которая занимается обработкой сигнала. Если подпрограммы обработки нет (а ее написанием занимаются разработчики программы, которая выполняется в контексте процесса), то управление передается ядру, которое выполняет действия по умолчанию, описанные для каждого сигнала.
Часть сигналов являются такими которые можно заблокировать. Например, один процесс посылает сигнал TERM другому процессу, а он в свою очередь не закончил операции ввода/вывода. В таком случае второй процесс может заблокировать полученный сигнал (опять таки в обработчике сигнала) до момента выполнения необходимой операции ввода/вывода. Сигнал TERM — это сигнал корректного завершения работы процесса. Обработчик этого сигнала, должен выполнить все необходимые действия для правильного завершения работы.
И есть третья группа сигналов, которые не блокируются и для которых не нужны обработчики. Примером такого сигнала является сигнал KILL. Этот сигнал уничтожает процесс, так как для него нет обработчиков в процессах, то он будет обрабатываться ядром по умолчанию и так как он не блокируемый, то действия будут выполнятся немедленно.
Пока мы говорили о том как процессы “общаются” между собой с помощью сигналов. Но мы (пользователи) также можем посылать сигналы процессам. Например, комбинация клавиш Ctrl+C посылает процессу сигнал INT, который прерывает выполнение процесса. Если вы наберете в терминале команду sleep 100, то команда не вернет управление терминалу пока не завершится. Прервать выполнение этой команды можно нажав комбинацию клавиш Ctrl+C.
В чем же отличия между похожими сигналами INT, TERM, KILL (а также QUIT и HUP)? Несмотря на похожесть отличия есть:
Сигнал KILL не блокируется и не перехватывается и ведет к немедленному завершению процесса.
Сигнал INT в отличии от KILL является блокируемым сигналом и перехватываемым.
Сигнал TERM также является перехватываемым и блокируемым и предназначен для корректного (предпочтительного) завершения работы процесса.
Сигнал QUIT — похож на TERM, но позволяет сохранить дамп памяти.
Сигнал HUP — сейчас этот сигнал чаще всего интерпретируется процессами как “прочесть конфигурационные файлы”.
Рассмотрим два сигнала: STOP и CONT. Сигнал STOP останавливает процесс, то есть процесс переходит в состояние “остановленный“. В таком состоянии процесс будет до тех пор пока снова не получит сигнал. Если будет получен сигнал CONT, то процесс возобновит свою работу с того момента как он был остановлен. Практический пример:
Наберите в терминале команду sleep 1000 &.
Затем проверьте, что процесс находится в состоянии ожидания, о чем нам говорит буква S в столбце STAT:
$ ps x | grep [s]leep
PID TTY STAT TIME COMMAND
6301 pts/1 S 0:00 sleep 1000
Теперь пошлем процессу сигнал STOP. Для этого используем команду kill (kill -название процесса PID процесса):
$ kill -STOP 6301
[1]+ Stopped sleep 1000
Проверяем статус процесса:
igor@ubuntu:
$ ps x | grep [s]leep
PID TTY STAT TIME COMMAND
6301 pts/1 T 0:00 sleep 1000
Видим, что процесс действительно находится в состоянии “остановленный” (символ T в столбце STAT).
Теперь отправим процессу сигнал продолжения работы (CONT) и проверим состояние:
igor@ubuntu:
$ kill -CONT 6301
igor@ubuntu:
$ ps x | grep [s]leep
PID TTY STAT TIME COMMAND
6301 pts/1 S 0:00 sleep 1000
Если необходимо корректно завершить процесс, то необходимо послать ему сигнал TERM:
igor@ubuntu:
$ kill -TERM 6301
igor@ubuntu:
$ ps x | grep [s]leep
[1]+ Terminated sleep 1000
igor@ubuntu:
$ ps x | grep [s]leep
Если сразу же после посылки сигнала TERM выполнить команду ps x | grep [s]leep, то можно успеть увидеть сообщение о том, что процесс завершает работу, в при следующей попытке вывести информацию о нашем процессе sleep мы уже ничего не увидим — процесс прекратил существование. Команда kill без указания сигнала, по умолчанию передает процессу именно сигнал TERM. Поэтому можно было написать просто kill 6301.
Если необходимо срочно завершить процесс, или процесс не завершается по сигналу TERM, то тогда необходимо послать процессу сигнал KILL:
igor@ubuntu:
$ sleep 1000 &
[1] 6348
igor@ubuntu:
$ kill -KILL 6348
igor@ubuntu:
$ ps x | grep [s]leep
[1]+ Killed sleep 1000
Если необходимо послать один и тот же сигнал нескольким процессам, то можно перечислить их через пробел: kill -TERM 2345 3456 4567.
Команда kill довольно ограничена в возможностях и не позволяет выполнять более сложные действия. Поэтому рассмотрим еще одну команду — killall. Основное преимущество этой команды, то что она умеет посылать сигналы всем процессам с одинаковым именем или всем процессам одного пользователя. Запустите несколько раз подряд команду sleep 1000 &:
$ ps x | grep [s]leep
6460 pts/1 S 0:00 sleep 1000
6461 pts/1 S 0:00 sleep 1000
6462 pts/1 S 0:00 sleep 1000
6463 pts/1 S 0:00 sleep 1000
6464 pts/1 S 0:00 sleep 1000
6465 pts/1 S 0:00 sleep 1000
6466 pts/1 S 0:00 sleep 1000
Теперь, чтобы завершить все процессы с именем sleep, достаточно набрать команду killall sleep:
igor@ubuntu:
$ killall sleep
[1] Terminated sleep 1000
[2] Terminated sleep 1000
[3] Terminated sleep 1000
[4] Terminated sleep 1000
[6]- Terminated sleep 1000
[7]+ Terminated sleep 1000
[5]+ Terminated sleep 1000
Выполните команду sleep 1000 & еще несколько раз, а затем зарегистрируйтесь в другой консоли от имени другого пользователя (например, test) и также от его имени выполните команду sleep 1000 &. Теперь вернитесь в свою консоль и просмотрите процессы sleep всех пользователей:
$ ps aux | grep [s]leep
igor 6540 0.0 0.0 2952 628 pts/1 S 22:30 0:00 sleep 1000
igor 6541 0.0 0.0 2952 632 pts/1 S 22:30 0:00 sleep 1000
igor 6542 0.0 0.0 2952 628 pts/1 S 22:30 0:00 sleep 1000
test 6543 0.0 0.0 2952 632 pts/3 S 22:30 0:00 sleep 1000
test 6544 0.0 0.0 2952 628 pts/3 S 22:30 0:00 sleep 1000
test 6545 0.0 0.0 2952 628 pts/3 S 22:30 0:00 sleep 1000
test 6546 0.0 0.0 2952 632 pts/3 S 22:30 0:00 sleep 1000
Теперь для того, чтобы удалить процессы только пользователя test необходимо выполнить (от имени пользователя root) команду killall -u test:
igor@ubuntu:
$ sudo killall -u test
igor@ubuntu:
$ ps aux | grep [s]leep
igor 6540 0.0 0.0 2952 628 pts/1 S 22:30 0:00 sleep 1000
igor 6541 0.0 0.0 2952 632 pts/1 S 22:30 0:00 sleep 1000
igor 6542 0.0 0.0 2952 628 pts/1 S 22:30 0:00 sleep 1000
Команда выше удалит не только процессы sleep, но вообще все процессы пользователя test. Если необходимо удалить конкретно процессы sleep, то тогда команду нужно было записать так: killall -u test sleep.
Если запустить команду killall c ключом -i, то перед посылкой сигнала будет запрашиваться подтверждение:
$ killall -i sleep
Прибить sleep(6540) ? (y/N) n
Прибить sleep(6541) ? (y/N) n
Прибить sleep(6542) ? (y/N) n
Следующая лекция будет завершающей по теме процессов и сигналов Linux. Мы поговорим о заданиях (jobs), командах jobs, fg, bg, strong>nohup, и top.
Источник
Использование команд ps, kill и nice для управления процессами в Linux
Вступление
На сервере Linux, как и на любой другой машине, можно запускать приложения. Компьютер рассматривает их как так называемые «процессы».
В то время как Linux обрабатывает низкоуровневое закадровое управление жизненным циклом процесса, пользователю может понадобиться другой способ взаимодействия с операционной системой для управления процессом на более высоком уровне.
Данное руководство затрагивает некоторые простейшие аспекты управления процессами. Для этого Linux предоставляет широчайший набор инструментов.
Данные понятия будут рассмотрены на примере сервера Ubuntu 12.04, но любой современный дистрибутив Linux будет работать таким же образом.
Как просматривать запущенные процессы в Linux
Самый простой способ узнать, какие процессы запущены на сервере в данный момент, – использовать команду top:
top
top — 15:14:40 up 46 min, 1 user, load average: 0.00, 0.01, 0.05
Tasks: 56 total, 1 running, 55 sleeping, 0 stopped, 0 zombie
Cpu(s): 0.0%us, 0.0%sy, 0.0%ni,100.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 1019600k total, 316576k used, 703024k free, 7652k buffers
Swap: 0k total, 0k used, 0k free, 258976k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1 root 20 0 24188 2120 1300 S 0.0 0.2 0:00.56 init
2 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kthreadd
3 root 20 0 0 0 0 S 0.0 0.0 0:00.07 ksoftirqd/0
6 root RT 0 0 0 0 S 0.0 0.0 0:00.00 migration/0
7 root RT 0 0 0 0 S 0.0 0.0 0:00.03 watchdog/0
8 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 cpuset
9 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 khelper
10 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kdevtmpfs
Верхняя часть выведенной информации предоставляет статистические данные системы, а именно нагрузку на систему и общее количество задач.
Можно увидеть, что 1 процесс запущен, а 55 процессов находятся в режиме ожидания (иначе говоря, простаивают, не используя ресурсы процессора).
Нижняя часть полученной информации отображает запущенные процессы и статистику по их использованию.
Усовершенствованная версия команды top под названием htop доступна в хранилищах. Чтобы установить ее, используйте данную команду:
sudo apt-get install htop
Запустив команду htop, можно увидеть более удобное для пользователя отображение информации:
htop
Mem[||||||||||| 49/995MB] Load average: 0.00 0.03 0.05
CPU[ 0.0%] Tasks: 21, 3 thr; 1 running
Swp[ 0/0MB] Uptime: 00:58:11
PID USER PRI NI VIRT RES SHR S CPU% MEM% TIME+ Command
1259 root 20 0 25660 1880 1368 R 0.0 0.2 0:00.06 htop
1 root 20 0 24188 2120 1300 S 0.0 0.2 0:00.56 /sbin/init
311 root 20 0 17224 636 440 S 0.0 0.1 0:00.07 upstart-udev-brid
314 root 20 0 21592 1280 760 S 0.0 0.1 0:00.06 /sbin/udevd —dae
389 messagebu 20 0 23808 688 444 S 0.0 0.1 0:00.01 dbus-daemon —sys
407 syslog 20 0 243M 1404 1080 S 0.0 0.1 0:00.02 rsyslogd -c5
408 syslog 20 0 243M 1404 1080 S 0.0 0.1 0:00.00 rsyslogd -c5
409 syslog 20 0 243M 1404 1080 S 0.0 0.1 0:00.00 rsyslogd -c5
406 syslog 20 0 243M 1404 1080 S 0.0 0.1 0:00.04 rsyslogd -c5
553 root 20 0 15180 400 204 S 0.0 0.0 0:00.01 upstart-socket-br
Как использовать ps для получения списка процессов
Команды top и htop предоставляют удобный интерфейс для просмотра запущенных процессов, аналогичный графическому диспетчеру задач.
Тем не менее, данные инструменты не всегда достаточно гибки, чтобы адекватно охватить все сценарии.
При вызове без аргументов результаты могут быть немного неполными:
ps
PID TTY TIME CMD
1017 pts/0 00:00:00 bash
1262 pts/0 00:00:00 ps
Эти данные отображают все процессы, связанные с текущим пользователем и терминальной сессией. Это имеет смысл, так как в данный момент с терминала запущены только команды bash and ps.
Чтобы получить более полную картину процессов данной системы, можно запустить следующее:
ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.2 24188 2120 ? Ss 14:28 0:00 /sbin/init
root 2 0.0 0.0 0 0 ? S 14:28 0:00 [kthreadd] root 3 0.0 0.0 0 0 ? S 14:28 0:00 [ksoftirqd/0] root 6 0.0 0.0 0 0 ? S 14:28 0:00 [migration/0] root 7 0.0 0.0 0 0 ? S 14:28 0:00 [watchdog/0] root 8 0.0 0.0 0 0 ? S
Эти параметры приказывают ps показать процессы, принадлежащие всем пользователям (вне зависимости от их терминала) в удобном формате.
Чтобы увидеть дерево, отображающее иерархические отношения, можно запустить команду с данными параметрами:
ps axjf
PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
0 2 0 0 ? -1 S 0 0:00 [kthreadd] 2 3 0 0 ? -1 S 0 0:00 \_ [ksoftirqd/0] 2 6 0 0 ? -1 S 0 0:00 \_ [migration/0] 2 7 0 0 ? -1 S 0 0:00 \_ [watchdog/0] 2 8 0 0 ? -1 S
Как можно видеть, процесс kthreadd отображен как порождающий относительно процесса ksoftirqd/0 и других.
Примечание об идентификаторах процессов (PID)
В Linux и Unix-подобных системах каждому процессу присвоен идентификатор (PID). Таким образом операционная система идентифицирует и отслеживает процессы.
Быстрый способ узнать PID процесса – использовать команду pgrep:
pgrep bash
1017
Это запросит идентификатор процесса и вернет его.
Первый порожденный при запуске процесс под названием init получает PID «1».
Данный процесс отвечает за порождение всех остальных процессов системы. Чем позже порожден процесс, тем больше будет присвоенный ему PID.
Родительский процесс – это процесс, ответственный за порождение другого процесса. Если порождающий процесс был прекращен, то дочерние процессы также прервутся. PID родительского процесса называется PPID.
PID и PPID можно увидеть в заголовках столбцов во многих приложениях управления процессами, включая top, htop и ps.
Любое общение между пользователем и операционной системой, связанное с процессами, предполагает перевод имен процессов в их идентификаторы и наоборот. Вот зачем утилиты сообщают PID.
Как отправлять сигналы процессам в Linux
Все процессы в Linux отвечают на сигналы.
Сигналы – способ завершить или изменить поведение программ на уровне ОС.
Как отправлять процессам сигналы при помощи PID
Наиболее распространенным способом передачи сигналов программам является команда kill.
Как и следовало ожидать, функциональность данной утилиты по умолчанию заключается в попытке завершить процесс:
Это отправит всем процессам сигнал TERM. Данный сигнал приказывает процессу завершиться. Это позволяет программе выполнять операции по очистке и завершить работу без помех.
Если программа неисправна и не завершает работу при отправке сигнала TERM, можно усилить сигнал, передав сигнал KILL:
kill -KILL PID_of_target_process
Данный специальный сигнал отправляется не программе.
Вместо этого он передается ядру операционной системы, которое прерывает процесс. Это используется для блокировки программ, которые игнорируют сигналы, посылаемые им.
Каждый сигнал имеет ассоциированный номер, который можно передать вместо имени. К примеру, можно отправить «-15» вместо «-TERM» и «-9» вместо «-KILL».
Как использовать сигналы для других целей
Сигналы используются не только для завершения работы программ. Они также полезны для совершения других действий.
К примеру, многие демоны можно перезапустить при помощи сигнала отбоя HUP. Apache является одной из работающих по такому принципу программ.
sudo kill -HUP pid_of_apache
Вышеприведенная команда заставит Apache перезагрузить конфигурационный файл и возобновить обслуживание контента.
Чтобы просмотреть список всех сигналов, которые можно отправить с kill, наберите:
kill -l
1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP
6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1
11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM
. . .
Как отправлять сигналы процессам по имени
Хотя отправлять сигналы процессам гораздо удобнее при помощи PID, существуют также методы отправки сигнала с помощью имен процессов.
Команда pkill работает почти также, как kill, но она действует от имени процесса:
Команда, приведенная выше, является эквивалентом:
kill -9 `pgrep ping`
Чтобы послать сигнал каждому экземпляру определенного процесса, используйте команду killall:
Вышеуказанная команда отправит сигнал TERM каждому экземпляру firefox, запущенному на данном компьютере.
Как установить приоритеты процессов
Часто возникает необходимость установить, какие процессы имеют приоритет в серверной среде.
Некоторые процессы могут рассматриваться как критически важные, в то время как другие могут быть выполнены за счет остатка ресурсов.
Linux контролирует приоритеты с помощью значения под названием niceness.
Задачи с высоким приоритетом имеют низшее значение nice, так как они поглощают ресурсы. С другой стороны, задачи с низким приоритетом имеют высокое значение nice, так как они используют минимальное количество ресурсов.
При запуске команды top в начале статьи был выведен столбец, отмеченный как «NI». В нем указывается значение nice процесса:
top
Tasks: 56 total, 1 running, 55 sleeping, 0 stopped, 0 zombie
Cpu(s): 0.0%us, 0.3%sy, 0.0%ni, 99.7%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 1019600k total, 324496k used, 695104k free, 8512k buffers
Swap: 0k total, 0k used, 0k free, 264812k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1635 root 20 0 17300 1200 920 R 0.3 0.1 0:00.01 top
1 root 20 0 24188 2120 1300 S 0.0 0.2 0:00.56 init
2 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kthreadd
3 root 20 0 0 0 0 S 0.0 0.0 0:00.11 ksoftirqd/0
В зависимости от системы, значение nice может варьироваться от «-19/-20» (наивысший приоритет) до «19/20» (самый низкий приоритет).
Чтобы запустить программу с определенным значением nice, можно использовать команду nice:
nice -n 15 command_to_execute
Это работает только при запуске новой программы.
Чтобы изменить значение nice программы, которая уже выполняется, нужно использовать инструмент renice:
renice 0 PID_to_prioritize
Примечание: в то время как nice работает с именем команды, renice вызывает PID процесса.
Итоги
Управление процессами – иногда достаточно сложная для новичков тема, так как используемые инструменты отличаются от их графических эквивалентов.
Однако концепции знакомы и интуитивно понятны, и, немного попрактиковавшись, их можно легко освоить. Поскольку процессы участвуют во всем, что касается компьютерной системы, очень важно научиться управлять ими.
Источник