将输出重定向到VTE终端的最佳方法

时间:2014-08-11 02:23:39

标签: bash python-2.7 vte

将命令输出重定向到VTE终端的最佳方法是什么?

我带着这个想法:

在VTE上执行:

tty > /usr/tmp/terminal_number    

然后从python程序中读取文件:

with open('/usr/tmp/terminal_number', 'r') as f:
    self.VTE_redirect_path=f.readline()

然后执行bash命令,例如:

os.system('''echo "foo" >  {0}'''.format(self.VTE_redirect_path))

此方法的问题是需要刷新包含terminal_number的文件/dev/pts/#。此外,我真的不喜欢必须创建文件进行通信的想法。有没有直接的解决方案?

2 个答案:

答案 0 :(得分:2)

@Quentin你给我的解决方案打印控制台输出非常糟糕(它没有缩进)所以我不得不使用我的解决方案。这是一个明显的例子:

from gi.repository import Gtk, GObject, Vte, GLib
import os, time, threading

def command_on_VTE(self,command):
    length=len(command)
    self.terminal.feed_child(command, length)


class TheWindow(Gtk.Window):

    def __init__(self):
        Gtk.Window.__init__(self, title="inherited cell renderer")
        self.set_default_size(600, 300)
        self.terminal=Vte.Terminal()
        self.terminal.fork_command_full(
                Vte.PtyFlags.DEFAULT, #default is fine
                os.environ['HOME'], #where to start the command?
                ["/bin/bash"], #where is the emulator?
                [], #it's ok to leave this list empty
                GLib.SpawnFlags.DO_NOT_REAP_CHILD,
                None, #at least None is required
                None,
                )

        #set up the interface
        box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
        #a scroll window is required for the terminal
        scroller = Gtk.ScrolledWindow()
        scroller.set_hexpand(True)
        scroller.set_vexpand(True)
        scroller.add(self.terminal)
        box.pack_start(scroller, False, True, 2)
        self.add(box)

        #To get the command to automatically run
        #a newline(\n) character is used at the end of the
        #command string.
        command_on_VTE(self,'''tty > /tmp/terminal_number\n''') # Get the terminal ID

        # read the terminal ID
        while not os.path.exists("/tmp/terminal_number"):
            time.sleep(0.1) 
        with open('/tmp/terminal_number', 'r') as f:
            self.VTE_redirect_path=f.readline()
            os.remove('/tmp/terminal_number')

        # this cleans the vte
        os.system('''printf "\\033c" > {0}'''.format(self.VTE_redirect_path)) 


        # this calls the exemple
        threading.Thread(target=self.make_a_test).start()   

    def make_a_test(self):
        os.system('''ls -laR /home/ > {rdc}
echo "-------- The listing ended -------

Note that the input of the commands are not printed
" > {rdc}'''.format(rdc=self.VTE_redirect_path))

win = TheWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()

我还没有找到一种方法来获取终端ID而没有通过创建临时文件。如果有一些方法可以将变量从VTE传递给python脚本,则可以跳过此步骤。对此的任何帮助都会很棒!

答案 1 :(得分:0)

在VTE中,您使用terminal.feed(“string”)

请参阅vte_terminal_feed

使用python Popen是执行命令的建议方法。 如果您想使用命令,那么您应该这样做。

#Uncomment the next line to get the print() function of python 3
#from __future__ import print_function
import os
import subprocess
from subprocess import Popen
command = "echo \"something\""
env = os.environ.copy()
try:
    po = Popen(command, shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE,
        universal_newlines=True, env=env)
    po.wait()
    output, error_output = po.communicate()

    if po.returncode:
        print(error_output)
    else:
        print(output)

except OSError as e:
    print('Execution failed:', e, file=sys.stderr)

如果你想将gtk与gtk vte一起使用,那就改为使用。

#place the following in a method of a vte instance
env = os.environ.copy()
try:
    po = Popen(command, shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE,
        universal_newlines=True, env=env)
    po.wait()
    output, error_output = po.communicate()

    if po.returncode:
        print(error_output)
    else:
        self.feed(output) #here you're printing to your terminal.

except OSError as e:
    print('Execution failed:', e, file=sys.stderr)

对于常规终端中最精细的控制,您可以尝试cmd module。这将要求您生成自己的提示,以便获得您想要的更具体的选项。