用popen无法启动两个交互shell [英] Cannot start two interactive shells using popen
问题描述
我有以下的Python代码片段,并不能解释为什么它的行为方式是这样。
导入子
bash1 = subprocess.Popen([/斌/ bash的, - 1,-i],标准输入= subprocess.PIPE)
打印检查点1
bash2 = subprocess.Popen([/斌/ bash的, - 1,-i],标准输入= subprocess.PIPE)
打印检查点2
bash1.communicate(回声works1')
bash2.communicate(回声Works2的')
打印OK
当我运行它,我得到以下的输出:
[用户@本地〜] $蟒蛇test.py
检查点1
检查点2
[1] +停止蟒蛇test.py
[用户@本地〜] $ [用户@本地〜] $回声'works1
works1
[用户@本地〜] $注销
[用户@本地〜] $ FG
蟒蛇test.py
[用户@本地〜] $回声'Works2的
Works2的
[用户@本地〜] $注销
好
[用户@本地〜] $
- 为什么Python的过程中停止了对第二POPEN电话吗? (由TTY输入停止),以及如何避免呢?
- 为什么我收到注销邮件回声works1'结束后,以及如何避免呢?
答问题1:
这是因为一个交互式bash外壳期望要附加到一个端子('控制终端')和以处理作业控制的中断(例如控制-Z)获得它。第二次调用试图获取终端却不能,因此被暂停。
答问题2:
沟通
将它的参数传递给子进程的标准输入管道,然后将其关闭。当它的标准输入耗尽击结束(这就像在一个bash终端会话进入控制-D)。
如果你想保持bash的子进程的运行,然后写入其标准输入,而不是直接使用沟通
如下:
bash1.stdin.write(回声works1的'\\ n)
您确实需要添加新行,如果你想命令实际执行,顺便说一句。
一个解决方案:
如果你想运行两个或更多的交互式shell,你应该设置每个壳的标准输入是一个的伪终端,而不是一个子进程管道。
I have the following Python snippet, and cannot explain why it behaves the way it does.
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"
When I run it, I get the following output:
[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 ~]$
- Why is Python process stopped on second Popen call? (stopped by tty input), and how to avoid it?
- Why do I get logout message after echo 'works1' is finished, and how to avoid it?
Answer to question 1:
This is because an interactive bash shell expects to be attached to a terminal (the 'controlling terminal') and acquire it in order to process job control interrupts (e.g. Control-Z). The second invocation tries to acquire the terminal but can't, so gets temporarily suspended.
Answer to question 2:
communicate
writes its argument to the stdin pipe of the child process and then closes it. Bash terminates when its stdin is exhausted (it is like entering Control-D in a bash terminal session).
If you want to keep the bash child process running, then write to its stdin directly rather than use communicate
as follows:
bash1.stdin.write("echo 'works1'\n")
You do need to add the newline if you want the command to actually execute, by the way.
A solution:
If you want to run two or more interactive shells, you should setup the stdin of each shell to be a pseudo-terminal rather than a subprocess PIPE.
这篇关于用popen无法启动两个交互shell的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!