コマンドを直接呼び出すと ssh がハングするが、対話的に実行すると正常に終了する
質問
リモート マシン上でサーバーを起動し、サーバー プロセスがサイト接続しているポート番号を取得する必要があります。呼び出されると、サーバーはランダムなポートでリッスンし、ポート番号を標準エラー出力に出力します。
リモート マシンへのログオン、プロセスの起動、ポート番号の取得のプロセスを自動化したいと考えています。「」というPythonスクリプトを書きました。invokejob.py
" これはリモート マシン上に存在し、ジョブを呼び出してポート番号を返すラッパーとして機能します。これは次のようになります。
import re, subprocess
executable = ... # Name of executable
regex = ... # Regex to extract the port number from the output
p = subprocess.Popen(executable,
bufsize=1, # line buffered
stderr=subprocess.PIPE
)
s = p.stderr.readline()
port = re.match(regex).groups()[0]
print port
対話的にログインすると、次のスクリプトが機能します。
$ ssh remotehost.example.com
Last login: Thu Aug 28 17:31:18 2008 from localhost
$ ./invokejob.py
63409
$ exit
logout
Connection to remotehost.example.com closed.
(注記:ログアウトに成功した場合、ハングしませんでした)。
ただし、コマンドラインから呼び出そうとすると、ただハングします。
$ ssh remotehost.example.com invokejob.py
2番目のケースでハングする理由と、これを回避するために何ができるか知っている人はいますか?
プログラムの出力を取得する必要があるため、ssh の「-f」フラグを使用したり、標準出力をリダイレクトしたりすることはできないことに注意してください。
解決
s = p.stderr.readline()
おそらく上記の行だと思います。ssh 経由でコマンドを直接呼び出すと、完全な pty (Linux を想定) が取得されないため、読み取るための stderr がありません。
対話的にログインすると、stdin、stdout、および stderr が設定され、スクリプトが機能します。
他のヒント
@ベン・コリンズ
stderr が問題であるということについては正しいと思います。readline() 呼び出しがブロックされていることは間違いありません。
結局、あきらめて、 のpxsshモジュールを使用することにしました。 期待する SSH セッションとの対話を自動化するため。
@ミーシャM
残念ながら、ここではセミコロンのトリックは機能しません。プログラムの実行がブロックされます。
次のようにするとどうなるでしょうか:
ssh <remote host> '<your command> ;<your regexp using awk or something>'
例えば
ssh <remote host> '<your program>; ps aux | awk \'/root/ {print $2}\''
これにより、 に接続し、実行して、任意のユーザー root または説明に root が含まれるプロセスの各 PSID が出力されます。
私はこの方法を使用して、リモート マシンであらゆる種類のコマンドを実行しました。問題は、実行するコマンドを一重引用符 (') で囲み、各コマンドをセミコロン (;) で区切ることです。