Почему некоторые команды «виснут» терминал до тех пор, пока они не закончатся?

Иногда вы запускаете программу с терминала, скажем, lxpanel . Терминал не вернет вас обратно в подсказку, он повесит. Вы можете нажать Ctrl + C, чтобы вернуться в приглашение, но это убьет lxpanel . Тем не менее, нажатие Alt + F2 (которое выдает окно, чтобы взять команду) и запуск lxpanel работает изящно.

Почему это? Что происходит между запуском команды из терминала и из окна «run», которое появляется при нажатии Alt + F2 ?

Здесь использовался только lxpanel. Я испытал это с помощью нескольких программ

По умолчанию терминал запускает программу на переднем плане, поэтому вы не вернетесь в оболочку до завершения программы. Это полезно для программ, которые читают из stdin и / или записывают в stdout – вы, как правило, не хотите, чтобы многие из них работали сразу. Если вы хотите, чтобы программа запускалась в фоновом режиме, вы можете запустить ее следующим образом:

 $ lxpanel & 

Или, если он уже запущен, вы можете приостановить его с помощью Ctrl + Z, а затем запустить bg чтобы переместить его в фоновый режим. В любом случае вы получите новое приглашение оболочки, но программа все еще работает, и его вывод появится в терминале (так что он может внезапно появиться, пока вы находитесь в середине набора)

Некоторые программы (обычно демоны) разворачивают отдельный процесс, когда они запускаются, а затем позволяют главному процессу немедленно выйти. Это позволяет программе работать без блокировки оболочки

Когда вы запускаете программу в терминале, терминал будет «зависать», пока ваша программа не остановится. Нажимая Ctrl + c, вы закрываете свою программу и возвращаетесь к подсказке. Вы увидите это со всеми графическими приложениями, например, попробуйте Firefox.

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

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

 lxpanel & 

Это говорит о том, что терминал запускает lxpanel в фоновом режиме и дает вам другое приглашение сразу.

Программы запускаются с помощью запуска оболочки на переднем плане этой оболочки по умолчанию. Это заставляет оболочку приостанавливать работу и направлять stdin / stdout / sterr из терминала в программу. Программы, запускаемые через среду рабочего стола, разворачиваются , что заставляет их запускаться независимо от программы, которая их запускала. Это можно смоделировать в большинстве оболочек, добавив команду & к команде, хотя это все равно будет подключать std * к терминалу (хотя чтение из stdin в фоновой программе имеет дополнительные сложности).

& Backgrounds хорошо, за исключением программ, которые возвращаются, требуя взаимодействия с консолью позже (например, «apt -y update &», который в конечном итоге входит в состояние STOP, поскольку он хочет пригласить пользователя на вопрос «действительно на самом деле?» Намного позже …. когда никто больше не смотрит).

Чтобы подключить это отверстие и сообщить о процессе, терминал никогда не станет для него недоступным, я добавлю <& – в некоторые из моих команд, полностью отсоединяя их от активного терминала, сообщая им, что STDIN больше не существует. Убедитесь, что / bin / bash – это ваша оболочка, если вы используете это. Сценарий будет вести регистрацию любых ошибок, связанных с отсутствием псевдотерминала, на котором можно было бы отправить любое приглашение.

Например:

 `./runme.sh &> runme.log <&- & disown` 

является моим окончательным способом disassociation от текущей сессии терминала. Как STDOUT, так и STDERR регистрируются в runme.log, не имеет значения, закончится ли ваша консоль или оболочка раньше или если вы выходите из / в другую учетную запись (без терминального мусора из runme), и, благодаря отключению даже родительского-дочернего Связь PID удаляется.

ОБНОВЛЕНИЕ: даже с этим у меня были проблемы с семафором, связанным с именем исходного родителя, поэтому теперь я рекомендую вместо этого:

 at now <<< "(cmd1; cmd2; etc.) &> logfile.log" 

Конечно, удалите &>, если вы хотите получить по электронной почте вывод из CRON, или перенаправить все это на / dev / null вместо файла.