Основы Linux от основателя Gentoo. Часть 2 (3/5): Управление процессами

http://www.funtoo.org/en/articles/linux/lpi/2/
  • Перевод
В этом отрывке рассмотрены команды управления процессами. Вы научитесь замораживать процессы, размораживать, отправлять в фоновый режим, изменять приоритет, просматривать запущенные процессы и жестоко их убивать. Введено понятие сигналов. Рассмотрены такие команды, как bg, fg, jobs, kill, nohup, nice, renice, ps и top.



Навигация по основам Linux от основателя Gentoo:

Часть I
  1. BASH: основы навигации (вступление)
  2. Управление файлами и директориями
  3. Ссылки, а также удаление файлов и директорий
  4. Glob-подстановки (итоги и ссылки)

Часть II
  1. Регулярные выражения (вступление)
  2. Назначения папок, поиск файлов
  3. Управление процессами
  4. Обработка текста и перенаправления
  5. Модули ядра (итоги и ссылки)



Управление процессами


Запуск xeyes


Для изучения управления процессами, какой-нибудь процесс необходимо сначала запустить. Убедитесь, что у вас запущен X (графический сервер — прим. пер.) и выполните следующую команду:



$ xeyes -center red

Вы увидите всплывающее окошко xeyes и красные глаза, следящие за курсором мыши. Также, обратите внимание, что у вас не появилось приглашения для ввода команд в терминале.



Остановка процесса


Чтобы вернуть приглашение, вы должны нажать Control-C (часто пишется как Ctrl-C или ^C):



Вы получили назад свое приглашение, но и окно xeyes исчезло. Фактически, процесс был «убит». Вместо завершения по Control-C, мы можем просто остановить процесс с помощью Control-Z:



$ xeyes -center red
Control-Z

[1]+  Stopped                 xeyes -center red
$

На этот раз вы получите приглашение bash'a, а окно xeyes останется сверху. Если вы с ним немного поиграете, возможно заметите, что глаза заморожены на одном месте. Если окно xeyes будет перекрыто другим окном и затем снова открыто, вы увидите, что оно даже не перерисовалось. Процесс не делает ничего. Он на самом деле остановлен.



fg и bg


Чтобы процесс «растормошить» и запустить обратно, мы можем вывести его на передний план используя команду fg (от англ. foreground — прим. пер.):



$ fg
(test it out, then stop the process again)
Control-Z

[1]+  Stopped                 xeyes -center red
$

А теперь продолжим его в фоне с помощью команды bg (от англ. backgroud — прим. пер.):



$ bg
[1]+ xeyes -center red &
$


Прекрасно! Процесс xeyes сейчас запущен в фоновом режиме, а мы снова имеем приглашение bash.



Использование "&"


Если нам нужно сразу запустить xeyes в фоновом режиме (вместо использования Control-Z и bg), мы можем просто добавить "&" (амперсанд) в конец команды xeyes:



$ xeyes -center blue &
[2] 16224


Несколько фоновых процессов


Теперь в фоне у нас одновременно работают красные и синие xeyes. Мы можем просмотреть список заданий с помощью jobs:



$ jobs -l
[1]- 16217 Running xeyes -center red & [2]+ 16224 Running xeyes -center blue &

Число в левой колонке — это порядковый номер задания, который bash присваивает ему при запуске. Плюс (+) у второго задания значит, что это «текущее задание», оно будет выведено на передний план при вводе fg. Вы также можете вывести на передний план конкретное задание указывая его номер; например, fg 1 сделает таковым красный xeyes. Следующая колонка это идентификатор процесса или сокращенно pid, любезно добавленный в вывод благодаря опции -l. Наконец, состояние обоих процессов «Running» (выполняется) и их командная строка справа.



Введение в сигналы


Чтобы убить, остановить, или продолжить процесс, Linux использует специальную форму взаимодействия, называемую сигналы. Отправляя сигнал некоторому процессу, вы можете его завершить, остановить, или сделать что-нибудь еще. Это то, что происходит на самом деле, когда вы нажимаете Control-C, Control-Z, или используете bg и fg — вы указываете bash отправить процессу определенный сигнал. Сигналы также можно отправить с помощью команды kill указав ей как параметр id процесса (pid):



$ kill -s SIGSTOP 16224
$ jobs -l
[1]- 16217 Running xeyes -center red & [2]+ 16224 Stopped (signal) xeyes -center blue

Как можно заметить, kill не обязательно «убивает» процесс, хотя может и это. Используя опцию -s, kill может отправить процессу любой сигнал. Linux убивает, останавливает или продолжает процессы когда они получают SIGINT, SIGSTOP, или SIGCONT сигнал соответственно. Есть и другие сигналы, которые вы можете отправить процессам; некоторые сигналы могут обрабатываться внутри самих программ. Вы можете узнать о сигналах которые обрабатывает конкретная программа поискав в ее man'е секцию SIGNALS.



SIGTERM и SIGINT


Если вы хотите убить процесс, есть несколько вариантов. По-умолчанию, kill отправляет SIGTERM, который отличается от SIGINT отправляемого по Control-C, но обычно имеет тот же эффект:



$ kill 16217
$ jobs -l
[1]- 16217 Terminated xeyes -center red [2]+ 16224 Stopped (signal) xeyes -center blue

Полное убийство


Процесс может игнорировать оба сигнала, SIGTERM и SIGINT, либо по своему усмотрению, либо потому, что он остановлен, либо еще как-то «застрял». В этом случае, может быть необходимо использование большого молотка — сигнала SIGKILL. Процесс не может игнорировать SIGKILL:



$ kill 16224
$ jobs -l

[2]+ 16224 Stopped (signal)        xeyes -center blue
$ kill -s SIGKILL 16224
$ jobs -l
[2]+ 16224 Interrupt xeyes -center blue

nohup


Терминал в котором вы запускаете задания, называется терминалом управления заданиями. Некоторые шеллы (но не bash по-умолчанию), отправляют сигнал SIGHUP фоновым заданиям когда вы выходите, заставляя их завершаться. Для защиты процессов от такого поведения, используйте nohup когда запускаете процесс:



$ nohup make &
[1] 15632
$ exit


Используем ps для вывода списка процессов


Команда jobs, которую мы использовали ранее выводит только те процессы, которые были запущены в вашей сессии bash. Чтобы увидеть все процессы в вашей системе, используйте ps совместно с опциями a и x:



$ ps ax
PID TTY STAT TIME COMMAND 1 ? S 0:04 init [3] 2 ? SW 0:11 [keventd] 3 ? SWN 0:13 [ksoftirqd_CPU0] 4 ? SW 2:33 [kswapd] 5 ? SW 0:00 [bdflush]

Здесь приведены только первые 5 процессов, поскольку обычно список процессов очень длинный. Команда дает вам «слепок» всего, что в данный момент выполняется на машине, однако в нем много лишней информации. Если бы вы, не указали ax, вы бы получили список только тех процессов, которые принадлежат вам, и которые есть в управляющем терминале. Команда ps x покажет все ваши процессы, даже те, которых нет в управляющем терминале. Если использовать ps a, то будет получен список процессов из терминалов всех пользователей.



Просмотр «леса» и «деревьев»


Вы также можете просмотреть и другую информацию о каждом процессе. Опция --forest позволяет легко просмотреть иерархию процессов и даст вам представление о том, как различные процессы в системе взаимосвязаны между собой. Если один процесс запускает другой процесс, то запущенный будет называться его потомком. В выводе --forest, родители находятся слева, а потомки появляются как ветки справа:



$ ps x --forest
PID TTY STAT TIME COMMAND 927 pts/1 S 0:00 bash 6690 pts/1 S 0:00 \_ bash 26909 pts/1 R 0:00 \_ ps x --forest 19930 pts/4 S 0:01 bash 25740 pts/4 S 0:04 \_ vi processes.txt

«u» и «l» опции ps


Опции u и l могут быть использованы в любой комбинации с опциями a, x с целью получения более подробной информации о процессах:



$ ps au
USER       PID %CPU %MEM   VSZ  RSS TTY      STAT START   TIME COMMAND
agriffis   403  0.0  0.0  2484   72 tty1     S     2001   0:00 -bash
chouser    404  0.0  0.0  2508   92 tty2     S     2001   0:00 -bash
root       408  0.0  0.0  1308  248 tty6     S     2001   0:00 /sbin/agetty 3
agriffis   434  0.0  0.0  1008    4 tty1     S     2001   0:00 /bin/sh /usr/X
chouser    927  0.0  0.0  2540   96 pts/1    S     2001   0:00 bash
$ ps al
  F   UID   PID  PPID PRI  NI   VSZ  RSS WCHAN  STAT TTY        TIME COMMAND
100  1001   403     1   9   0  2484   72 wait4  S    tty1       0:00 -bash
100  1000   404     1   9   0  2508   92 wait4  S    tty2       0:00 -bash
000     0   408     1   9   0  1308  248 read_c S    tty6       0:00 /sbin/ag
000  1001   434   403   9   0  1008    4 wait4  S    tty1       0:00 /bin/sh
000  1000   927   652   9   0  2540   96 wait4  S    pts/1      0:00 bash

Использование top


Если вы обнаружили, что запускаете ps несколько раз подряд, пытаясь рассмотреть происходящие изменения, возможно вам стоит воспользоваться top. Программа top отображает постоянно обновляющийся список процессов, наряду с другой полезной информацией:



$ top
10:02pm up 19 days, 6:24, 8 users, load average: 0.04, 0.05, 0.00 75 processes: 74 sleeping, 1 running, 0 zombie, 0 stopped CPU states: 1.3% user, 2.5% system, 0.0% nice, 96.0% idle Mem: 256020K av, 226580K used, 29440K free, 0K shrd, 3804K buff Swap: 136544K av, 80256K used, 56288K free 101760K cached PID USER PRI NI SIZE RSS SHARE STAT LIB %CPU %MEM TIME COMMAND 628 root 16 0 213M 31M 2304 S 0 1.9 12.5 91:43 X 26934 chouser 17 0 1272 1272 1076 R 0 1.1 0.4 0:00 top 652 chouser 11 0 12016 8840 1604 S 0 0.5 3.4 3:52 gnome-termin 641 chouser 9 0 2936 2808 1416 S 0 0.1 1.0 2:13 sawfish

nice


Каждый процесс имеет свое значение приоритета, которое Linux использует для разделения времени CPU. Вы можете указать приоритет процесса при его запуске, с помощью команды nice:



$ nice -n 10 oggenc /tmp/song.wav

С тех пор, как приоритет стал называться nice, он стал легче для запоминания, так, большее значение nice делает «хорошо» (nice — хорошо, замечательно; прим. пер.) другим процессам, позволяя им получить более приоритетный доступ к времени CPU. По-умолчанию, процессы запускаются с приоритетом 0, поэтому установка приоритета в 10 для oggenc значит, что он будет давать больше времени поработать другим процессам. Как правило, это означает, что oggenc даст возможность другим процессам выполняться со своей обычной скоростью, не зависимо от того, сколько времени процессора хочет сам oggenc. Вы могли видеть эти «уровни любезности» в колонке NI у ps и top ранее.



renice


Команда nice может изменять приоритет процессов только во время их запуска. Если вам необходимо изменить приоритет работающего процесса, воспользуйтесь командой renice:



$ ps l 641
F UID PID PPID PRI NI VSZ RSS WCHAN STAT TTY TIME COMMAND 000 1000 641 1 9 0 5876 2808 do_sel S ? 2:14 sawfish

$ renice 10 641
641: old priority 0, new priority 10

$ ps l 641
  F   UID   PID  PPID PRI  NI   VSZ  RSS WCHAN  STAT TTY        TIME COMMAND
000  1000   641     1   9  10  5876 2808 do_sel S    ?          2:14 sawfish


Спасибо Dmitry Minsky (Dmitry.Minsky@gmail.com) за перевод.



Продолжение...



Об авторах


Daniel Robbins


Дэниэль Роббинс — основатель сообщества Gentoo и создатель операционной системы Gentoo Linux. Дэниэль проживает в Нью-Мехико со свой женой Мэри и двумя энергичными дочерьми. Он также основатель и глава Funtoo, написал множество технических статей для IBM developerWorks, Intel Developer Services и C/C++ Users Journal.



Chris Houser


Крис Хаусер был сторонником UNIX c 1994 года, когда присоединился к команде администраторов университета Тэйлора (Индиана, США), где получил степень бакалавра в компьютерных науках и математике. После он работал во множестве областей, включая веб-приложения, редактирование видео, драйвера для UNIX и криптографическую защиту. В настоящий момент работает в Sentry Data Systems. Крис также сделал вклад во множество свободных проектов, таких как Gentoo Linux и Clojure, стал соавтором книги The Joy of Clojure.



Aron Griffis


Эйрон Гриффис живет на территории Бостона, где провел последнее десятилетие работая в Hewlett-Packard над такими проектами, как сетевые UNIX-драйвера для Tru64, сертификация безопасности Linux, Xen и KVM виртуализация, и самое последнее — платформа HP ePrint. В свободное от программирования время Эйрон предпочитает размыщлять над проблемами программирования катаясь на своем велосипеде, жонглируя битами, или болея за бостонскую профессиональную бейсбольную команду «Красные Носки».

Поделиться публикацией
Ой, у вас баннер убежал!

Ну. И что?
Реклама
Комментарии 20
  • НЛО прилетело и опубликовало эту надпись здесь
      +1
      Спасибо! Складываю каждую часть в dropbox =)
        –6
        Полезность такого мануала сомнительна…

        Основы ведь и так есть в хендбуке, а тонкости всё равно всё забудутся, и придётся каждый раз подсматривать, пока не наступит просветление. А для этих целей лучше какой-нибудь небольшой cheatsheet подойдёт…

          +1
          Вы про какой хэндбук?
            –4
            Gentoo handbook — он такой один.
              +2
              А вы его сами то видели? Ну и покажите мне где там хоть намек на материал описанный тут?
            +2
            тонкостей тут вроде нету, но их всегда можно узнать в мане, главное — основы, а они как раз в статье и описаны
              +2
              Полезность Вашего коммента сомнительна…

              Я давно с Linux и некоторые вещи для меня тут оказались полезны. Если это для Вас очевидно — это еще не значит что все это знают.

              За --forest и renice спасибо.
              Пост отличный, разждевано так, что просто глотай.
              Ждём продолжения!
              +1
              добавлю крупицу инфы.
              Существует понятие — zombie-process. Это процесс порожденный другим процессом, и уже остановленный. Все что в нем сохранилось — лишь информация о коде возврата, и еще несколько системных значений. Система будет хранить зомби-процесс до тех пор пока родительский процесс не вызовет wait() или же пока сам родитель не завершится.

              Классической ошибкой программиста будет в данном случае создание процессов exec() без последующего вызова wait()- так как в этом случае ваше приложение будет постоянно плодить новых и новых зомби.
              Решением проблемы станет вызов wait/waitpid или же использование сигнала:
              signal(SIGCLD, SIG_IGN);
              этот код, вызванный до создания новых процессов, приведет к автоматическому удалению зомби ( и если вам не нужно считывать информацию о завершившихся порожденных процессах — это будет самое простое решение ).
                0
                а как получить список зомби?
                  0
                  ps aux | grep program_name
                  процессы с флагом Z+ и будут зомби
                    0
                    статус процесса.
                    например если статус = D (Uninterruptible sleep) — его не убьешь, пока он не выйдет из такого состояния. а если процесс надолго завис в такое статусе это очень неприятно, возможно проблемы с дисковыми устройствами.
                    +1
                    ps -el | grep -e '^.\sZ'
                    0
                    Разве init не наследует зомби с целью получить их код? ИМХО вы цитируете какую-то древнюю книжку по юниксам; я ни разу не видел «орд зомби» под линуксом, какие бы неприличности там не творились.

                    А уж сколько forc'ов я лично делал без получения кода… И никаких проблем.
                      0
                      насчет древней книжки не знаю, у меня такое случилось буквально вчера на живом примере, когда после проги осталось 200 зомбей, процессов которые она вызывала через fork() exec() и без последующего wait(). Вылечилось как написал выше.
                      может дело в том что ваша программа завершалась после всех «безобразий» а моя работала долго, и все зомби естественно жили только пока она была жива.
                        0
                        А, понял. Речь про долго работающие программы. Да, init наследует зомби после смерти родителя. Если родитель долго работает, будут зомби.

                        PS Кстати, а почему init? pid=0 — это swapper. Странная логика…
                    0
                    Что такое «остановленный процесс»? Ему просто не выделяется процессорное время?
                      +1
                      Именно. В виндах такого понятия нет, так что мигрирующим приходится долго осознавать такую простую вещь — программу можно «остановить», а потом «продолжить». Очень удобно, если есть какие-то подозрения относительно программы. Остановил, изучил, продолжил.
                      0
                      За --forest спасибо, не знал.
                        +1
                        Есть еще pstree, но он отображает значительно меньше информации.

                        pstree -p — отобразить дерево процессов с принадлежащими pid;
                        pstree -u — отобразить дерево процессов с принадлежащими uid;
                        pstree -pu — отобразить дерево процессов с pid и uid.

                        Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                        Самое читаемое