Возобновить выполнение команды в отброшенном сеансе SSH

32

Чтение этого вопроса заставило меня задуматься. Предполагая, screenчто не используется. Если сеанс SSH на цели Linux по какой-либо причине отброшен, и вы повторно подключаетесь до того, как сервер завершит сеанс из-за истечения времени ожидания, можно ли восстановить контроль над выполняющейся командой, чтобы она не была прервана из-за прерванного сеанса ?

Джон Гарденье
источник
Какая это команда? Я предполагаю, что в целом ответ - нет.
Davr
Никакой конкретной команды, я просто спрашиваю, как общая концепция.
Джон Гарденье
1
Кто-то с полным пониманием того, как инициализируются tty-сессии, может рассказать нам, как это сделать. Похоже, что если бы вы могли воссоздать новый сеанс на том же tty и явно назначить предыдущий PPID, это было бы возможно. Я просто жду, когда придет какой-нибудь бородатый никс-гуру и поразит нас. Это мечта в любом случае.
CarpeNoctem
Что произойдет, если вы поэкспериментируете с привязанным ноутбуком и вытяните шнур Ethernet?
Пол
@ ~ drpaulbrewer - точно так же, как когда вы делаете это с настольным компьютером - соединение обрывается. Как разорвана связь, не имеет отношения к вопросу.
Джон Гарденье

Ответы:

13

Попытка подключить текущие дескрипторы файлов STD * нового терминала к старому запущенному процессу просто вызывает проблемы. Даже если вам удастся это сделать, управление заданиями терминала не будет работать должным образом. У вас останется беспорядок, если вы в конце концов выйдете из захваченной программы, и что случится с оболочкой, которая пожертвовала своими файловыми дескрипторами для передачи в только что отлаженный процесс. Ssh останется открытым, когда эта оболочка уйдет? Возможно нет. Поэтому вам нужно сначала перенаправить его куда-нибудь еще.

Возможно или нет, я бы поспорил, что более желательно просто позволить заброшенному процессу быть убитым «естественно». Если вы делаете что-то достаточно важное, чтобы оправдать попытки сделать все хакерские действия, требуемые для возобновления контроля, и у вас нестабильная связь, вы, вероятно, должны знать об этом заранее и просто использовать screen (или vnc, или что-то еще, что всплывает на вашем компьютере). управляющая лодка). :)

dannysauer
источник
Мне трудно выбрать ответ, чтобы принять его, поэтому я принимаю этот, потому что в данный момент это единственный ответ, который имеет повышенный голос.
Джон Гарденье
5

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

Я не видел каких-либо необычных последствий для этого да, но это то, что я использовал, и это сработало потрясающе. Иногда, когда мы запускаем длинные процессы на нашем сервере, он иногда отключает сессию ssh. Процесс вместе с сеансом tty продолжает работать, но мы не можем подключиться к нему. Я нашел программу ниже, чтобы вытащить процесс к новому подключенному сеансу.

https://github.com/nelhage/reptyr

Вот больше информации

https://blog.nelhage.com/2011/02/changing-ctty/

user215086
источник
5
Добро пожаловать в сбой сервера! Хотя это может теоретически ответить на вопрос, было бы предпочтительным включить здесь основные части ответа и предоставить ссылку для справки.
EEAA
спасибо, @ user215086! Удивительно, но это сработало! Я некоторое время редактировал длинный конфигурационный файл, добавил кучу пользовательских настроек и тщательно написанных комментариев, и был почти закончен, когда соединение оборвалось! «Нееееет !! ...» После того, как я закончил кричать ненормативную лексику в потолок, я установил reptyr, et voila! Я восстановил сессию ssh прямо там, где я оставил ее в редакторе, закончил несколько вещей, сохранил, сделал !! WooHoo! Рептир потрясающий.
ColdCold
4

Как правило, правильный способ справиться с этим - подготовиться к нему заранее, используя GNU, screenbash nohupили disownмеханизмы. Если вы используете tcsh, оболочка откажется от фоновых заданий, когда она выйдет ненормально.

Если вы не используете, screenно сумели сохранить процесс с помощью одного из методов disown , вы можете подделать повторное подключение к процессу с помощью gdb( source ):

[...] с некоторыми грязными взломами, невозможно повторно открыть процесс 'stdout / stderr / stdin. [...]

А затем, например, используйте gdb для присоединения к процессу, сделайте несколько вызовов close (0),
вызов close (1),
вызов close (2),
вызов open ("/ dev / pts / xx", ...)
call dup (0)
call dup (0)
отсоединить

Теперь вам нужно настроить этот процесс для вашей ситуации. Я сомневаюсь, что это помогло бы, если бы вам не удалось отречься от процесса. Если вы используете bash, прочитайте этот пост о том, как автоматически отключать bash фоновые процессы при выходе (в основном, отключать huponexit с помощью shopt ). С процессом переднего плана, вы должны использовать nohup .

шарлатан
источник
1

Возможно нет. Я не могу гарантировать, что это невозможно, но я действительно сомневаюсь в этом.

Одним из них является отсутствие уничтожения оболочки и возможных команд, выполняемых как следствие прекращения соединения ssh. Это не так сложно, вы должны быть в состоянии использовать nohup и аналогичные механизмы, как указано в другом вопросе.

Но тогда предположим, что вы запустились, ssh somehost nuhup vim /some/fileи соединение исчезло. Ты бежишьssh somehost для входа снова и видите, что ваш процесс vim все еще работает. Но как же вы снова подключаетесь к этому процессу? Интерактивные процессы forground имеют управляющий tty, и тот, который был открыт для вашего vim-процесса при запуске, с тех пор был бы закрыт. Я не уверен, есть ли какой-либо способ «открыть» его снова в вашей новой оболочке (так же, как если у вас есть несколько фоновых заданий, запущенных в одной оболочке, вы не можете перенаправить ни одну из них в другую оболочку).

Screenбыли явно написаны, чтобы иметь эту функциональность. При запуске он разветвляется на два процесса: процесс управления терминалом и клиентский процесс. Взаимодействие выполняется клиентским <-> терминальным менеджером <-> приложением, и когда вы отсоединяете или теряете соединение, клиентский процесс умирает, а терминальный менеджер продолжает жить. У Screen есть некоторая конкретная поддержка для последующего подключения к процессу управления терминалом, и я не думаю, что это возможно в общем случае.

hlovdal
источник
Спасибо. Это почти то, что я ожидал. Посмотрим, сможет ли кто-нибудь доказать, что мы неправы. ;)
Джон Гарденье
С момента написания этого ответа я узнал, что существует программа reptyr для "перепечатывания" процессов. Так что в теории выполнимо, но я все же думаю, что общий ответ, вероятно, нет.
Хловдал
1

Ретти может быть в состоянии помочь вам, но отказ от ответственности очень реальны и актуальны :)

Эван Бродер
источник
1

Если сеанс отброшен, это означает, что TTL уже истек, поэтому для вас больше нет tty (насколько я понимаю). Но если ваше сетевое соединение нарушено, сеанс SSH может не потребоваться прервать, и вы сможете возобновить соединение и продолжить. Это то, что вы спрашиваете?

мономиф
источник
Я спрашивал в целом, но меня больше всего интересует, когда проблема с сетью вызывает разрыв соединения. В целом, я бы сказал, что это выглядит не очень хорошо. Тем не менее, это было задано только из любопытства, а не по необходимости. Всегда приятно узнать ответ, прежде чем он понадобится. ;)
Джон Гарденье
разорванное соединение - не такая простая концепция, как кажется. Вы можете испытать несколько разных этапов. Например, вы должны быть в состоянии отключить сетевой кабель, подключить его через пару секунд, и ваш сеанс SSH продолжится, вам не нужно будет повторно подключаться, чтобы продолжить, даже если у вас может быть небольшая начальная задержка. Если вы столкнулись с сеансом прерванного ssh, это означает, что что-то настроено неправильно (или, скорее, не настроено должным образом для поддержки такого рода сбоев).
мономит
0

В этом вопросе была ссылка на некоторый хакерский код для кражи tty . Теоретически вы должны быть в состоянии использовать это для восстановления контроля над процессом nohup.

Камил Кисиэль
источник
1
Команда disown, упомянутая в ответах на этот вопрос, также заслуживает дальнейшего изучения. Спасибо.
Джон Гарденье