Завершение сеанса SSH, выполняемое bash script

У меня есть script Я могу запустить локально для удаленного запуска сервера:

#!/bin/bash
ssh [email protected] <<EOF
  nohup /path/to/run.sh &
EOF
echo 'done'

После запуска nohup он зависает. Мне нужно нажать ctrl-c, чтобы выйти из script.

Я попытался добавить явный выход в конец этого документа и использовать аргумент "-t" для ssh. Ничего не работает. Как сделать этот script выход немедленно?

EDIT: клиент OSX 10.6, сервер Ubuntu.

Ответ 1

Я думаю, проблема заключается в том, что nohup не может перенаправлять вывод, когда вы входите из ssh, он перенаправляет только на nohup.out, когда он думает, что он подключен к терминалу, и я верю в stdin, что вы, с -t.

Обходной путь может заключаться в том, чтобы перенаправить вывод самостоятельно, а затем клиент ssh может отключиться - он не дожидается завершения потока. Что-то вроде:

nohup /path/to/run.sh > run.log &

(Это работало для меня в простой тесте, подключаемом к серверу Ubuntu от клиента OS X.)

Ответ 2

Проблема может заключаться в том, что...

... ssh is respecting the POSIX standard when not closing the session 
if a process is still attached to the tty.

Следовательно, решение может заключаться в отсоединении stdin команды nohup от tty:

nohup /path/to/run.sh </dev/null &

Смотрите: SSH висит на выходе при использовании nohup

Еще один подход может заключаться в использовании ssh -t -t для принудительного распределения псевдо-tty, даже если stdin не является терминалом.

man ssh | less -Ip 'multiple -t'

ssh -t -t [email protected] <<EOF
  nohup /path/to/run.sh &
EOF

Смотрите: BASH создайте подпрограмму для SSH и продолжите с потоком программы

Ответ 3

Перенаправление stdin удаленного хоста из документа здесь при вызове ssh без явной команды приводит к сообщению: Pseudo-terminal will not be allocated because stdin is not a terminal.

Чтобы избежать этого сообщения, используйте переключатель ssh -T, чтобы сообщить удаленному хосту, нет необходимости выделять псевдотерминал или явно указывать команду (например, /bin/sh) для удаленного хоста для выполнения команды, предоставленные здесь документом.

Если для ssh задана явная команда, по умолчанию используется no оболочка входа в форму псевдотерминала, i. е. при указании команды не будет обычного сеанса входа в систему (см. man ssh).

Без команды, указанной для ssh, с другой стороны, по умолчанию создается псевдо-tty для интерактивного сеанса входа на удаленном хосте.

- ssh [email protected] <<EOF
+ ssh -T [email protected] <<EOF
+ ssh [email protected] /bin/bash <<EOF

Как правило, ssh -t или даже ssh -t -t следует использовать, только если есть команды, которые ожидают, что stdin/stdout будет терминалом (например, top или vim), или если необходимо убить удаленная оболочка и ее дети, когда команда клиента ssh завершает выполнение (см. команда ssh неожиданно продолжается в другой системе после завершения ssh).

Насколько я могу судить, единственный способ объединить команду ssh, которая не выделяет команду pseudo-tty и nohup, которая записывает на nohup.out на удаленном хосте, должна позволить nohup выполнить в псевдотерминале не, созданный механизмом ssh. Это можно сделать с помощью команды script, например, и избегать сообщения tcgetattr: Inappropriate ioctl for device.

#!/bin/bash
ssh localhost /bin/sh <<EOF
  #0<&-  script -q /dev/null nohup sleep 10 1>&- &
  #0<&- script -q -c "nohup sh -c 'date; sleep 10 1>&- &'" /dev/null  # Linux
  0<&- script -q /dev/null nohup sh -c 'date; sleep 10 1>&- &'        # FreeBSD, Mac OS X
  cat nohup.out
  exit 0
EOF
echo 'done'
exit 0

Ответ 4

Вы пробовали выход 0 в конце?