我有一个Linux应用程序,从某个设备获得的输入流。 使得它模拟给用户的标准外壳,输入应被定向到一个外壳进程。 到目前为止,我已经通过创建运行“/ bin / sh的”一个过程来完成它,我重定向它的输入,输出和标准错误如下:
import subprocess
p = subprocess.Popen(shell=False, args=['/bin/sh'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
_make_nonblocking(p.stdout) # sets O_NONBLOCK
_make_nonblocking(p.stderr)
当我刚一通命令,一切正常:
p.stdin.write('pwd\n')
p.stdout.read()
'/home/dave\n'
对于自动完成,我试着写:
p.stdin.write('ls s\t')
p.stdout.read()
IOError: [Errno 11] Resource temporarily unavailable
我希望得到尽可能完整的列表,但没有任何反应,直到我把“\ n”的标准输入。 (另外,没有任何等待标准错误)。
我已经通过telnetd的代码望去,只见使用pty的。 我试图用pty.openpty()和从属组作为标准输入,但也不能工作。 应该怎样做呢?
更新:我使用-i参数的建议。 现在我有,一旦我使用POPEN,然后按ENTER蟒蛇的外壳移动到背景如下问题:
>>> p = subprocess.Popen(shell=False, args=['/bin/sh', '-i'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
>>> <ENTER>
[1]+ Stopped ipython
$
随着bash
自动完成功能只能在交互模式:
-i If the -i option is present, the shell is interactive.
这将做适当的仿真,包括显示提示和所有常见的东西。
最终彻底解决所有的问题,我不得不做几件事情:
- 配置PTY设备(使用PTY模块在python)。
- 设定使用的termios(回波,信号处理等)相应的标志。
- 启动一个新的会话(使信号不会propagte原工艺)。
- 打开使用无缓冲文件(在BUFSIZE传递0)的PTY设备。
这是工作的代码:
def prepare():
os.setsid() # start a new detached session
tty.setcbreak(sys.stdin) # set standard input to cbreak mode
old = termios.tcgetattr(sys.stdin)
old[0] |= termios.BRKINT # transforms break to SIGINT
old[3] &= termios.ICANON # non-canonical mode
old[3] |= termios.ECHO | termios.ISIG # set echo and signal characters handling
cc = old[6]
# make input unbuffered
cc[termios.VMIN] = 1
cc[termios.VTIME] = 0
termios.tcsetattr(sys.stdin, termios.TCSANOW, old)
master, slave = pty.openpty()
master = os.fdopen(master, 'rb+wb', 0) # open file in an unbuffered mode
_make_non_blocking(master)
prog = subprocess.Popen(shell=False, args=['/bin/sh', '-i'], stdin=slave, stdout=slave, stderr=subprocess.STDOUT, preexec_fn=prepare)
文章来源: How to run a shell in a separate process and get auto completions? (Python)