Завершение сеанса SSH, выполняемого скриптом bash
У меня есть скрипт, который я могу запустить локально для удаленного запуска сервера:
#!/bin/bash
ssh user@host.com <<EOF
nohup /path/to/run.sh &
EOF
echo 'done'
После запуска nohup зависает. Я должен нажать Ctrl-C, чтобы выйти из сценария.
Я попытался добавить явный выход в конце документа здесь и использовать аргумент "-t" для ssh. Ни то, ни другое не работает. Как сделать так, чтобы этот скрипт немедленно завершился?
РЕДАКТИРОВАТЬ: клиент OSX 10.6, сервер Ubuntu.
4 ответа
Я думаю, проблема в том, что nohup не может перенаправить вывод, когда вы входите из ssh, он только перенаправляет в nohup.out, когда думает, что он подключен к терминалу, и если у вас есть переопределение stdin, это будет предотвращено, даже если -t
,
Обходным путем может быть перенаправление вывода самостоятельно, тогда клиент ssh может отключиться - он не ожидает закрытия потока. Что-то вроде:
nohup /path/to/run.sh > run.log &
(Это сработало для меня в простом тесте подключения к серверу Ubuntu из OS X-клиента.)
Проблема может быть в том, что...
... 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 user@host.com <<EOF
nohup /path/to/run.sh &
EOF
Смотрите: BASH порождает подоболочку для SSH и продолжайте выполнение программы
Перенаправление stdin удаленного хоста из документа здесь при вызове ssh
без явной команды приводит к сообщению: Pseudo-terminal will not be allocated because stdin is not a terminal.
Чтобы избежать этого сообщения либо используйте ssh
"s -T
переключатель, чтобы сказать удаленному хосту, что нет необходимости выделять псевдо-терминал или явно указывать команду (например, /bin/sh
) для удаленного хоста, чтобы выполнить команды, предоставленные здесь документа.
Если явная команда дается ssh
по умолчанию не указывается оболочка входа в виде псевдотерминала, т. е. не будет нормального сеанса входа при указании команды (см. man ssh
).
Без команды, указанной для ssh
с другой стороны, по умолчанию создается псевдотерминал для сеанса интерактивной регистрации на удаленном хосте.
- ssh user@host.com <<EOF
+ ssh -T user@host.com <<EOF
+ ssh user@host.com /bin/bash <<EOF
Как правило, ssh -t
или даже ssh -t -t
следует использовать, только если есть команды, которые ожидают, что stdin / stdout будет терминалом (например, top
или же vim
) или если необходимо убить удаленную оболочку и ее дочерние элементы, когда ssh
клиентская команда завершает выполнение (см.: команда ssh неожиданно продолжается в другой системе после завершения работы ssh).
Насколько я могу судить, единственный способ объединить ssh
команда, которая не выделяет псевдо-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