Как убить сессию SSH, которая была запущена с опцией -f (запускается в фоновом режиме)

50

Я довольно потерян на этом. Со страницы руководства:

 -f      Requests ssh to go to background just before command execution.

После запуска SSH с -fопцией у меня работает туннель. Но после того, как я закончу его использовать, я не знаю, как дальше взаимодействовать с ним. Например, я не могу закрыть туннель SSH, когда закончу с ним.

Обычные методы, которые я знаю, не работают. Например, jobsничего не возвращает. Команда ~не распознана (и я точно не знаю, как ее использовать).

Тем не менее, pgrepговорит мне, что SSH туннель все еще работает (после того, как я закрыл терминал и т. Д.). Как мне с этим взаимодействовать? Как мне это закрыть?

MountainX
источник

Ответы:

65

Особенно хорошим решением для сценариев является использование master modeс сокетом для команд управления:

ssh -f -N -M -S <path-to-socket> -L <port>:<host>:<port> <server>

Чтобы закрыть его снова:

ssh -S <path-to-socket> -O exit <server>

Это позволяет избежать как поиска идентификаторов процессов, так и любых проблем синхронизации, которые могут быть связаны с другими подходами.

Брайан Х
источник
10
Просто, чтобы немного расширить для непосвященных, <путь-к-сокету> - это путь к файлу, который будет создан основным экземпляром клиента ssh для межпроцессного взаимодействия с другими экземплярами клиента ssh, которые хотят совместно использовать соединение главного экземпляра. Созданный файл фактически представляет собой сокет домена unix. Он может быть назван и расположен как угодно и где угодно, например /tmp/session1(хотя рекомендуется называть его с использованием % шаблонов - см. Описание ControlPath в man ssh_config)
голем
1
Кроме того , кажется , что <сервер> часть ssh -S <path-to-socket> -O exit <server>команды может быть любая строка, но она должна присутствовать. Это немного неуклюже.
Голем
1
Этот ответ и вопрос несколько устарели, но я хотел одобрить это как, вероятно, самый элегантный и «правильный» способ решения этой проблемы, который я видел. Спасибо, сэр!
Zentechinc
41

Я нашел решение здесь: http://www.g-loaded.eu/2006/11/24/auto-closing-ssh-tunnels/

Лучший способ - Туннели, которые автоматически закрываются

Как уже упоминалось ранее, вместо использования ключа -f -N мы можем просто использовать -f отдельно, но также выполнить команду на удаленном компьютере. Но какую команду следует выполнить, поскольку нам нужно только инициализировать туннель?

Это когда сон может быть самой полезной командой из всех! В этой конкретной ситуации сон имеет два преимущества:

  • ничего не делает, поэтому ресурсы не расходуются
  • пользователь может указать, как долго он будет выполняться

Как они помогают в автоматическом закрытии туннеля ssh, объяснено ниже.

Мы запускаем сессию ssh в фоновом режиме, выполняя команду sleep в течение 10 секунд на удаленной машине. Количество секунд не имеет решающего значения. В то же время мы выполняем vncviewer точно так же, как и раньше:

[me@local]$ ssh -f -L 25901:127.0.0.1:5901 me@remote.example.org sleep 10; \
          vncviewer 127.0.0.1:25901:1

В этом случае клиент ssh получает команду разорвать сеанс ssh в фоновом режиме (-f), создать туннель (-L 25901: 127.0.0.1: 5901) и выполнить команду sleep на удаленном сервере в течение 10 секунд (sleep 10).

Разница между этим методом и предыдущим (ключ -N), по сути, заключается в том, что в этом случае основная цель клиента ssh - не создать туннель, а выполнить команду сна в течение 10 секунд. Создание туннеля является своего рода побочным эффектом, вторичной целью. Если vncviewer не используется, клиент ssh завершит работу через 10 секунд, поскольку у него не останется больше заданий, одновременно уничтожая туннель.

Во время выполнения команды sleep, если другой процесс, в данном случае vncviewer, начинает использовать этот туннель и сохраняет его занятым после 10-секундного периода, тогда, даже если клиент ssh завершает свою удаленную работу (выполнение сна), он не может выход, потому что другой процесс занимает туннель. Другими словами, клиент ssh не может уничтожить туннель, потому что он должен был бы также убить vncviewer. Когда vncviewer прекращает использовать туннель, ssh-клиент тоже завершает работу, поскольку он уже достиг своей цели.

Таким образом, ssh-процессы не работают в фоновом режиме.

MountainX
источник
4
Краткое замечание / исправление: Насколько я знаю, вы должны указать, vncviewer 127.0.0.1::25091как вы используете синтаксис порта, а не синтаксис дисплея.
Кристиан Вольф
Это отличная идея, которая аккуратно обходит проблему, возникшую у меня в Windows. Последние версии Windows поставляются с ssh-клиентом, и он теоретически поддерживает опцию -S, но, похоже, у меня не работает.
Keeely
9

Чтобы уничтожить туннель, используйте ps -C sshили ps | grep sshили любой другой вариант, чтобы определить, какой процесс ssh выполняет ваш туннель. Тогда убей это.

Кроме того, вы можете искать процесс, определяя, какой из них имеет этот открытый порт:

netstat -lnpt | awk '$4 ~ /:1234$/ {sub(/\/.*/, "", $7); print $7}'

Если вы хотите уничтожить все ssh-клиенты, работающие на вашем компьютере (как ваш пользователь), pkill sshсделайте это.

Жиль "ТАК - перестань быть злым"
источник
6

Как ответили здесь другие, pkill sshубивает это.

Чтобы создать туннель, который можно вернуть, я запускаю его screenбез -fопции, а затем отсоединяю экран с помощью Ctrl-A D. Чтобы вернуть туннель, позвоните screen -r.

Хаотянь Ян
источник
Грубая сила, но эффективная
мафроз
1
Будьте осторожны, если вы подключаетесь удаленно. pkill ssh даже убьет ваше текущее соединение.
кеннют
@kennyut Еще одна причина для использования screen.
Хаотянь Ян
0

Когда я начинаю туннель с:

ssh -fN -D 8080 SOME_IP_HERE -l LOGIN_NAME_HERE
  • -f Запрашивает ssh перейти в фоновый режим непосредственно перед выполнением команды.
  • -NНе выполняйте удаленную команду. Это полезно только для переадресации портов.
  • -D Определяет локальную «динамическую» переадресацию портов уровня приложения.
  • -l Указывает пользователя для входа в систему как на удаленном компьютере.

Я могу закрыть это с:

ps -lef | grep ssh | grep "8080" | awk "{print \$2}" | xargs kill
numediaweb
источник
-1

Лучшее решение, которое я нашел, чтобы убить все туннели в одной командной строке, это

ps -lef|grep ssh|grep "\-L"|awk '{print $4}'|xargs kill

для сеансов SSH просто удалите параметр туннеля

ps -lef|grep ssh|awk '{print $4}'|xargs kill

Филипп Гачу
источник