我有一个Linux应用程序,从一些设备获取inputstream。 这个input应该被引导到一个shell进程,以便它模拟给用户一个标准的shell。 到目前为止,我已经通过创build运行'/ bin / sh'的进程来完成它,并且我redirect了其input,输出和stderr,如下所示:
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”在标准input。 (另外,stderr没有什么等待)。
我已经查看了telnetd代码,并看到使用pty。 我尝试使用pty.openpty()并将slave设置为stdin,但是这也不起作用。 应该怎么办?
更新:我用build议的-i参数。 现在我有一个问题,一旦我使用Popen,然后按ENTER键,python shell移动到后台,如下所示:
>>> p = subprocess.Popen(shell=False, args=['/bin/sh', '-i'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) >>> <ENTER> [1]+ Stopped ipython $
使用bash
autocompletion只能在交互模式下工作:
-i If the -i option is present, the shell is interactive.
这将做适当的仿真,包括显示提示和所有常用的东西。
最终要彻底解决所有问题,我不得不做几件事情:
这是工作的代码:
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)