web-dev-qa-db-ja.com

sshの終了時にsshによって生成されたプロセスを強制終了する

これは、ここだけでなく、スタック交換ネットワークの他のサイトでも何度も対処されている質問です(例: ssh自体に割り込みをかけたときに、リモートプロセスを強制終了するようにsshを作成する方法は? )。ただし、どの解決策もうまく機能させることができません。

Sshを介してコマンドを実行しています。 sshを終了するときはいつでも、コマンドも終了させます。このコマンドは、Ctrl + Cを押すまで無期限に実行されるktserverと呼ばれるデーモンです。

私はそれを次のように実行します:ssh -t compute-0-1 ktserver、そして実際、Ctrl-Cを押すと、プロセスが正常に終了し、sshセッションが終了します。

ただし、Ctrl-Cを押す代わりに、killコマンドを使用してsshプロセスを強制終了した場合(たとえば、SIGINTまたはSIGHUPを送信する)、ktserverプロセスはそのまま残ります。

ktserverを殺す方法とは無関係にsshを常に独立させるにはどうすればよいですか?

[〜#〜] edit [〜#〜]ktserverの代わりに、geditなどのまったく異なるものを実行すると、すべてがチャームのように機能します(つまり、geditは接続が終了すると終了します)。したがって、プロセス自体に問題がある可能性があります。たとえば、SIGHUPやSIGINTを無視しているのではないかと思いました。ただし、kill -1 ktserverまたはkill -2 ktserverを実行すると、プロセスは予期したとおりに終了します。

EDIT2:Mark Plotnickが指摘しているように、この問題は、sshチャネルで循環している通信がないという事実に関連しています。 ssh -t <Host> readを実行し、その後sshプロセスを強制終了することで確認しました。 readはまだ生きていて蹴っていました。

23
GermanK

通常、ssh接続が停止すると、シェルも停止します。すべての子プロセスが終了したときにシグナル-1(SIGHUP)を送信するようにシェルを構成できます。

Bashの場合は、組み込みコマンド shopt を使用してこのオプションを構成できます。 (shopt -s huponexit)。

Zshには setoptHUPが必要です。

13
Hennes

私は単に-t -tsshの引数として使用すると、機能します。 huponexitを元のシェルまたはリモートシェルに設定する必要はありませんでした。

私はこれを次のようにテストしました:

動作しません:

ssh user@remote sleep 100
^C

これによりsshセッションが終了しましたが、スリーププロセスがリモートホスト(ps -ef | grep sleepはそれを示しています)。

動作します:

ssh -t -t user@remote sleep 100
^C

これによりsshセッションが強制終了され、リモートスリーププロセスも強制終了されました。また、リモートプロセスに送信されるシグナルがSIGINTであることも確認しました。 Control-C。また、sshプロセスにSIGKILL(-9)を適用すると、リモートプロセスも強制終了されることを確認しました。

編集1:

そのwassleepに対してtrue ...より頑固なリモートプロセスの場合、sshは^ CをそのSIGINTとは異なる方法で処理することがわかりました。 Ctrl-C 動作しましたが、kill -INT $pidしませんでした

これが私が最終的に思いついたもので、実際のアプリケーションで機能しました(他の回答から盗みます)。

ssh -t -t -i id_rsa user@mic0 "/bin/sh -O huponexit -c 'sleep 100'"

二重引用符と単一引用符のネストされた使用に注意してください。リモートプロセスは実際に終了することによってSIGHUPに応答する必要があることに注意してください。

14
Mark Lakata

Sshが信号を伝搬しない場合、sshは何を期待していますか?

PD。(JosephRの特別):誤解から生じた問題自体は明らかにエラーです—「sshが終了したときにsshによってプロセスが強制終了されました」。 SSHは通常、プロセスを生成しません(時には生成しますが、これは別の話です)。接続の反対側を見ると、代わりにSSHDが生成します。 SSHは、リモートサーバーが持つ疑似端末の抽象化に単に依存しています。そのため、役立つことができる唯一のことは、接続されたプロセスにシグナルを発信する端末の機能です。これは、すべてのUNIXライクなシステムにとっていくぶん非常に基本的です。

1
poige

ここに投稿された解決策は私にとってはうまくいきませんでしたが、私が同様の問題の解決策を探していたときにこの質問が最初に出て以来、-t -tトリックがここで言及されました。他の人が試すことができる解決策を投稿します。

ssh -t -t -o ControlMaster=auto -o ControlPath='~/test.ssh' your_remote_ip_goes_here "your_long_running_command" &
sleep 100
ssh -o ControlPath='~/test.ssh' -O exit your_remote_ip_goes_here

このように接続が終了すると、長時間実行されていたコマンドが実行されなくなりました。

0
Greg0ry