2

次の Python スニペットがありますが、なぜこのように動作するのか説明できません。

import subprocess  
bash1 = subprocess.Popen(["/bin/bash","-l", "-i"], stdin=subprocess.PIPE)  
print "Checkpoint 1"  
bash2 = subprocess.Popen(["/bin/bash","-l", "-i"], stdin=subprocess.PIPE)  
print "Checkpoint 2"  
bash1.communicate("echo 'works1'")  
bash2.communicate("echo 'works2'")  
print "OK"

実行すると、次の出力が得られます。

[user@localhost ~]$ python test.py  
Checkpoint 1  
Checkpoint 2  
[1]+  Stopped                 python test.py
[user@localhost ~]$ [user@localhost ~]$ echo 'works1'  
works1  
[user@localhost ~]$ logout  
[user@localhost ~]$ fg    
python test.py  
[user@localhost ~]$ echo 'works2'  
works2  
[user@localhost ~]$ logout 
OK  
[user@localhost ~]$
  1. 2 回目の Popen 呼び出しで Python プロセスが停止するのはなぜですか? (tty入力で停止)、それを回避する方法は?
  2. echo 'works1' の終了後にログアウト メッセージが表示されるのはなぜですか? また、それを回避するにはどうすればよいですか?
4

2 に答える 2

3

質問 1 への回答:

これは、インタラクティブな bash シェルが端末 (「制御端末」) に接続され、ジョブ制御割り込み (Control-Z など) を処理するためにそれを取得することを想定しているためです。2 番目の呼び出しは端末を取得しようとしますが取得できないため、一時的に中断されます。

質問 2 への回答:

communicate引数を子プロセスの stdin パイプに書き込み、それを閉じます。bash は、stdin が使い果たされると終了します (bash ターミナル セッションで Control-D を入力するようなものです)。

communicatebash の子プロセスを実行し続けたい場合は、次のように使用するのではなく、stdin に直接書き込みます。

bash1.stdin.write("echo 'works1'\n")

ちなみに、コマンドを実際に実行したい場合は、改行を追加する必要があります。

解決策:

2 つ以上の対話型シェルを実行する場合は、各シェルの stdin をサブプロセス PIPE ではなく疑似端末に設定する必要があります。

于 2013-02-18T19:05:35.133 に答える
2

isedev ヒントに従って、2 つの疑似端末を開きました。重要なことは、マスター プロセス (この python スクリプト) がマスター PTY ファイルを読み書きし、子サブプロセスがスレーブ ファイルを stdin、stdout、および stderr として使用することです。コードの下部は、すべてがどのように機能するかをテストするためのものです。

import subprocess
import os
import pty
import select
import time

# according to> http://fleckenzwerg2000.blogspot.com/2011/10/running-and-controlling-gnu-screen-from.html
(master1, slave1) = pty.openpty()
bash1 = subprocess.Popen(["bash", "-l", "-i"], stdin=slave1, stdout=slave1, stderr=slave1)
(master2, slave2) = pty.openpty()
bash2 = subprocess.Popen(["bash", "-l", "-i"], stdin=slave2, stdout=slave2, stderr=slave2)
data = "echo 'bla'\n"

## taken from> http://stackoverflow.com/questions/14564904/how-to-send-tab-key-to-python-subprocesss-stdin
def write_all(masterPTY, data):
    """Successively write all of data into a file-descriptor."""
    while data:
        chars_written = os.write(masterPTY, data)
        data = data[chars_written:]
    return data

def read_all(masterPTY):
    r,w,x = select.select([masterPTY], [], [], 10)
    if r:
        data = os.read(masterPTY, 1024)
        return data


write_all(master1, "echo 'bla1'\n")
write_all(master2, "echo 'bla2'\n")
time.sleep(1)
print read_all(master1)
write_all(master1, "echo 'bla1'\n")
time.sleep(1)

print read_all(master2)

time.sleep(1)

os.close(master1)
os.close(slave1)
os.close(master2)
os.close(slave2)

bash1.terminate()
bash2.terminate()

print "OK"

それだ。それが誰かを助けることを願っています!

于 2013-02-22T15:29:26.560 に答える