2011-03-21 104 views
18

我正在寻求从外部进程向现有进程的STDIN写入数据的方法,并在stackoverlow中发现了类似的问题How do you stream data into the STDIN of a program from different local/remote processes in Python?如何从外部进程将数据写入现有进程的STDIN?

在该线程中,@Michael说我们可以像下面那样获取现有进程的文件描述符,并允许在Linux上将数据写入它们。

/proc/$PID/fd/ 

所以,我创建了下面列出的数据写入测试从外部过程脚本的STDIN(和TTY)一个简单的脚本。

#!/usr/bin/env python 

import os, sys 

def get_ttyname(): 
    for f in sys.stdin, sys.stdout, sys.stderr: 
     if f.isatty(): 
      return os.ttyname(f.fileno()) 
    return None 

if __name__ == "__main__": 
    print("Try commands below") 

    print("$ echo 'foobar' > {0}".format(get_ttyname())) 
    print("$ echo 'foobar' > /proc/{0}/fd/0".format(os.getpid())) 

    print("read :: [" + sys.stdin.readline() + "]") 

这个测试脚本显示的STDINTTY路径,然后等待一个写它的STDIN

我启动了这个脚本,在下面得到了消息。

Try commands below 
$ echo 'foobar' > /dev/pts/6 
$ echo 'foobar' > /proc/3308/fd/0 

所以,我执行来自其它终端的命令echo 'foobar' > /dev/pts/6echo 'foobar' > /proc/3308/fd/0。执行完这两个命令之后,消息foobar在运行测试脚本的终端上显示两次,但仅此而已。行print("read :: [" + sys.stdin.readline() + "]")未执行。

是否有任何方法将数据从外部进程写入现有进程的STDIN(或其他文件描述符),即调用其他进程执行print("read :: [" + sys.stdin.readline() + "]")行?

+1

命名管道(请参见man mkfifo')做你想要的吗? – Andy 2011-03-21 16:05:11

+0

感谢您的建议。我会看看named-pipe。 – mooz 2011-03-21 18:20:47

回答

16

您的代码将无法使用。
/proc/pid/fd/0是到/dev/pts/6文件的链接。

$回声 'foobar的'>的/ dev/PTS/6
$回声 'foobar的'>/proc /进程/ FD/0

由于两个命令写入到终端。该输入进入终端,而不是进程。

这将工作,如果标准输入为inlined是管道。
例如,test.py是:

#!/usr/bin/python 

import os, sys 
if __name__ == "__main__": 
    print("Try commands below") 
    print("$ echo 'foobar' > /proc/{0}/fd/0".format(os.getpid())) 
    while True: 
     print("read :: [" + sys.stdin.readline() + "]") 
     pass 

运行此为:

$ (while [ 1 ]; do sleep 1; done) | python test.py 
从另一端写的东西 /proc/pid/fd/0

现在,它会来到test.py

+0

您提出的脚本和命令可以正常工作。所以,一旦我像'$ python test.py'那样从没有管道的终端创建进程,就没有办法执行'print(“read :: [”+ sys.stdin.readline()+“]”)'from外部过程? – mooz 2011-03-21 18:13:40

+1

@mooz:AFAIK没有办法做到这一点。 – 2011-03-24 06:39:54

3

我想在这里的离开我发现有用的例子。这是对我的机器上间歇性失败的上述真实技巧的轻微修改。

# pipe cat to your long running process 
(cat) | ./your_server & 
server_pid=$! 
# send an echo to your cat process that will close cat and in my hypothetical case the server too 
echo "quit\n" > "/proc/$server_pid/fd/0" 

这是对我很有帮助,因为我不能用mkfifo,这是完美的这种情况下特殊原因。

相关问题