Управление приоритетными и фоновыми процессами в bash

В предыдущей статье вы имели возможность ознакомиться с командами ps, kill и nice. В данном руководстве речь пойдёт о том, как управлять процессами bash.

Руководство сосредоточено на управлении приоритетными и фоновыми процессами. С его помощью вы научитесь использовать функции управления заданиями оболочки и сделать процессы более гибкими.

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

Большинство процессов, запущенных на машине Linux, работает на переднем плане. При этом выполняемые команды будут блокировать оболочку на период выполнения. Процесс может быть интерактивным. После выполнения процесса в терминале появится вывод. В данном разделе речь пойдёт об управлении процессами переднего плана.

Запуск процесса

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

Некоторые команды переднего плана выполняются очень быстро и возвращают вас в командную строку оболочки почти мгновенно. Вот одна из таких команд:

echo "Hello World"

Эта команда вернёт фразу Hello World в терминале, после чего вы снова сможете использовать командную строку.

Другие команды переднего плана могут занять больше времени. Это бывает потому, что команда выполняет расширенную операцию или настроена таким образом, что будет работать, пока её не остановят вручную.

Примером команды, которая может работать неопределенный срок, является top. После запуска эта команда будет обновлять экран, пока пользователь не прервёт процесс:

top

Чтобы остановить процесс, нужно нажать q. Некоторые процессы, однако, невозможно остановить таким образом, поскольку у них нет такой встроенной функции. Их придётся останавливать при помощи других методов.

Завершение процесса

Предположим, что вы запустили простой цикл bash в командной строке. Пусть этот цикл будет отображать фразу Hello World каждые десять секунд. Этот цикл будет продолжаться до тех пор, пока пользователь не завершит его.

while true; do echo "Hello World"; sleep 10; done

Циклы не имеют ключа quit, то есть их нельзя остановить, просто нажав q. Остановить этот процесс можно, только отправив ему сигнал. В системах Linux ядро может посылать процессам сигналы, чтобы завершить их или изменить их состояние. Обычно терминалы Linux посылают сигнал SIGINT (как правило, сигнал № 2) текущему процессу переднего плана при нажатии комбинации клавиш CTRL-C. Сигнал SIGINT говорит программе, что пользователь завершает процесс с помощью клавиатуры.

Итак, чтобы остановить запущенный ранее цикл, нужно нажать:

CTRL-C

После этого цикл остановится.

Сигнал SIGINT, отправленный при помощи клавиш CTRL-C, – всего лишь один из множества доступных сигналов. Большинство сигналов нельзя отправить при помощи комбинаций клавиш, такие сигналы отправляются с помощью команды kill.

Приостановка процесса

Как было сказано ранее, процесс переднего плана будет блокировать доступ к оболочке в течение всего срока его исполнения. Но что делать, если после запуска процесса на переднем плане вам нужен доступ к терминалу?

Для этого существует сигнал SIGTSTP (обычно это сигнал №20). Его можно отправить при помощи комбинации клавиш CTRL-Z. При этом терминал регистрирует команду suspend, которая приостанавливает выполнение процесса и возвращает пользователя в интерактивную среду.

Для примера попробуйте запустить команду ping, которая будет подключаться к google.com каждые 5 секунд. Перед командой ping нужно ввести префикс command, который позволит обойти алиасы оболочки:

command ping -i 5 google.com

Чтобы приостановить запущенный процесс, нажмите:

CTRL-Z

На экране появится вывод:

[1]+  Stopped                 ping -i 5 google.com

Как видите, команда ping временно остановлена, а у вас снова появился доступ к командной строке оболочки. Используйте инструмент ps, чтобы убедиться в этом:

ps T
PID TTY      STAT   TIME COMMAND
26904 pts/3    Ss     0:00 /bin/bash
29633 pts/3    T      0:00 ping -i 5 google.com
29643 pts/3    R+     0:00 ps t

Как видите, процесс ping всё ещё в списке текущих процессов, однако в столбце STAT находится T. Это значит, что данный процесс был приостановлен с помощью сигнала управления процессами.

Об изменении состояния процессов речь пойдёт далее. На данный момент нужно восстановить выполнение приостановленной команды:

fg

Процесс будет восстановлен. Чтобы остановить его, используйте клавиши CTRL-C.

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

Также процессы можно запускать в фоновом режиме. Фоновый процесс связан с отдельным терминалом, но не блокирует доступа к оболочке, то есть пользователь может взаимодействовать с системой во время выполнения процесса.

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

Запуск процесса

Чтобы запустить процесс в фоновом режиме, добавьте в конец команды символ амперсанда (&). Тогда оболочка не станет ждать окончания процесса. Вывод команды будет отображаться в терминале (если он не перенаправлен в файл). Однако при этом можно вводить дополнительные команды.

К примеру, попробуйте запустить ту же команду ping в фоновом режиме.

command ping -i 5 google.com &

Вы увидите такой вывод системы управления задачами bash:

[1] 4287

А также стандартный вывод команды ping:

PING google.com (74.125.226.71) 56(84) bytes of data.
64 bytes from lga15s44-in-f7.1e100.net (74.125.226.71): icmp_seq=1 ttl=55 time=12.3 ms
64 bytes from lga15s44-in-f7.1e100.net (74.125.226.71): icmp_seq=2 ttl=55 time=11.1 ms
64 bytes from lga15s44-in-f7.1e100.net (74.125.226.71): icmp_seq=3 ttl=55 time=9.98 ms

Вывод фоновых процессов будет смешиваться со входными и выходными данными процессов переднего плана, но это не будет мешать исполнению приоритетных процессов.

Список фоновых процессов

Чтобы просмотреть список всех остановленных или переведённых в фоновый режим процессов, введите:

jobs

Если вы не остановили запущенную ранее команду ping, на экране появится такой результат:

[1]+  Running                 command ping -i 5 google.com &

Это значит, что на данный момент в фоновом режиме работает только один процесс, где [1] – порядковый номер процесса. При помощи этого номера можно ссылаться на процесс, то есть использовать номер в командах kill, fg, и bg; для этого нужно поставить символ процента перед номером процесса, например:

%1

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

Остановить текущий фоновый процесс можно несколькими способами. Проще всего использовать для этого команду kill, указав номер процесса. К примеру, чтобы остановить команду ping, нужно ввести:

kill %1

В зависимости от настроек терминала, чтобы получить вывод, нужно либо подождать, либо нажать Enter. На экране появится:

[1]+  Terminated              command ping -i 5 google.com

Чтобы убедиться, что процесс остановлен, запросите список фоновых процессов при помощи команды jobs.

Изменение состояния процесса

В данном разделе вы научитесь изменять состояние процесса. Мы уже затрагивали эту тему в данном руководстве, когда отправили команде сигнал CTRL-Z, чтобы приостановить её. Приостановленные процессы можно переводить из фонового режима на передний план и наоборот.

Перевод процесса в фоновый режим

Допустим, вы хотели запустить процесс в фоновом режиме, но забыли добавить в конец команды &, амперсанд. В таком случае можно просто перевести процесс в фоновый режим.

Для начала приостановите процесс:

CTRL-Z

После этого используйте команду bg, которая запустит процесс, но уже в фоновом режиме:

bg

Вы снова увидите состояние процесса:

[1]+ ping -i 5 google.com &

По умолчанию команда bg восстанавливает последний остановленный процесс. Если же вы остановили несколько процессов, и вам нужно восстановить их в фоновом режиме, просто укажите порядковый номер процесса.

Обратите внимание: не все команды можно перевести в фоновый режим. Некоторые процессы при переходе будут автоматически прерываться

Перевод фонового процесса на передний план

Фоновые процессы можно переводить на передний план. Для этого нужно ввести:

fg

По умолчанию эта команда восстанавливает последний процесс, переведённый в фоновый режим (он отмечен + в выводе команды jobs). Команда немедленно приостанавливает процесс и переводит его на передний план. Вы также можете задать номер процесса, который нужно перевести:

fg %2

Переведя процесс на передний лан, вы можете остановить его при помощи CTRL-C, позволить ему завершиться, приостановить или снова вернуть в фоновый режим.

Сигнал SIGHUP

Независимо от того, где выполняется процесс (в фоновом режиме или на переднем плане), он довольно тесно связан с терминалом, в котором он был запущен. Когда терминал закрывается, он обычно посылает сигнал SIGHUP всем привязанным к нему процессам (фоновым, приоритетным, приостановленным). Этот сигнал остановит процессы, потому что их управляющий терминал будет в скором времени недоступен. Но что делать, если вы хотите закрыть терминал и при этом сохранить фоновые процессы?

Существует несколько способов сделать это. Как правило, для этого используются инструменты screen или tmux.

Однако это не всегда подходит.

Команда nohup

Если, запуская процесс, вы знаете, что в дальнейшем вам нужно будет закрыть терминал до завершения процесса, запустите его при помощи команды nohup. Эта команда позволяет запущенному процессу игнорировать сигнал SIGHUP. Даже если терминал будет закрыт, процесс продолжит работу в качестве дочернего процесса системы инициализации:

nohup ping -i 5 google.com &

Вывод будет иметь такой вид:

nohup: ignoring input and appending output to ‘nohup.out’

Это значит, что вывод команды будет записан в файл nohup.out (в текущем каталоге, если он доступен для записи, или в домашнем каталоге).

Если вы закроете терминал и откроете новое окно, процесс все равно будет работать. Его не будет в выводе команды jobs, потому что каждый терминал поддерживает индивидуальную очередь заданий. Закрывая терминал, вы остановите задание ping, но не процесс ping.

Чтобы остановить процесс ping, нужно найти PID процесса (его идентификационный номер). Для этого используется команда pgrep и флаг –a:

pgrep -a ping
7360 ping -i 5 google.com

Теперь вы можете остановить процесс, добавив в команду его PID (первый столбец вывода):

kill 7360

После этого можно удалить файл nohup.out.

Команда disown

Команда nohup очень полезна, но только если вы заранее знаете, что вам нужно будет закрыть терминал. Система управления заданиями bash предоставляет другие методы достижения аналогичных результатов, один из них – встроенная команда disown.

Команда disown удаляет задачу из очереди заданий терминала. Это означает, что этим процессом больше нельзя управлять с помощью описанных ранее механизмов управления заданиями (например, fg, BG, CTRL-Z, CTRL-C). Процесс будет немедленно удален из списка команды jobs и больше не будет связан с терминалом.

Для вызова команды нужно указать номер процесса. Например:

disown %2

Теперь процесс находится примерно в том же состоянии, что и при использовании nohup. Единственное отличие состоит в том, что весь вывод будет утрачен после закрытия терминала, если его предварительно не перенаправить в файл.

Как правило, полностью удалять процесс из очереди задач не нужно. Флаг –h позволяет процессу игнорировать сигнал SIGHUP и оставаться в списке задач:

disown -h %1

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

Опция huponexit

При помощи опции huponexit bash посылает сигнал SIGHUP всем заданиям при завершении работы интерактивного начального командного интерпретатора.

Примечание: Опция huponexit влияет на поведение сигнала SIGHUP только если завершение сессии было инициировано внутри оболочки (команда exit или CTRL-D). Если сессия прерывается самой программой терминала, опция huponexit не работает, поскольку в таком случае сигнал SIGHUP отправляется не оболочкой, а терминалом.

Чтобы узнать, включена ли опция huponexit, введите:

shopt huponexit

Чтобы включить опцию, используйте команду:

shopt -s huponexit

Теперь попробуйте закрыть сессию при помощи команды exit. При этом процесс продолжит работу:

exit

При этом также есть вероятность потерять вывод, если он не был перенаправлен в файл.

Tags: ,

Добавить комментарий