「車輪の再実装」って言葉が好き(実践はできてない)

paramikoでclientをcloseせずにCtrl+Cを実現する

paramikoとは

paramikoは、SSHの為のPythonライブラリです。 paramikoを使うことで、認証情報の管理、接続、そしてリモートでのコマンドの実行等を行うことができます。

例えば以下のようにすることで、リモートでコマンドを実行できます

from paramiko import SSHClient

client = SSHClient()
client.load_system_host_keys()
client.connect('ssh.example.com')
stdin, stdout, stderr = client.exec_command('sleep 1000') # この実行自体はすぐに返る

細かい使い方は公式ドキュメント等を参考にしてください。

paramikoを用いたリモートプロセスの実行中断方法

さて、上記様なコマンドを途中で中断、終了するためにはどうすれば良いでしょうか? まず、最も簡単なのは、clientをcloseすることです。

しかし、何らかの方法でclientをcloseしたくない場合、以下のようにしてCtrl+cを実現できます 以下の2つが要点になるのでそれぞれ見ていきます。

  • 疑似端末の取得
  • Ctrl+C(相当の値\x03)の送信

疑似端末の取得

疑似端末を取得(割当)することで、通常ターミナルを使って作業するときのようにプロセスを振る舞わせる事ができます。 こうすることで、Ctrl+C(相当の値)を受け付けるようになります。

具体的には exec_command 時に get_pty=True を付与することでできます。

stdin, stdout, stderr = client.exec_command('sleep 1000', get_pty=True)

Ctrl+C(相当の値\x03)の送信

以下のようにすれば可能です。

print('\x03', file=stdin, end='')

より低レベルなクラスを用いた場合

上記の例では SSHClient クラスを用いた例を示しましたが、 その内部で使われているChannel クラスを用いた場合も要点は同じです。

ただし、具体的には以下のような手順を踏む事になります。

chan.get_pty() # オプションとしてではなく、独立したコマンドとしてptyを取得
chan.exec_command(...)
中略
chan.send('\x03') # ファイルオブジェクトに対してではなく、直接データ送信