[英]Run interactive Bash in dumb terminal using Python subprocess.Popen and pty
這個問題類似於使用 popen 和專用的 TTY Python 運行交互式 Bash ,除了我想在“啞”終端( TERM=dumb
)中運行 Bash,並且不將 tty 置於原始模式。
下面的代碼是我的嘗試。 該代碼類似於鏈接問題中給出的解決方案,主要區別在於它不會將 tty 置於原始模式,並設置TERM=dumb
。
import os
import pty
import select
import subprocess
import sys
master_fd, slave_fd = pty.openpty()
p = subprocess.Popen(['bash'],
stdin=slave_fd,
stdout=slave_fd,
stderr=slave_fd,
# Run in a new process group to enable bash's job control.
preexec_fn=os.setsid,
# Run bash in "dumb" terminal.
env=dict(os.environ, TERM='dumb'))
while p.poll() is None:
r, w, e = select.select([sys.stdin, master_fd], [], [])
if sys.stdin in r:
user_input = os.read(sys.stdin.fileno(), 10240)
os.write(master_fd, user_input)
elif master_fd in r:
output = os.read(master_fd, 10240)
os.write(sys.stdout.fileno(), output)
上面的代碼有兩個問題:
printf ''
,上面的代碼將在打印下一個 bash 提示之前在下一行打印printf ''
。bash
所期望的那樣。我應該如何解決這些問題?
這正是不將 tty 置於原始模式的副作用。 通常,處理 pty 的程序(如expect )會將外部 tty 置於原始模式。
您的 Python 腳本的 tty(或 pty)會回顯您輸入的內容,並且新的 pty 會第二次回顯。 您可以在新 pty 上禁用 ECHO。 例如:
$ python3 using-pty.py bash-5.1$ echo hello echo hello hello bash-5.1$ stty -echo stty -echo bash-5.1$ echo hello # <-- no double echo any more hello bash-5.1$ exit exit
您的 Python 腳本的 tty 未處於原始模式,因此當您按ctrl-d 時, Python 不會獲得文字ctrl-d 。 相反,Python 會到達 EOF 並且read()
返回一個空字符串。 因此,要使生成的外殼退出,您可以
user_input = os.read(sys.stdin.fileno(), 10240) if not user_input: # explicitly send ctrl-d to the spawned process os.write(master_fd, b'\\04') else: os.write(master_fd, user_input)
同樣,Python 的 tty 不在原始模式下,所以當你按下ctrl-c 時,它不會得到文字ctrl-d 。 相反,它被殺死了。 作為一種解決方法,您可以捕獲SIGINT
。
def handle_sigint(signum, stack): global master_fd # send ctrl-c os.write(master_fd, b'\\03') signal.signal(signal.SIGINT, handle_sigint)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.