Удаленная команда PuTTY, содержащая цикл while

Удаленная команда PuTTY, содержащая цикл while

Я пытаюсь автоматизировать несколько распространенных задач, которые я выполняю по SSH на удаленном сервере. Для этого я использую PuTTY и его опцию "удаленная команда" (Подключение > SSH) в нескольких сохраненных сеансах. Моя удаленная команда выглядит примерно так:

~/scripts/test; $SHELL -l

Выполняемый скрипт отличается для каждого сохраненного сеанса и выполняет разные задачи. $SHELL -lсохраняет сеанс PuTTY активным после завершения выполнения скрипта.

Все это прекрасно работает для большинства скриптов, которые я запускаю. Однако у меня есть один, который использует цикл while для выполнения серии команд, пока он не будет завершен с помощью Ctrl+C. Скрипт запускается нормально, но оболочка PuTTY не остается активной после его завершения. $SHELL -lне похоже, что он выполняется.

Пример сценария с таким поведением выглядит следующим образом:

while true; do
echo "."
sleep 2
done

Следующий код отлично работает при ручном выполнении, я вижу ожидаемый вывод от второй команды:

~/scripts/test; echo "done"

Однако вторая команда PuTTY "remote command" не выполняется. Действительно, если я изменю удаленную команду, включив echo, она не отобразится.

~/scripts/test; echo "done"; $SHELL -l

Итак, я думаю, мой вопрос: почему вторая команда в списке не выполняется удаленной командой, хотя выполняется вручную? И, что еще важнее, что я могу с этим сделать?

Если это актуально, я использую PuTTY на Ubuntu 14.04.

решение1

Когда вы запускаете puttyили ssh— я не думаю, что в этом контексте есть какая-либо разница — команду для запуска на удаленной системе, удаленный сервер SSH запускает команду как команду оболочки:

/bin/bash -c '~/scripts/test; $SHELL -l'

Итак, у вас есть bashэкземпляр на удаленной системе, выполняющий этот конвейер. У вас также есть другой bashэкземпляр, запущенный первым экземпляром, выполняющий этот "тестовый" скрипт.

При нажатии Control-C puttyсимвол отправляется на удаленную систему, где он интерпретируется вашим TTY как символ прерывания. Это приводит к отправке SIGINT (сигнала прерывания) процессам, которые подключены к TTY. Это прерывает оба этих процесса оболочки, заставляя их оба завершиться. Вы хотите, чтобы родительский экземпляр оболочки игнорировал SIGINT.

Команда bash для игнорирования SIGINT:

trap "" INT

Таким образом, чтобы отключить SIGINT для вашего конвейера, вам нужно изменить исходную команду на:

trap '' INT; ~/scripts/test; $SHELL -l

Но это отключает SIGINT также и для дочерних процессов, что сделает "тестовый" скрипт невосприимчивым к Ctrl-C. Поэтому вам нужно снова включить SIGINT для тестового скрипта. Команда для этого:

trap INT

Эту строку можно добавить в сам тестовый скрипт или в конвейер:

trap '' INT; ( trap INT; ~/scripts/test ); $SHELL -l

Теперь, когда вы нажмете Ctrl-C, вы должны прервать процесс «теста», но не родительский процесс, который выполняет командный конвейер.

Вы можете проверить это без использования putty или ssh. Просто запустите эти команды и попробуйте нажать Ctrl-C во время выполнения "sleep":

bash -c 'sleep 15; echo foo'                  # Ctrl-C kills sleep; doesn't print "foo"
bash -c 'trap "" INT ; sleep 15; echo foo'    # Ctrl-C has no effect
bash -c 'trap "" INT; ( trap INT; sleep 15 ); echo foo'    # Kills sleep, prints "foo"

решение2

ctrl+c для удаленной команды putty фактически прерывает сеанс ssh, поэтому следует ожидать, что он не выполнит оставшиеся удаленные команды. Если ваша цель — просто сохранить сеанс активным, то вашего бесконечного цикла должно быть достаточно.

Связанный контент