web-dev-qa-db-ja.com

バックグラウンド/デタッチされたsshセッションを強制終了するにはどうすればよいですか?

Sshトンネルと一緒にプログラムの相乗効果を使用しています

動作します。コンソールを開いて、次の2つのコマンドを入力するだけです。

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

im lazyは、アイコンを1回マウスクリックするだけで実行されるBash-Scriptを作成したためです。

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

上記のBash-Scriptも同様に機能しますが、1回のマウスクリックで相乗効果とsshトンネルも削除したいので、相乗効果とsshのPIDをファイルに保存して後で削除する必要があります。

#!/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

ただし、このスクリプトのファイルは空です。

Sshと相乗効果のPIDを取得するにはどうすればよいですか?
(私はps aux | grep ... | awk ... | sed ...組み合わせ、より簡単な方法が必要です。)

59
Skaarj

コンソール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に統合することもできますが、今は面倒です)

12
Skaarj

クイックサマリー:動作しません。

私の最初のアイデアは、バックグラウンドでプロセスを開始して、$!

のようなパターン

some_program &
some_pid=$!
wait $some_pid

あなたが必要なことをするかもしれません...それ以外の場合、sshはもはやパスフレーズを要求するためにフォアグラウンドにありません。

それでは、結局別の何かが必要になるかもしれません。 ssh -fはおそらく、シェルがそれを呼び出してもわからない新しいプロセスを生成します。理想的には、ssh自体がPIDを何らかのファイルに書き込む方法を提供します。

74
ndim

pgreppkillps | awkなどのユーザーに敬意を表して、muchより良い方法。

プロセスを見つけるために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がバックグラウンドになり、トンネルが開いたままになります。しかし、トンネルがなくなると、私は立ち往生し、それを見つけたい場合は、プロセスリストを解析し、「正しい」sshを取得しなければなりません(誤って複数のsshを起動した場合に備えて)同様)。

代わりに、複数の接続を管理する場合は、SSHのControlMaster configオプションと、制御用の-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/[email protected]:22): No such file or directory

そして、この時点で、ハンマー(killkillallpkillなど)を使用する必要なく、トンネル(および制御SSHセッション)はなくなりました。

これをユースケースに戻す...

syngergycがTCPポート12345でsyngergysと通信するトンネルを確立しています。そのために、次のようなことをします。

~/.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キーワードで処理され、Control {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を使用してssh構成ファイル内からsynergycを起動できるかどうかを確認することもできます。

57
ghoti

このスレッドに出くわして、「pidof」Linuxユーティリティについて言及したかっただけです。

$ pidof init
1
21
zrathen

Lsofを使用して、localhostのポート12345をリッスンしているプロセスのpidを表示できます。

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"
16
Atle

-fをドロップすると、バックグラウンドで実行され、evalで実行して、自分でバックグラウンドに強制できます。

その後、pidを取得できます。 evalステートメント内に&を必ず配置してください。

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

これは、synergyc(およびそれ自体をデーモン化しようとする他のほとんどのプログラム)にとって特別なケースです。 $を使用して!ただし、synergycは実行中にclone()syscallを実行し、bashが持っていると考えていたもの以外の新しいPIDを提供します。これを回避して$!を使用できるようにする場合は、synergycにフォアグラウンドに留まってからバックグラウンドにするように指示できます。

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

synergycは、自動再起動など、管理しようとしている場合はオフにすることもできる他のいくつかのことも行います。

4
deltaray

別のオプションは、pgrepを使用して最新のsshプロセスのPIDを見つけることです。

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

次の行を使用して、ローカルポートにバインドされているsshプロセスを確認できます。

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

Localhostのポート12345/TCPを使用して、プロセスのPIDを返します。したがって、sshからのすべてのpsの結果をフィルタリングする必要はありません。

確認する必要がある場合、ifポートがバインドされている場合は、次を使用します。

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

バインドされていない場合は1を、誰かがこのポートをリッスンしている場合は0を返します。

2
foo

@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が戻るとすぐに閉じられます。ソリューションには適切なエラー報告がありませんが。

1
doak