如何从外部进程将数据写入现有进程的 STDIN?

Posted

技术标签:

【中文标题】如何从外部进程将数据写入现有进程的 STDIN?【英文标题】:How to write data to existing process's STDIN from external process? 【发布时间】:2011-07-19 10:58:28 【问题描述】:

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

在那个线程中,@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(或其他文件描述符),即从其他进程调用 lineprint("read :: [" + sys.stdin.readline() + "]") 的执行?

【问题讨论】:

命名管道(见man mkfifo)会做你想做的事吗? 感谢您的建议。我来看看命名管道。 【参考方案1】:

您的代码将不起作用。/proc/pid/fd/0 是指向/dev/pts/6 文件的链接。

$ echo 'foobar' > /dev/pts/6 $ echo 'foobar' > /proc/pid/fd/0

因为这两个命令都写入终端。此输入进入终端而不是进程。

如果标准输入最初是管道,它将起作用。 例如,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

【讨论】:

您建议的脚本和命令可以正常工作。那么,一旦我从没有管道的终端(如$ python test.py)创建进程,就无法从外部进程执行print("read :: [" + sys.stdin.readline() + "]") @mooz:AFAIK 没有办法做到这一点。【参考方案2】:

我想在这里留下一个我觉得有用的例子。这是对上面在我的机器上间歇性失败的 while true 技巧的轻微修改。

# 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,这非常适合这种情况。

【讨论】:

以上是关于如何从外部进程将数据写入现有进程的 STDIN?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Perl 中读取和写入大缓冲区到进程 stdin/stdout/stderr?

子进程stdin没有得到数据,由父进程发送

如何在 Python 中执行将数据写入标准输入的进程?

使用 boost::process 读取 cout 并写入进程的 cin

Python asyncio子进程连续写入stdin和读取stdout/stderr

当父进程为 64 位时,StdIN/StdOUT 管道出现问题