gpt4 book ai didi

python - 使用 popen 和专用的 TTY Python 运行交互式 Bash

转载 作者:IT王子 更新时间:2023-10-28 23:59:42 25 4
gpt4 key购买 nike

我需要在 Python 的单独进程中运行一个交互式 Bash 实例,它有自己的专用 TTY(我不能使用 pexpect)。我使用了我在类似程序中经常看到的这段代码片段:

master, slave = pty.openpty()

p = subprocess.Popen(["/bin/bash", "-i"], stdin=slave, stdout=slave, stderr=slave)

os.close(slave)

x = os.read(master, 1026)

print x

subprocess.Popen.kill(p)
os.close(master)

但是当我运行它时,我得到以下输出:

$ ./pty_try.py
bash: cannot set terminal process group (10790): Inappropriate ioctl for device
bash: no job control in this shell

运行的 Strace 显示一些错误:

...
readlink("/usr/bin/python2.7", 0x7ffc8db02510, 4096) = -1 EINVAL (Invalid argument)
...
ioctl(3, SNDCTL_TMR_TIMEBASE or SNDRV_TIMER_IOCTL_NEXT_DEVICE or TCGETS, 0x7ffc8db03590) = -1 ENOTTY (Inappropriate ioctl for device)
...
readlink("./pty_try.py", 0x7ffc8db00610, 4096) = -1 EINVAL (Invalid argument)

代码片段看起来很简单,是 Bash 没有得到它需要的东西吗?这可能是什么问题?

最佳答案

这是一个在子进程中运行交互式命令的解决方案。它使用伪终端使 stdout 成为非阻塞的(有些命令也需要 tty 设备,例如 bash)。它使用 select 来处理子进程的输入和输出。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import os
import sys
import select
import termios
import tty
import pty
from subprocess import Popen

command = 'bash'
# command = 'docker run -it --rm centos /bin/bash'.split()

# save original tty setting then set it to raw mode
old_tty = termios.tcgetattr(sys.stdin)
tty.setraw(sys.stdin.fileno())

# open pseudo-terminal to interact with subprocess
master_fd, slave_fd = pty.openpty()


try:
# use os.setsid() make it run in a new process group, or bash job control will not be enabled
p = Popen(command,
preexec_fn=os.setsid,
stdin=slave_fd,
stdout=slave_fd,
stderr=slave_fd,
universal_newlines=True)

while p.poll() is None:
r, w, e = select.select([sys.stdin, master_fd], [], [])
if sys.stdin in r:
d = os.read(sys.stdin.fileno(), 10240)
os.write(master_fd, d)
elif master_fd in r:
o = os.read(master_fd, 10240)
if o:
os.write(sys.stdout.fileno(), o)
finally:
# restore tty settings back
termios.tcsetattr(sys.stdin, termios.TCSADRAIN, old_tty)

关于python - 使用 popen 和专用的 TTY Python 运行交互式 Bash,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41542960/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com