如何运行在单独的进程壳获得自动补全? (蟒蛇) [英] How to run a shell in a separate process and get auto completions? (Python)

查看:173
本文介绍了如何运行在单独的进程壳获得自动补全? (蟒蛇)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Linux应用程序,从某些设备获取的输入流。因此,它模拟给用户一个标准的外壳,输入应被定向到一个shell进程。到目前为止,我已经通过创建运行/ bin / sh的'一个过程来完成它,我重定向其输入,输出和标准错误如下:

 导入子P = subprocess.Popen(SHELL =假,ARGS = ['/ bin / sh的'],标准输入= subprocess.PIPE,标​​准输出= subprocess.PIPE,标​​准错误= subprocess.PIPE)
_make_nonblocking(p.stdout)#台O_NONBLOCK
_make_nonblocking(p.stderr)

当我刚一通命令,一切正常:

  p.stdin.write('PWD \\ n)
p.stdout.read()
'/家庭/戴夫\\ n'

有关自动完成,我试着写:

  p.stdin.write('LS小号\\ T')
p.stdout.read()
IO错误:[错误11]资源暂时不可用

我希望得到尽可能完整的列表,但没有任何反应,直到我把'\\ n'的标准输入。 (另外,没有任何等待标准错误)。

我已经通过telnetd的code望去,只见使用pty的。我试图用pty.openpty(),并设置从作为标准输入,但也不能工作。应如何做?

更新:我用-i参数的建议。现在我有,一旦我使用POPEN和preSS ENTER蟒蛇的外壳移动到背景如下问题:

 >>> P = subprocess.Popen(SHELL =假,ARGS = ['/ bin / sh的','-i'],标准输入= subprocess.PIPE,标​​准输出= subprocess.PIPE,标​​准错误= subprocess.PIPE)
>>> <&ENTER GT;
[1] +停止IPython中
$


解决方案

最终彻底解决所有的问题,我不得不做几件事情:


  1. 配置pty设备(使用python的PTY模块)。

  2. 将使用termios的相应标志(回声,信号处理等)。

  3. 启动一个新的会话(这样的信号不会propagte原工艺)。

  4. 使用无缓冲文件(BUFSIZE传球0)打开pty设备。

这是code的作品:

  DEF prepare():
    os.setsid()#启动一个新的独立的会话
    tty.setcbreak(sys.stdin)#设置标准输入模式CBREAK
    老= termios.tcgetattr(sys.stdin)
    老[0] | = termios.BRKINT#转换为突破SIGINT
    老[3]和安培; =#termios.ICANON非标准模式
    老[3] | = termios.ECHO | termios.ISIG#设置回音和信号处理的字符
    CC =旧[6]
    #使输入缓冲
    立方厘米[termios.VMIN] = 1
    立方厘米[termios.VTIME] = 0
    termios.tcsetattr(sys.stdin,termios.TCSANOW,老)主,从= pty.openpty()
主= os.fdopen(主人,RB + WB',0)#打开文件中的缓冲模式
_make_non_blocking(主)PROG = subprocess.Popen(SHELL =假,ARGS = ['/ bin / sh的','-i'],标准输入=奴隶,标准输出=奴隶,标准错误= subprocess.STDOUT,preexec_fn = prepare)

I have a linux application that gets an input stream from some device. That input should be directed to a shell process so that it emulates to the user a standard shell. So far, I've done it by creating a process that runs '/bin/sh' and I redirected its input, output, and stderr as follows:

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)

When I just a pass command, everything works:

p.stdin.write('pwd\n')
p.stdout.read()
'/home/dave\n'

For auto completion, I tried writing:

p.stdin.write('ls s\t')
p.stdout.read()
IOError: [Errno 11] Resource temporarily unavailable

I expect to get a list of possible completions but nothing happens until I put '\n' in stdin. (Also, there was nothing waiting in stderr).

I've looked through the telnetd code and saw the use of pty. I tried to use pty.openpty() and set slave as stdin, but that didn't work either. How should it be done?

UPDATE: I used the -i parameter as suggested. Now I have a problem that once I use Popen and press ENTER the python shell move to the background as follows:

>>> p = subprocess.Popen(shell=False, args=['/bin/sh', '-i'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
>>> <ENTER>
[1]+ Stopped                ipython
$ 

解决方案

Eventually to completely solve all problems I had to do several things:

  1. configure a pty device (using pty module in python).
  2. set the appropriate flags using termios (echo, signal handling, etc).
  3. start a new session (so that signals won't propagte the original process).
  4. open the pty device using an unbuffered file (passing 0 in bufsize).

This is the code that works:

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)

这篇关于如何运行在单独的进程壳获得自动补全? (蟒蛇)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆