объяснение
Это не о wait
. Я думаю, что это то, что происходит:
Вы можете использовать <<
, поэтому stdin
из ssh
перенаправляется в какой - то дескриптор, через который весь документ здесь течет.
Этот другой ответ объясняет, как ssh
можно захватить Ctrl+, Cкогда -t
используется. Вот что важно:
На стороне клиента
ssh
будет пытаться установитьtty
используемыйstdin
режим в «сырой» режим […]. Установка сырого режима означает, что символы, которые обычно посылают сигналы (например, Ctrl+ C), вместо этого просто вставляются во входной поток.
В вашем случае это не то же самое, что stdin
ваша локальная оболочка. tty
используемая вашей локальной оболочкой остается без изменений, она никогда не устанавливается в «сырой» режим.
Поэтому, когда вы нажимаете Ctrl+, Cон действует локально и завершается ssh
. В этот момент удаленная сторона получает SIGHUP
. Твои trap
работы и убийства java
. Я думаю, что здесь есть подводный камень: a trap
выполняет некоторый код в ответ на данный сигнал, но он не препятствует тому, чтобы сигнал имел нормальный эффект. Поэтому мне кажется, что вы java
были бы убиты даже без, trap
потому что это работа оболочки, которая завершается в ответ на SIGHUP
.
Завершенная оболочка перестает читать и интерпретировать свою stdin
. Вот почему все, что следует wait
, отбрасывается.
Решение
commands() { cat <<-'COMMANDS' cleanup() { # cleanup code here echo "Done. Logging out" sleep 2 logout } echo "Preparing execution" java -jar execute.jar & executePID=$! echo "Ready." echo "CTRL+C to clean and close" trap "kill $executePID; cleanup" INT HUP wait $executePID cleanup COMMANDS } stty raw -echo; cat <(commands) - | ssh -t $USER@remote.far; stty -raw echo
Последняя строка - фактическая команда. Сначала мы готовимся, tty
чтобы Ctrl+ Cне мог действовать локально. Затем мы объединяем команды и стандартный ввод, передаем его в удаленную оболочку. Я не могу сделать это с этим документом напрямую, command
функция является обходным путем (было бы проще использовать обычный файл, но вы сказали, что не можете использовать более одного). После ssh
и cat
выхода мы устанавливаем tty
его в нормальное состояние.
Наличие псевдотерминала необходимо, поэтому убедитесь, что ssh -t
работает (используйте -tt
при необходимости).
Удаленная оболочка должна считывать (буферизовать) все команды commands
, только тогда она может получить Ctrl+ Cпри нажатии. Я думаю, это означает, что вы не можете иметь слишком много кода после wait
. Кроме того, все, что вы хотите сделать после, SIGINT
должно быть запущено изнутри trap
. По этим причинам я использовал одну cleanup
функцию, которая делает все это.
Код не является надежным. Нажмите Ctrl+ Cслишком рано или несколько раз, и вы окажетесь в удаленной оболочке или с несколько «сломанным» локальным tty
. В этом последнем случае используйте команду reset
для сброса tty
.
Вы должны нажать клавишу (например Enter) после того, как увидите «Соединение с… закрыто». Причина в том, что cat
он не заметит, что канал сломан (из-за ssh
того, что его больше нет), пока не попытается что-то записать в него.
альтернатива
Если по какой-либо причине вышеуказанное решение не работает для вас, воспользуйтесь этой более простой альтернативой. Здесь документ точно так, как раньше. В этом случае мы не связываемся с tty
, Ctrl+ Cзавершает локальный, ssh
как это происходит с вашим исходным кодом. Разница (по отношению к вашему коду) в том, что trap
делает уборку. Я думаю, что этого будет достаточно, чтобы поймать SIGHUP
только.
ssh -t $USER@remote.far <<-'COMMANDS' cleanup() { # cleanup code here echo "Done. Logging out" sleep 2 logout } echo "Preparing execution" java -jar execute.jar & executePID=$! echo "Ready." echo "CTRL+C to clean and close" trap "kill $executePID; cleanup" INT HUP wait $executePID cleanup COMMANDS
Примечание: при trap
срабатывании cleanup
эхо-сообщения появляется сообщение, но вы не увидите его, потому что ваш локальный ssh
уже отключен. Вы увидите сообщение, только если java
выход без trap
. Тем не менее ваш код очистки ( # cleanup code here
) должен быть выполнен.