Зависит ли программа, запускаемая из сеанса ssh, от соединения?

Проблема не в tr , проблема заключается в том, как вы выводите расширение переменной:

echo $PAGE_LINKS

Цитируйте переменную раскрытие:

echo "$PAGE_LINKS"

в противном случае расширение будет проходить через разделение слов в соответствии со значением IFS (пробел, табуляция, новая строка по умолчанию) и раскрытие имени пути ( * , ? , []).

В вашем случае происходит разделение слов, и каждый элемент, разделенный новой строкой, берется индивидуально и, наконец, отображается как объекты, разделенные пробелом. Использование кавычек предотвратит разделение слов (и расширение имени пути), поэтому все расширение будет считаться единым целым.

29
13.04.2017, 15:36
3 ответа

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

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

27
27.01.2020, 19:38

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

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

Из часто задаваемых вопросов программиста Unix , пункт 1.15:

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

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

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

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

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

 Сигнал Значение Действие Комментарий 
 ---------------- -------------------------------------------------- ---- 
SIGHUP 1 Срок Обнаружено зависание на управляющем терминале 
или смерть управляющего процесса 
 

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

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

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

     make all 
     

    Ctrl Z

     bg 
    disown% 1 {{ 1}} 

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

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

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

9
27.01.2020, 19:38

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

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

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

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

Screen изменит ситуацию тем, что будет действовать как терминал и сохранит то, что должно быть показано "в окне терминала" (плюс прокрутка назад). Ему не нужно запоминать все, что выводит ваша программа, только те части, которые будут соответствовать "окну" и прокрутке назад. По умолчанию, screen будет ждать медленного соединения (блокируя программу), но его можно настроить на обнаружение застрявшего соединения, установив "nonblock on".

Из man-страницы:

nonblock [on|off|numsecs]

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

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

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

.
1
27.01.2020, 19:38

Теги

Похожие вопросы