Как мне завершить фоновый / отсоединенный ssh-сеанс?
-
10-07-2019 - |
Вопрос
Я использую программу 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
.
Хотя в решении отсутствуют правильные сообщения об ошибках.