Как мне завершить фоновый / отсоединенный ssh-сеанс?

StackOverflow https://stackoverflow.com/questions/1821968

Вопрос

Я использую программу synergy вместе с ssh-туннелем

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

ssh -f -N -L localhost:12345:otherHost:12345 otherUser@OtherHost
synergyc localhost

поскольку я ленив, я создал Bash-скрипт, который запускается одним щелчком мыши по значку:

#!/bin/bash
ssh -f -N -L localhost:12345:otherHost:12345 otherUser@OtherHost
synergyc localhost

приведенный выше Bash-скрипт также работает, но теперь я также хочу отключить synergy и ssh-туннель одним щелчком мыши, поэтому мне нужно сохранить PID synergy и ssh в файл, чтобы отключить их позже:

#!/bin/bash

mkdir -p /tmp/synergyPIDs || exit 1
rm -f /tmp/synergyPIDs/ssh || exit 1
rm -f /tmp/synergyPIDs/synergy || exit 1

[ ! -e /tmp/synergyPIDs/ssh ] || exit 1
[ ! -e /tmp/synergyPIDs/synergy ] || exit 1

ssh -f -N -L localhost:12345:otherHost:12345 otherUser@OtherHost
echo $! > /tmp/synergyPIDs/ssh
synergyc localhost
echo $! > /tmp/synergyPIDs/synergy

Но файлы этого скрипта пусты.

Как мне получить PID-коды ssh и synergy?
(Я стараюсь избегать ps aux | grep ... | awk ... | sed ... комбинации, должен быть более простой способ.)

Это было полезно?

Решение 5

ну, я не хочу добавлять & amp; в конце команды, поскольку соединение прекратится, если консоль wintow закрыта ... так что я получил ps-grep-awk-sed-combo

ssh -f -N -L localhost:12345:otherHost:12345   otherUser@otherHost
echo `ps aux | grep -F 'ssh -f -N -L localhost' | grep -v -F 'grep' | awk '{ print $2 }'` > /tmp/synergyPIDs/ssh
synergyc localhost
echo `ps aux | grep -F 'synergyc localhost' | grep -v -F 'grep' | awk '{ print $2 }'` > /tmp/synergyPIDs/synergy

(вы могли бы интегрировать grep в awk, но сейчас мне лень)

Другие советы

Краткое резюме. Не будет работать.

Моя первая идея заключается в том, что вам нужно запускать процессы в фоновом режиме, чтобы получить их PID с $! .

Шаблон как

some_program &
some_pid=$!
wait $some_pid

может делать то, что вам нужно ... за исключением того, что тогда ssh больше не будет на переднем плане запрашивать пароли.

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

При всем должном уважении к пользователям pgrep, pkill, ps | awk, и т.д., существует многое лучший способ.

Учтите, что если вы полагаетесь на ps -aux | grep ... чтобы найти процесс, вы рискуете столкнуться с ним.У вас может быть вариант использования, когда это маловероятно, но, как правило, это не тот путь, которым нужно идти.

SSH предоставляет механизм для управления фоновыми процессами.Но, как и многие другие SSH-функции, это "продвинутая" функция, и многие люди (судя по другим ответам здесь) не знают о ее существовании.

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

$ ssh -fNT -L8888:proxyhost:8888 -R22222:localhost:22 officefirewall
$ ssh -fNT -L4431:www1:443 -L4432:www2:443 colocatedserver

Это приводит к тому, что ssh переходит в фоновый режим, оставляя туннели открытыми.Но если туннель исчезнет, я застряну, и если я хочу найти его, я должен проанализировать свой список процессов и home, у меня есть "правильный" ssh (на случай, если я случайно запустил несколько похожих).

Вместо этого, если я хочу управлять несколькими подключениями, я использую SSH ControlMaster параметр конфигурации вместе с -O опция командной строки для управления.Например, со следующим в моем ~/.ssh/config файл,

host officefirewall colocatedserver
    ControlMaster auto
    ControlPath ~/.ssh/cm_sockets/%r@%h:%p

приведенные выше ssh-команды при запуске оставят след в ~/.ssh/cm_sockets/ который затем может обеспечить доступ для управления, например:

$ ssh -O check officefirewall
Master running (pid=23980)
$ ssh -O exit officefirewall
Exit request sent.
$ ssh -O check officefirewall
Control socket connect(/home/ghoti/.ssh/cm_socket/ghoti@192.0.2.5:22): No such file or directory

И в этот момент туннель (и управляющий SSH-сеансом) исчезает, без необходимости использовать молоток (kill, killall, pkill, и т.д.).

Возвращаем это к вашему варианту использования...

Вы прокладываете туннель, по которому хотите пройти syngergyc поговорить с syngergys на TCP-порту 12345.Для этого я бы сделал что-то вроде следующего.

Добавьте запись в свой ~/.ssh/config файл:

Host otherHosttunnel
    HostName otherHost
    User otherUser
    LocalForward 12345 otherHost:12345
    RequestTTY no
    ExitOnForwardFailure yes
    ControlMaster auto
    ControlPath ~/.ssh/cm_sockets/%r@%h:%p

Обратите внимание, что командная строка -L опция обрабатывается с помощью LocalForward ключевое слово и управляющие строки {Master, Path} включены, чтобы убедиться, что у вас есть контроль после создания туннеля.

Затем вы могли бы изменить свой скрипт bash примерно на это:

#!/bin/bash

if ! ssh -f -N otherHosttunnel; then
    echo "ERROR: couldn't start tunnel." >&2
    exit 1
else
    synergyc localhost
    ssh -O exit otherHosttunnel
fi

Тот Самый -f опция создает фон туннеля, оставляя сокет на вашем ControlPath, чтобы закрыть туннель позже.Если ssh выходит из строя (что может быть связано с сетевой ошибкой или ExitOnForwardFailure), нет необходимости выходить из туннеля, но если он не провалился (else), запускается synergyc, а затем туннель закрывается после его выхода.

Возможно, вы также захотите посмотреть, используется ли опция SSH LocalCommand может быть использован для запуска synergyc прямо из вашего конфигурационного файла ssh.

только что наткнулся на эту ветку и хотел упомянуть " pidof " Утилита Linux:

$ pidof init
1

Вы можете использовать lsof, чтобы показать pid процесса, прослушивающего порт 12345 на localhost:

lsof -t -i @localhost:12345 -sTCP:listen

Примеры:

PID=$(lsof -t -i @localhost:12345 -sTCP:listen)
lsof -t -i @localhost:12345 -sTCP:listen >/dev/null && echo "Port in use"

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

Затем вы можете получить pid . Не забудьте поместить & amp; в оператор eval .

eval "ssh -N -L localhost:12345:otherHost:12345 otherUser@OtherHost & " 
tunnelpid=$!

Это скорее особый случай для синергии (и большинства других программ, которые пытаются демонизировать себя). Используя $! будет работать, за исключением того, что synergyc выполняет системный вызов clone () во время выполнения, который даст ему новый PID, отличный от того, который, по мнению bash, он имеет. Если вы хотите обойти это, чтобы использовать $ !, тогда вы можете сказать synergyc остаться на переднем плане, а затем задний фон.

synergyc -f -n mydesktop remoteip &
synergypid=$!

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

Другой вариант - использовать pgrep, чтобы найти PID новейшего процесса ssh

ssh -fNTL 8073:localhost:873 otherUser@OtherHost
tunnelPID=$(pgrep -n -x ssh)
synergyc localhost
kill -HUP $tunnelPID

Вы можете посмотреть процесс ssh, связанный с вашим локальным портом, используя эту строку:

netstat -tpln | grep 127\.0\.0\.1:12345 | awk '{print $7}' | sed 's#/.*##'

Возвращает PID процесса, используя порт 12345 / TCP на локальном хосте. Поэтому вам не нужно фильтровать все результаты ssh из ps .

Если вам просто нужно проверить, если этот порт связан, используйте:

netstat -tln | grep 127\.0\.0\.1:12345 >/dev/null 2>&1

Возвращает 1 , если ничто не связано, или 0 , если кто-то прослушивает этот порт.

На основе очень хорошего ответа @ghoti приведем более простой сценарий (для тестирования), использующий управляющие сокеты SSH без необходимости дополнительной настройки:

#!/bin/bash
if ssh -fN -MS /tmp/mysocket -L localhost:12345:otherHost:12345 otherUser@otherHost; then
    synergyc localhost
    ssh -S /tmp/mysocket -O exit otherHost
fi

synergyc будет запущен только в том случае, если туннель был успешно установлен, который сам закроется, как только вернется synergyc . Хотя в решении отсутствуют правильные сообщения об ошибках.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top