これは、ここだけでなく、スタック交換ネットワークの他のサイトでも何度も対処されている質問です(例: 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
はまだ生きていて蹴っていました。
私は単に-t -t
をssh
の引数として使用すると、機能します。 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)を適用すると、リモートプロセスも強制終了されることを確認しました。
そのwasはsleep
に対して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に応答する必要があることに注意してください。
Sshが信号を伝搬しない場合、sshは何を期待していますか?
PD。(JosephRの特別):誤解から生じた問題自体は明らかにエラーです—「sshが終了したときにsshによってプロセスが強制終了されました」。 SSHは通常、プロセスを生成しません(時には生成しますが、これは別の話です)。接続の反対側を見ると、代わりにSSHDが生成します。 SSHは、リモートサーバーが持つ疑似端末の抽象化に単に依存しています。そのため、役立つことができる唯一のことは、接続されたプロセスにシグナルを発信する端末の機能です。これは、すべてのUNIXライクなシステムにとっていくぶん非常に基本的です。
ここに投稿された解決策は私にとってはうまくいきませんでしたが、私が同様の問題の解決策を探していたときにこの質問が最初に出て以来、-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
このように接続が終了すると、長時間実行されていたコマンドが実行されなくなりました。