Программы, запущенные из сеанса ssh, зависят от соединения?

29

Зависит ли программа, запущенная от ssh-сессии, от соединения с клиентом? Например, когда соединение действительно медленное. Так активно ли он ждет, пока что-то будет напечатано на экране?

И если это зависит от соединения, это также происходит с экраном или byobu, например? Поскольку с этими программами продолжают работать даже после отключения от хоста.


Примечание: я нашел только эти связанные вопросы:

Agold
источник
1
Обратите внимание, что если ваше соединение потеряно, программа продолжит работу до истечения времени ожидания сеанса (если она не застряла в операции печати), но если ваш сеанс завершится, программа будет завершена изящно.
Себб

Ответы:

26

Вывод программ буферизуется, поэтому, если соединение медленное, программа будет остановлена, если буфер заполнится.

Если вы используете screen, он также имеет буфер, который он использует, чтобы попытаться отобразить в подключенном сеансе. Но программа, подключенная в сеансе экрана, не будет остановлена, если screenне сможет достаточно быстро обновить удаленный терминал. Так же, как когда соединение потеряно, программа продолжает заполнять screensбуфер, пока он не переполнится (выталкивает самую старую информацию). То, что вы видите (и можете прокрутить назад), зависит от того, что находится (еще) в этом буфере. screenэффективно отсоединяет вашу программу от вашего терминала (и вашего медленного SSH-соединения).

Энтон
источник
9

Соединение SSH может преждевременно прерваться, если базовое TCP-соединение получит пакет с флагом RST . Это может произойти, если одна сторона отправляет пакет (который может быть периодическим проверкой активности активности SSH), но не получает подтверждение TCP в течение разумного промежутка времени, или если маршрутизатор решает, что соединение слишком долго простаивает, или если Интернет-провайдер - это просто зло.

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

Из FAQ для программиста Unix , пункт 1.15:

SIGHUPявляется сигналом, который означает, что «терминальная линия зависла». Он не имеет ничего общего с родительскими процессами и обычно генерируется драйвером tty (и доставляется в группу процессов переднего плана).

Тем не менее, как часть системы управления сеансами, существует ровно два случая, когда SIGHUPотправляется в случае смерти процесса:

  • Когда умирающий процесс является лидером сеанса сеанса, который подключен к терминальному устройству, SIGHUPон отправляется всем процессам в группе процессов переднего плана этого терминального устройства.

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

Обработчик сигнала по умолчанию для SIGHUP является завершение процесса:

Signal     Value     Action   Comment
----------------------------------------------------------------------
SIGHUP        1       Term    Hangup detected on controlling terminal
                              or death of controlling process

Однако можно избежать завершения процесса.

  • Вы можете вставить обработчик сигнала, который игнорирует SIGHUP. Чтобы сделать это как пользователь, оберните команду в nohup. Например:

    nohup make all &
    
  • Вы можете сказать оболочке отделить от нее дочерний процесс. Например, Bash имеет disownвстроенную команду:

    make all
    

    CtrlZ

    bg
    disown %1
    

    Тогда SIGHUP не будет передаваться ребенку (который больше не является ребенком).

  • Некоторые программы, в частности, демоны , будут использовать механизмы, описанные выше, автоматически: программа может установить альтернативный обработчик SIGHUP (используя sigaction(2)) или может присоединиться к новому сеансу ( setsid(2)).
  • Вы можете запустить screenили tmux, который выделяет псевдо-TTY для запуска сеанса с оболочкой, которая не получает SIGHUP, когда соединение SSH прекращается. SIGHUP не ретранслируется из сеанса SSH в сеанс screen / tmux.

Кстати, альтернативный способ справиться с ненадежными SSH-соединениями - использовать вместо этого протокол Mosh . Mosh работает по UDP, поэтому нет TCP-соединения, которое может быть сброшено.

200_success
источник
Дальнейшее чтение: Разница между nohup, disown и & .
200_success
1

Да, программа, работающая через SSH, будет зависеть от того, куда она направляется. Если соединение медленное, вывод должен быть где-то буферизован, а буферы не могут быть бесконечными, поэтому программа должна блокироваться, если они заполнены.

Обратите внимание, что вывод может не обязательно идти в терминал: подумайте о запуске чего-то вроде

ssh user@somewhere "cat file.txt" > file.txt

Это фактически скопирует файл. Чтобы это работало, скорость вывода cat должна соответствовать скорости соединения: должно быть очевидно, что потеря частей вывода из середины была бы неприемлемой.

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

Со страницы руководства:

неблокировать [on | off | numsecs]

Скажите экрану, как обращаться с пользовательскими интерфейсами (дисплеями), которые перестают принимать вывод. Это может произойти, если пользователь нажимает ^ S или соединение TCP / модема обрывается, но не происходит зависание. Если неблокирование выключено (это значение по умолчанию), экран ожидает перезагрузки дисплея, чтобы принять вывод. Если неблокирование включено, экран ожидает, пока не истечет тайм-аут (вкл. Рассматривается как 1 с). Если дисплей по-прежнему не принимает символы, экран сочтет его «заблокированным» и прекратит отправку символов на него. Если через некоторое время он перезапустит прием символов, экран разблокирует дисплей и снова отобразит обновленное содержимое окна.

Разъединение отличается от медленного соединения. Обычный SSH не может восстановиться автоматически, поэтому ваша программа получит SIGHUP. С другой стороны, экран обнаружит отключение, отсоединение и возврат к локальной буферизации, пока экран не будет снова подключен. Это не заблокирует работающую программу.

(Настройка nonblock 1в вашем .screenrcважна, если вы запускаете что-то вроде irssi, которое будет непрерывно производить вывод, но все равно должно одновременно общаться с сетью. Блокировка может привести к отключению от IRC, что крайне раздражает ...)

ilkkachu
источник