タイトルの一部に触れるトピックはたくさんありますが、すべてを完全に満たすものはありません。私は遠隔サーバー上でコマンドを実行しており、長い実行時間、例えば5分程度で完全な出力を必要としています。チャンネルを使って私はタイムアウトを設定することができましたが、私がstdoutを読み返すとき、私は出力のわずかな部分しか得ませんでした。解決策は、channel.exit_status_ready()を待つことであるようでした。これは成功したコールで機能しましたが、失敗したコールは決してチャネルタイムアウトをトリガーしません。ドキュメントを見直した後、タイムアウトは読み取り操作でのみ機能し、終了ステータスを待つことは条件を満たさないためです。その試みは次のとおりです。Python Paramikoは長い実行時間で完全な出力を必要とします
channel = ssh.get_transport().open_session()
channel.settimeout(timeout)
channel.exec_command(cmd) # return on this is not reliable
while True:
try:
if channel.exit_status_ready():
if channel.recv_ready(): # so use recv instead...
output = channel.recv(1048576)
break
if channel.recv_stderr_ready(): # then check error
error = channel.recv_stderr(1048576)
break
except socket.timeout:
print("SSH channel timeout exceeded.")
break
except Exception:
traceback.print_exc()
break
かなり、そうじゃないですか?それがうまくいってほしい。
解決策の最初の試みは、time.time()を使用して開始を取得し、次にstart-time.time()> timeoutをチェックすることでした。これは簡単なようですが、私の現在のバージョンでは、time-time()を固定タイムアウトで出力し、ブレークをトリガする必要があります。スペースを節約するために、3回目の試行について言及します。ここでは、select.selectを使用して出力を待機する方法について説明し、ドキュメントにはタイムアウトがあることが記載されています。下のコードからわかるように、チャンネルタイムアウト、time.timeタイムアウト、select timeoutの3つのメソッドをすべて混合しましたが、まだプロセスを終了させる必要があります。ここで
channel = ssh.get_transport().open_session()
channel.settimeout(timeout)
channel.exec_command(cmd) # return on this is not reliable
print("{0}".format(cmd))
start = time.time()
while True:
try:
rlist, wlist, elist = select([channel], [], [],
float(timeout))
print("{0}, {1}, {2}".format(rlist, wlist, elist))
if rlist is not None and len(rlist) > 0:
if channel.exit_status_ready():
if channel.recv_ready(): # so use recv instead...
output = channel.recv(1048576)
break
elif elist is not None and len(elist) > 0:
if channel.recv_stderr_ready(): # then check error
error = channel.recv_stderr(1048576)
break
print("{0} - {1} = {2}".format(
time.time(), start, time.time() - start))
if time.time() - start > timeout:
break
except socket.timeout:
print("SSH channel timeout exceeded.")
break
except Exception:
traceback.print_exc()
break
いくつかの典型的な出力は次のとおり: - 開始=(
[<paramiko.Channel 3 (open) window=515488 -> <paramiko.Transport at 0x888414cL (cipher aes128-ctr, 128 bits) (active; 1 open channel(s))>>], [], []
1352494558.42 - 1352494554.69 = 3.73274183273
トップラインセレクトから、一番下の行は、time.time()[RLIST、wlist、ELIST]である。ここでfrankencodeですtime.time() - start)。私は1000回ループした後、繰り返しを数え、tryの最下部で壊すことで、この実行を中断しました。サンプル実行時にtimeoutが3に設定されました。これは、私たちが試行錯誤を経ることを証明しますが、明らかに、タイムアウトするべき3つの方法のどれもが機能しません。
私が根本的に誤解したことがあれば、コードを自由に取り入れることができます。私はこれがウイアーPythonicであることを望み、まだ学んでいます。
私の研究は同じ方向に走っていましたが、私は意図的に自分のコードでスレッドを使用していませんが、 "ValueError:信号はメインスレッドでのみ動作します"いくつかのモジュールがプロセスをフォークしているか、これはバグです。思考? – user1772459
ええ、私はあまりにもPythonは、メインスレッドで信号をサポートして実現しました。そのメッセージを受け取ったら、ある時点で何かがスレッドを生成すると思います。 –