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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5374255/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-05 03:20:31  来源:igfitidea点击:

How to write data to existing process's STDIN from external process?

linuxprocessstdinfile-descriptortty

提问by mooz

I'm seeking for ways to write data to the existing process's STDINfrom external processes, and found similar question How do you stream data into the STDIN of a program from different local/remote processes in Python?in stackoverlow.

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

In that thread, @Michael says that we can get file descriptors of existing process in path like below, and permitted to write data into them on Linux.

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

/proc/$PID/fd/

So, I've created a simple script listed below to test writing data to the script's STDIN(and TTY) from external process.

因此,我创建了一个下面列出的简单脚本来测试从外部进程向脚本的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() + "]")

This test script shows paths of STDINand TTYand then, wait for one to write it's STDIN.

这个测试脚本显示了STDINTTY然后,等待一个人写它的STDIN.

I launched this script and got messages below.

我启动了这个脚本并在下面收到了消息。

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

So, I executed the command echo 'foobar' > /dev/pts/6and echo 'foobar' > /proc/3308/fd/0from other terminal. After execution of both commands, message foobaris displayed twice on the terminal the test script is running on, but that's all. The line print("read :: [" + sys.stdin.readline() + "]")was not executed.

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

Are there any ways to write data from external processes to the existing process's STDIN(or other file descriptors), i.e. invoke execution of the lineprint("read :: [" + sys.stdin.readline() + "]")from other processes?

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

采纳答案by Rumple Stiltskin

Your code will not work.
/proc/pid/fd/0is a link to the /dev/pts/6file.

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

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

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

Since both the commands write to the terminal. This input goes to terminal and not to the process.

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

It will work if stdin intially is a pipe.
For example, test.pyis :

如果 stdin 最初是一个管道,它将起作用。
例如,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

Run this as:

运行它:

$ (while [ 1 ]; do sleep 1; done) | python test.py

Now from another terminal write something to /proc/pid/fd/0and it will come to test.py

现在从另一个终端写一些东西/proc/pid/fd/0,它会来test.py

回答by Martín Coll

I want to leave here an example I found useful. It's a slight modification of the while true trick above that failed intermittently on my machine.

我想在这里留下一个我觉得有用的例子。这是对上面的 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"

It was helpful to me because for particular reasons I couldn't use mkfifo, which is perfect for this scenario.

这对我很有帮助,因为由于特殊原因我无法使用mkfifo,这非常适合这种情况。