7.13. Использование контроля за задачами (job control)
Описание:
Кандидат должен знать как запустить процесс в фоновом режиме,
переместить запущенный процесс в фон, вернуть на передний план
процесс работающий в фоне. Кандидат должен уметь проверить
запущены ли какие-нибуть задачи в фоновом режиме и знать разницу
между командой kill(1) и встроенной в оболочку
командой kill.
Практика: &
, ^Z
,
jobs, fg,
bg
, и встроенная в оболочку
kill
.
Комментарий
Каждая команда (или, точнее, каждый конвейер, pipeline) в
sh(1) должен заканчиваться либо знаком ;
, либо &
.
В случае, если нет ни того ни другого, а в конце команды
пользователь просто нажал на клавишу <Enter>, неявно
подразумевается знак ;
.
Конвейер заканчивающийся на ;
выполняется «на переднем плане» (foreground). Оболочка
не возвращает приглашения до тех пор, пока конвейер не
отработает. Т.е. оболочка ждёт пока закончится процесс
выполняющийся на переднем плане.
Конвейер заканчивающийся на &
выполняется «в фоновом режимме» (в background).
Оболочка сразу возвращает приглашение, а процесс выполняется
параллельно с оболочкой.
Список Конвейеров и их статус можно посмотреть при помощи
встроенной в оболочку команды jobs. Эта
команда перечисляет запущенные в фоновом режиме процессы и
объясняет выполняются они или остановлены. В квадратных скобках
jobs сообщает номер задания, следующее
число — PID
процесса. Если у
задания стоит знак +
, то это «текущее
задание». С ним по умолчанию будут работать команды
bg и fg.
Конвейер выполняющийся в фоновом режиме можно перевести на
передний план при помощи команды fg [%n].
Необязательный аргумент — номер задания, его
сообщяет команда jobs, если он не указан,
на передний план будет переведено «текущее задание».
Чтобы перевести задание с переднего плана в фоновый режим, надо
послать ему из оболочки сигнал SIGSTOP
нажав
сочетание клавиш <Ctrl>+Z. После этого оболочка вернёт
приглашение, но процесс будет остановлен. Теперь надо послать
процессу сигнал SIGCONT
, для этого надо
выполнить либо команду fg и вернуть его на
передний план, либо bg и продолжить его в
фоновом режиме. Мне приходилось наблюдать как люди запускают
vi(1) (см. Раздел 7.3, «Навыки работы в vi(1)») и нажимат
в нём <Ctrl>+Z пребывая в заблуждении, что так выходят из
редактора. Спустя короткое время у них в оболочке накапливается
большое количество остановленных vi(1).
Для того, чтобы послать запущенному заданию иной сигнал, служит
встроенная команда kill. Она ведёт себя
идентично внешней команде kill(1), но в
отличие от последней, может послать сигнал заданию, не только по
PID
, но и по номеру, выдаваемому командой
jobs. Для этого, номер надо предварить знаком
%
. Если скомандовать kill %
без номера, будет уничтожено
«текущее задание».
| Замечание |
---|
Команда kill в sh(1)
нереализована. Она есть только в csh(1) (и
конечно в bash(1)). Остальные команды имеются
в обоих интерпретаторах.
|
Ниже приведён пример на csh(1).
%
sleep 1000 & sleep 2000 & sleep 3000 &
[1] 2028
[2] 2029
[3] 2030
%
fg %2
sleep 2000
^Z
Suspended
%
jobs
[1] - Выполняется sleep 1000
[2] + Suspended sleep 2000
[3] Выполняется sleep 3000
%
kill %
[2] Прервано sleep 2000
%
jobs
[1] + Выполняется sleep 1000
[3] - Выполняется sleep 3000
%
fg %3
sleep 3000
^Z
Suspended
%
bg
[3] sleep 3000 &
%
jobs
[1] + Выполняется sleep 1000
[3] Выполняется sleep 3000
%
kill %3
[3] Прервано sleep 3000
%
kill -STOP %
[1] + Suspended (signal) sleep 1000
%
kill -CONT %
[1] sleep 1000 &
%
jobs
[1] + Выполняется sleep 1000
%
|
Запускаем сразу три задания, все три сразу в фоновом режиме.
|
|
Задание номер 2 выводим на передний план.
|
|
Сочетанием <Ctrl>+Z заставляем его «заснуть»
и снова получаем приглашение командной строки. Фактически мы
послали процессу сигнал SIGSTOP . Ниже,
вывод команды jobs показывает, что второе
задание остановлено.
|
|
Поскольку мы не указали команде kill
номер задания, а указали просто знак процента, без числа,
было прервано «текущее задание» т.е. то, у
которого в выводе команды jobs стоял знак
плюс.
|
|
Выводим на передний план и усыпляем третье задание.
|
|
Теперь можно командой bg продолжить
выполнение усыплённого задания. Таким образом можно увести в
фоновый режим любое задание выполняющееся на переднем плане:
усыпить <Ctrl>+Z и продолжить bg.
|
|
Убиваем задание, но не «текущее», а по номеру
(номер указываем в явном виде).
|
|
Команда kill может послать любой сигнал,
в том числе сигнал SIGSTOP и
SIGCONT . Приведённая команда эквивалентна
сочетанию fg+<Ctrl>+Z. А следующая
эквивалентна команде bg.
|
| Важно |
---|
Никогда не запускайте команду sudo(8) в
фоновом режиме. Это типичная ошибка начинающего администратора:
напустить команду вроде: sudo find /etc ... &
Следующим номером программы утилита sudo(8)
спрашивает у администратора пароль, он вводит его не гладя на
экран и нажимает на <Enter>. Увы, пароль он вводит при
этом не в программу sudo(8), а в оболочку
(ведь sudo(8) запущена в фоне). После этого
пароль в открытом виде не только отображается на экран, но так
же сохраняется в разнообразных буферах и history-файлах. Лучше
запустите программу sudo(8) на переднем
плане, введите пароль, а потом переведите её в фоновый режим
описанным выше способом (<Ctrl>+Z и
bg).
|
Перечень сигналов, которые посылает команда
kill, и их описание можно найти в
man signal. С точки зрения
администрирования продставляют интерес следующие сигналы:
Таблица 7.13. Некоторые сигналы, представляющие интерес для
администратора
Сигнал | Номер | Описание |
---|
SIGHUP | 1 |
Посылается демонам для перечитывания ими
конфигурационных файлов, а так же всем
процессам-потомкам при уничтожении родителя. Если в
терминале надо запустить программу, которая будет
продолжаться и после закрытия терминала, её можно, как
вариант, запустить внутри программы
nohup(1), которая будет перехватывать
данный сигнал. Команда nohup встроена
в оболочку csh(1). Из
sh(1) её можно вызвать как внешнюю
программу.
|
SIGINT | 2 | Прерывание процесса. Этот сигнал посылается
процессу, когда в оболочке пользователь нажимает
клавишесочетание <Ctrl>+C |
SIGKILL | 9 |
Уничтожение процесса. Этот сигнал неперехватывается
приложением, больше того, оно даже ничего не узнаёт о
том, что применён данный сигнал. Фактически это сигнал
ядру о том, что данный процесс должен быть уничтожен.
|
SIGTERM | 15 |
Програмное завершение процесса. Приложение имеет
возможность перехватить его и выполнить необходимые
финализационные действия: стереть временные файлы,
освободить иные ресурсы и т.п. Именно этот сигнал
посылается приложению по умолчанию, когда команде
kill не указано какой сигнал надо
доставить процессу.
|
SIGSTOP | |
Остановить процесс (нельзя перехватить, направляется
ядру). Этот сигнал посылается процессу, когда в оболочке
пользователь нажимает клавишесочетание <Ctrl>+Z
|
SIGCONT | |
Продолжить остановленный процесс
|
Если сигнал направлен на PID
равный -1, он
доставляется всем процессам (если его вызвал суперпользователь)
или всем процессам данного пользователя. В
OpenBSD и NetBSD есть
дополнительные псевдо-PID
'ы 0 и -pgid,
служащие для доставки сигнала группам процессов.