簡體   English   中英

捕獲傳遞給嵌入式終端的命令的標准輸出

[英]Capture standard output for command passed to an embedded terminal

我試圖捕獲我正在使用subprocess.Popen運行的命令的輸出,並輸出到嵌入在tkinter構建的應用程序中的xterm終端。 我希望命令的輸出轉到終端並被捕獲,以便我可以分析信息。

在另一種情況下,我只使用subprocess.Popen運行命令,並且不將輸出傳遞給終端。 我可以通過包含stdout=subprocess.PIPE, stderr=subprocess.STDOUT獲得輸出

proc_output = subprocess.Popen('ls', stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
print(str(proc_output.stdout.read()))

我猜我的編碼方式我可以將輸出發送到終端或變量,但不是兩者。

對於我的代碼示例,一旦終端打開,我必須在終端中手動鍵入tty ,然后將輸出放在tty輸入字段中。 之后,我可以從cmd_entry運行命令並將輸出發送到終端。

此代碼是此處答案的略微修改版本。

from tkinter import *
import subprocess

root = Tk()
termf = Frame(root, height=360, width=625)
termf.pack(fill=BOTH, expand=YES)
wid = termf.winfo_id()

f=Frame(root)
Label(f,text="/dev/pts/").pack(side=LEFT)
tty_index = Entry(f, width=3)
tty_index.insert(0, "1")
tty_index.pack(side=LEFT)
Label(f,text="Command:").pack(side=LEFT)
cmd_entry = Entry(f)
cmd_entry.insert(0, "ls -l")
cmd_entry.pack(side=LEFT, fill=X, expand=1)

def send_entry_to_terminal(*args):
    tty="/dev/pts/%s" % tty_index.get()
    proc = subprocess.Popen(f'{cmd_entry.get()} <{tty} >{tty} 2> {tty}',
                            shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    print(str(proc.stdout.read())
    # cmd(f'{e.get()} <{tty} >{tty} 2> {tty}')

cmd_entry.bind("<Return>", send_entry_to_terminal)
b = Button(f,text="Send", command=send_entry_to_terminal)
b.pack(side=LEFT)
f.pack(fill=X, expand=1)

# cmd(f'xterm -into {wid} -geometry 100x27 -sb -e "tty; sh" &')
subprocess.Popen(f'xterm -into {wid} -geometry 100x27 -sb &', shell=True)

root.mainloop()

我想要做的是讓任何命令的輸出與子進程一起運行以打印到終端並保存在變量中以便以后處理。 但是現在我只能得到一個或另一個。

首先將shell重定向轉換為本機Popen功能:

with open(tty,'r+b',0) as f:
  proc=subprocess.Popen(cmd_entry.get(),shell=True,
                        stdin=f,stdout=f,stderr=f)
if proc.wait(): warn_user(…)

那么如何保留輸出的副本應該是相當明顯的:

with open(tty,'r+b',0) as f:
  proc=subprocess.Popen(cmd_entry.get(),shell=True,
                        stdin=f,stdout=subprocess.PIPE,stderr=subprocess.STDOUT)
  out=[]
  for l in proc.stdout:
    f.write(l)
    out.append(l)
  out=b"".join(out)
  if proc.wait(): warn_user(…)

請注意,該進程將為其輸出設置管道而不是(偽)終端,這可能會改變其行為( 例如ls打印在單個列中,而git不使用尋呼機)。 如果要保留終端行為,則必須打開自己的偽終端並將寫入的中繼輸出(可能包含各種控制序列)發送到xterm創建的輸出。

您可能還希望將該進程設置為( xterm )終端的前台進程組,以便它可以接收鍵盤信號; 這涉及到tcsetpgrp ,有點復雜。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM