2016-08-12 12 views
0

私はリモートで配備された組み込みLinuxデバイス上でpythonスクリプトを取得してscpコマンドを実行しようとしています。コマンドの実行は簡単ですが、ターゲットサーバが 'known_hosts'ファイルにリストされていない場合、scpは対話が必要な警告をスローします。私はこれを数日間止め、2つの問題を解決することはできません。Python - サブプロセスで入力プロンプトを処理する

まず、サブプロセスからの応答をノンブロッキングで正しく読み取ることができません。次のコードでは、(信頼できるホストファイルの警告が生成されたと仮定して)stderrから読み取ることができることがわかっている場合でも、必ず[(]、[]、[])を返します。

cmdString = 'scp [email protected]:file localFile -i ~/.ssh/id_rsa' 

process = subprocess.Popen(shlex.split(cmdString), shell=False, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 

while(process.poll() is None): 
    readable, writable, exceptional = select.select([process.stdout], [], [process.stderr], 1) 

    if not (readable or writable or exceptional): 
    # Always hits this condition, although adding an "os.read(...)" here 
    # will return the error prompt from process.stderr. 
    print "timeout condition" 
    else: 
    # Never makes it here 
    for e in exceptional: 
     stderr = os.read(process.stderr.fileno(), 256) 
     print stderr 
    for r in readable: 
     stdout = os.read(process.stdout.fileno(), 256) 
     print stdout 

第2に、入力パイプを介して入力を入力することによって、警告を超えてサブプロセスを進めることができません。次のコードはprocess.stderrから警告コードを読み込みますが、端末で{enter}を押すまでハングします。私は "n"、 "n \ n"、 "\ n"を送信しようとしましたが、サブプロセスが実行を継続することはありませんでした。

cmdString = 'scp [email protected]:file localFile -i ~/.ssh/id_rsa' 

process = subprocess.Popen(shlex.split(cmdString), shell=False, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 

# Correctly grabs warning and displays it 
stderr = os.read(process.stderr.fileno(), 256) 
print stderr 

# Just in case there was some weird race condition or something 
time.sleep(0.5) 

# Doesn't ever seem to do anything 
process.stdin.write('\n') 

最後に重要ですか?私は元々サブプロセスとPIPESの調査を始めました。なぜなら、私はスレッドをブロックした "os.system(cmdString)"を使ってscpを実行していたので、私はこの問題に対処しなければなりませんでした。サブプロセスを使用しているので、コマンドを実行して成功または失敗させるのは悪いですか?失敗したサブプロセスが最終的に消滅するか、最終的に数十から数百の隠されたscpが実行されているところでユーザーの入力を待つことになりますか?

ありがとうございます!

答えて

0

この場合、scpはstdin/stdout/stderrを使用して通信するのではなく、端末から直接通信する可能性があります。

stackoverflowでscp inputのようなものを検索することで、同様の疑問やそれに対処する方法がたくさんあります。

開始されたサブプロセスは、親プロセスが出力(stdout/stderr)をパイプしてサブプロセスが何かを書き込もうとすると消滅します。この場合、端末を使用しているため、scpはおそらく動作し続けます。しかし、これらのプロセスは本当に隠されていません。 psのようなツールで簡単に確認できます(killまたはkillall)。

EDIT:あなたはさまざまなライブラリに問題が述べたように、おそらく次のようなアプローチが役立ちます。

import os, pty 

pid, fd = pty.fork() 
if pid == 0: 
    os.execvp('scp', ['scp', '[email protected]:file', ... ]) 
else: 
    while True: 
    s = os.read(fd, 1024) 
    print repr(s) 
    os.write(fd, 'something\n') 
+0

おかげで、それは標準の標準入力/標準出力/標準エラー出力を使用していないという洞察をたくさん助けました。 "pexpect"はscpを正しく動かすことができ、paramikoのためのscpアドオンもあります。 残念ながら、 "pexpect"は私に必要な仮想ptyを作成できません。また、paramikoが必要とする暗号化パッケージのコンパイル済みバージョンはありません。私が裸のサードパーティ製の組み込みデバイスに取り組んでいるので、ptyの作成を許可するようにシステム設定を変更したり、パッケージをクロスコンパイルするのは難しいです。 – digitalosmosis

+0

@digitalosmosisあなたに役立つかもしれないより多くの「素朴な」例が追加されました。 – mweerden

関連する問題