Процесс убийства, порожденный ssh, когда ssh умирает

23

Это вопрос, который был рассмотрен несколько раз, не только здесь, но и на других сайтах сети обмена стека (например, Как заставить ssh убить удаленный процесс, когда я прерываю сам ssh? ). Однако я не могу заставить любое решение работать на меня.

Я запускаю команду через SSH. Всякий раз, когда я выхожу из ssh, я хочу, чтобы команда тоже умерла. Эта команда - демон ktserver, который выполняется бесконечно, пока вы не нажмете Ctrl-C.

Я запускаю его следующим образом: ssh -t compute-0-1 ktserverи действительно, когда я нажимаю Ctrl-C, процесс завершается изящно, и сессия ssh заканчивается.

Однако если вместо нажатия Ctrl-C я уничтожу процесс ssh с помощью killкоманды (например, отправив SIGINT или SIGHUP), ktserverпроцесс останется активным.

Как я могу заставить ktserverвсегда умереть независимо от того, как sshего убить?

РЕДАКТИРОВАТЬ : Если вместо того, чтобы ktserverзапустить что-то совершенно другое, например gedit, все работает как шарм (т.е. gedit умирает, когда умирает соединение). Поэтому, возможно, что-то не так с самим процессом. Например, я подумал, что это может быть игнорирование SIGHUP или SIGINT. Однако когда я запускаю kill -1 ktserverили kill -2 ktserver, процесс умирает, как и ожидалось.

РЕДАКТИРОВАТЬ 2 : Как отмечает Марк Плотник, проблема связана с тем, что по каналу SSH не существует связи. Я подтвердил, запустив ssh -t <host> readи убив процесс ssh впоследствии. readбыл еще жив и здоров.

GermanK
источник
Ты пробовал kill -9 ktserver?
@HermanTorjussen Конечно, это работает. Проблема заключается в том, что эта команда запускается из другого процесса, и я не могу контролировать все многочисленные возможности, которые могут привести к смерти моего процесса, и, следовательно, сеанс ssh с ним. Поэтому мне нужен надежный способ быть уверенным, что всякий раз, когда мой процесс и, следовательно, sshdies, ktserver умирает вместе с ними.
GermanK
Мой опыт работы с Linux заключается в том, что если удаленная команда не выполняет никаких операций ввода-вывода для мертвого TCP-соединения, она продолжит работать. У меня были ssh example.com dd ...задания, выполненные до конца, даже через несколько часов после sshпрекращения соединения из-за проблем с сетью. Если вы можете изменить ktserverвариант, чтобы выводить что-то один раз, это может быть обходной путь.
Марк Плотник
@MarkPlotnick Действительно, я попытался запустить readна удаленном компьютере, и после разрыва соединения ssh, readне умер. К сожалению, я не могу изменить ktserver для вывода ничего. Тогда нет решения?
GermanK
2
Я предполагаю, что когда ssh умирает, ваша оболочка также умирает. Вы можете настроить свою оболочку так, чтобы она отправляла сигнал -1 (SIGHUP), когда он завершается. ( shopt -s huponexit). Можете ли вы проверить, работает ли это для вас?
Хеннес

Ответы:

13

Обычно, когда соединение ssh умирает, оболочка также умирает. Вы можете настроить свою оболочку так, чтобы она отправляла сигнал -1 (SIGHUP), когда она завершается со всеми дочерними элементами.

Для bash вы можете настроить эту опцию с помощью встроенной команды shopt . ( shopt -s huponexit).

Для зш ты хочешь .setoptHUP

Hennes
источник
Я думал, что это был ответ на мою текущую проблему, но это, похоже, не работает. Я использую: ssh $ host "scp LargeFile.dat $ OtherHost: / tmp" & pid = $! и затем пытается остановить эту передачу с помощью: shopt -s huponexit; kill $ pid, но scp не останавливается, когда я уничтожаю запущенный ssh. Есть предположения?
Дэвид Дория
Можете ли вы проверить параметры оболочки, установленные перед запуском команды scp? Или путем запуска оболочки, установки shopt и запуска scp?
Хеннес
2
Это работает для меня, но я должен был сначала убедиться, что я использовал ssh -t -t(обратите внимание -tдважды!) , Что вызывает tty-распределение, а не просто pty.
Николас Ву
13

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

Я проверил это следующим образом:

Не работает:

ssh user@remote sleep 100
^C

Это убило сессию ssh, но я вижу, что спящий процесс все еще выполняется на удаленном хосте ( ps -ef | grep sleepпоказывает это).

Работает:

ssh -t -t user@remote sleep 100
^C

Это убивает сеанс ssh, и удаленный спящий процесс также был убит. Я также проверил, что сигнал, который отправляется удаленному процессу, это SIGINTесли вы используете Control- C. Я также проверил, что SIGKILL (-9), примененный к sshпроцессу, также уничтожит удаленный процесс.

РЕДАКТИРОВАТЬ 1:

Это было верно для sleep... для более упорных удаленных процессов, я обнаружил, что sshобрабатывает ^ C иначе, чем SIGINT. Ctrl- Cработал, но не kill -INT $pidсделал

Вот что я наконец-то придумал, что сработало для моего реального приложения (кража из других ответов).

ssh -t -t -i id_rsa user@mic0 "/bin/sh -O huponexit -c 'sleep 100'"

Обратите внимание на вложенное использование двойных кавычек и одинарных кавычек. Обратите внимание, что ваш удаленный процесс ДОЛЖЕН реагировать на SIGHUP, фактически завершив работу!

Марк Лаката
источник
Это сработало лучше для меня, но, к вашему сведению, это также вызвало прохождение через контрольные символы терминала, что может привести к забавным выводам. Таким образом, в моем случае простым обходным путем было обернуть вызываемые команды и передать их вывод cat. Например,ssh -ttq user@host '{ cmd; cmd; } | cat'
Дрой
Ctrl-CНЕ всегда эквивалентен kill -INT $pid, см. мой ответ на unix.stackexchange.com/questions/377191/… и другой на stackoverflow.com/questions/8398845/… для подробностей кровавый ;-)
thecarpy
@thecarpy - ваш первый ответ говорит, что Ctrl-C сродни SIGINT , а другой ответ говорит, что ^Cотправляет SIGINT . Так в чем же разница, если они не эквивалентны?
Марк Лаката
1

Если ssh не распространяет сигналы, которые он получает, что вы ожидаете от него?

UPD. (специально для JosephR): это, очевидно, сама ошибка в вопросе, которая вытекает из недоразумения - «Процесс убийства, порожденный ssh, когда ssh умирает». SSH обычно не порождает процессы (иногда это происходит, но это другая история), вместо этого SSHD, когда мы смотрим на другую сторону соединения. SSH просто полагается на псевдо-терминальную абстракцию удаленного сервера. Вот почему единственное, что может помочь, - это способность терминала излучать сигналы на присоединенные процессы. Это несколько основополагающее значение для каждой UNIX-подобной системы.

poige
источник
1
Это не дает ответа на вопрос. Чтобы критиковать или запросить разъяснения у автора, оставьте комментарий под своим постом.
Anthon
@ Антон, это объяснение. Но никто не утверждает, что это должен быть единственный правильный ответ. Спасибо за ваш комментарий ниже.
Пой
1
@poige Возможно, уточните объяснение, чтобы оно могло быть полезным для ОП и других.
Джозеф Р.
@JosephR. Хорошо, только для тебя.
Пой
1
Если я скажу «Процесс Kill, порожденный sshd, когда соединение ssh потеряно», будет ли это звучать лучше для вас? Я не думаю, что перефразировка решает мою проблему в любом случае.
GermanK
0

Решение, опубликованное здесь, не работает для меня, но так как этот вопрос возник первым, когда я искал решение для аналогичной проблемы, а также -t -tздесь был упомянут трюк, я опубликую решение, которое помогло мне попробовать другим.

ssh -t -t -o ControlMaster=auto -o ControlPath='~/test.ssh' your_remote_ip_goes_here "your_long_running_command" &
sleep 100
ssh -o ControlPath='~/test.ssh' -O exit your_remote_ip_goes_here

Моя долго работающая команда больше не выполнялась, когда соединение было разорвано следующим образом.

Greg0ry
источник