Завершение сеанса 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

Вам нужно добавить exit 0 в конце.

Другие вопросы по тегам