Управление выполняющимися процессами в шелле
Уверен, многие новички, пытаясь пользоваться шеллом, наивно полагают, что в одном терминале может выполняться только одно приложение. Чуть более продвинутые слышали о (якобы монструозном) screen
’е, позволяющим делать разные страшные штуки, в том числе запускать в одной консоли много приложений сразу. При этом очень полезные built-in команды часто остаются незамеченными. О них и пойдёт речь.
Сразу замечу, что в посте будут описаны bash и zsh. Другие шеллы могут не поддерживать указанных команд.
Итак, представим себе ситуацию: вы запустили какую-то долго выполняющуюся команду, скажем, find
, и ждёте её вывода. Тут у вас появилась какая-то идейка, и вы уже тянетесь к клавиатуре, но шелл ведь занят, верно? Не беда — жмите ctrl+z
и воплощайте идею в жизнь. Когда закончите, наберите fg %1
— и прерванная команда продолжит выполняться.
Давайте теперь разберём, как же это работает. Когда вы нажимаете ctrl+z
, текущий процесс приостанавливается («suspend» — «приостанавливать»). Следует понимать, что пока процесс приостановлен, он никак не реагирует на внешние раздражители — например, если вы приостановили какое-то графическое приложение, его окно не будет перерисовываться, а если это был wget
— он не будет ничего качать.
Команда fg
(название которой, как вы догадались, происходит от «foreground» — «передний план») выполняет абсолютно противоположную задачу — она запускает (можно сказать, снимает с паузы) приостановленное приложение. Аргумент указывает на то, какую именно задачу следует запустить.
Из предыдущего абзаца можно сделать два полезных вывода:
- вы можете приостанавливать более чем одну задачу одновременно;
- каждая приостановленная задача имеет свой собственный номер, так что ими легко оперировать.
Таким образом мы приходим к третьей команде — jobs
. Несложно догадаться, что она выводит список всех задач вместе с их номерами.
Менее очевидной, но всё же верной догадкой является то, что помимо fg
должна существовать и парная ей команда bg
(«background» — «фон»). Её задача — продолжить выполнение приостановленного процесса в фоне. Очень удобно с командами, вывод которых перенаправлен в файл: они ведь ничего не выводят на экран, так что нам нечего пялиться на занятый шелл — поместили её в фон и работаем дальше. Синтаксис bg
ничем не отличается от оного у fg
— команда принимает на вход номер задачи, выполнение которой следует продолжить в фоне. Кстати, отправить задачу в фон можно сразу же — достаточно просто дописать в конце команды амперсанд, например, вот так:
updatedb &
Недостаток всей этой системы один: при закрытии шелла все задачи прерываются. Возможно, в годы чистой консоли такое поведение и не мешало спокойно работать, но в наше время, когда многие смешивают Иксы и терминал, нередки ситуации вроде такой: из терминала запускается графическая утилитка, после чего терминал можно было бы закрыть, но нет, нельзя, иначе утилита тоже закроется. Грустно…
К счастью, даже для такой задачи у шелла есть решение, а имя ему — disown
. Эта команда делает именно то, что нам нужно — она открепляет определённую задачу от шелла. Синтаксис ничем не отличается от fg
и bg
— команда принимает номер задачи. Команду также можно использовать вот в таком виде:
command & disown
(обратите внимание, что амперсанд всего один!) При этом процесс, созданный командой command
, сразу же открепляется от шелла, так что вам не надо ничего больше вводить. Счастливые пользователи ZSH могут использовать сокращённую запись:
command &!
Правда, disown
имеет некую специфику — если выполнить её для приостановленной задачи, задача так и останется приостановленной. Выход — сигнал CONT
. После того, как сделали disown приостановленной задачи, наберите:
kill -CONT PID
где PID — это номер процесса, который мы только что открепили от консоли. Не пугайтесь команды kill
— она вовсе не обязательно убивает процесс: как видите, с её помощью можно мирно передавать процессам какие-то команды (ещё один пример такого поведения — conky: если выполнить kill -USR1 PID
, коньки перечитают свой конфиг). Отдельное слово также надо сказать про PID — BASH говорит его сам:
bash: warning: deleting stopped job 1 with process group 23710
(последнее число и есть искомый IDшник), а ZSH и вовсе выдаёт готовую команду:
disown: warning: job is suspended, use `kill -CONT -24309' to resume
Собственно, на этом разговор об управлении процессами в шелле можно считать законченным. В качестве дополнительной литературы могу посоветовать вывод help fg
, help bg
, help jobs
и help disown
. До встречи!
Comments (migrated from Blogger)
On 2010-05-27T18:38:41.619+03:00, Minoru wrote:
Так и знал, что кто-то таки спалит :) Короче, про screen, nohup и dtach — тссс! Про них я ещё напишу.
On 2010-05-27T19:04:27.853+03:00, Анонимный wrote:
можно включить новый tab и ничего не нужно прерывать
On 2010-05-27T19:23:02.302+03:00, Minoru wrote:
> можно включить новый tab и ничего не нужно прерывать
Можно. Но в tty, например, вы не найдёте табов, как, впрочем, и в легковесных исковых терминалах (xterm, емнип, не умеет). Да и в любом случае — неужели Вы, уважаемый анонимус, против получения новых знаний?
On 2010-05-27T19:26:53.866+03:00, Pavel Vyazovoi wrote:
>> Короче, про screen, nohup и dtach — тссс!
tmux не забудьOn 2010-05-27T19:34:01.821+03:00, Minoru wrote:
> tmux не забудь
М! Слышал о нём, но не знал, что он из этой оперы. Постараюсь разобраться и написать, спасибо за подсказку!
On 2010-05-28T00:49:21.617+03:00, bosha wrote:
>tmux не забудь
Ей! Не пали. У меня статья завтра про него опубликуется ;)On 2010-06-12T13:00:58.514+03:00, Анонимный wrote:
Здорово, наконец-то узнал как продолжить команду в фоне (bg). Да и здесь Вы описались: "Синтаксис bg ничем не отличается от оного у fg — команда принимает на вход номер задачи, которую следует отправить в фон." Должно быть типа "..активировать фоновую задачу"
On 2010-06-12T21:37:59.335+03:00, Minoru wrote:
> Да и здесь Вы описались: "Синтаксис bg ничем не отличается от оного у fg — команда принимает на вход номер задачи, которую следует отправить в фон." Должно быть типа "..активировать фоновую задачу"
Да, формулировку следовало бы поправить. Сейчас займусь. Спасибо за комментарий!
On 2010-09-10T10:02:37.112+03:00, Beggy wrote:
Век живи, век учись :)) Запись %1 меня поначалу смутила, но теперь после прочтения соответствующей секции man bash понимаю, что это как раз правильный способ.
Если позволите, я бы все-таки где нибудь вставил мысль, что все это внутренние команды конкретного shell (например bash) и они могут не поддерживаться или поддерживаться иначе в других. И пару слов о главном герое "&" - именно с него у новичков обычно начинается знакомство с "фоновыми" задачами.
А так - спасибо. Хорошая статья - буду рекомендовать :)
On 2010-09-10T17:02:49.470+03:00, Minoru wrote:
Спасибо, Beggy! С амперсандом я и правда дал маху :)
Добавил пару предложений в абзац о fg, а в начале поста дописал абзацик о том, что речь идёт о bash/zsh.
Your thoughts are welcome by email
(here’s why my blog doesn’t have a comments form)
On 2010-05-27T10:04:12.712+03:00, bosha wrote:
Вместо disown можно ещё использовать nohup: nohup command. Если шелл закрыть, процесс останется.