Как записать данные в STDIN существующего процесса из внешнего процесса? - PullRequest
22 голосов
/ 21 марта 2011

Я ищу способы записи данных в существующий процесс STDIN из внешних процессов и нашел похожий вопрос Как вы передаете данные в STDIN программы из разных локальных / удаленных процессов в Python? в stackoverlow.

В этом потоке @Michael говорит, что мы можем получить файловые дескрипторы существующего процесса по пути, как показано ниже, и разрешить записывать в них данные в Linux.

/proc/$PID/fd/

Итак, я создал простой скрипт из списка ниже, чтобы проверить запись данных в STDINTTY) скрипта из внешнего процесса.

#!/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() + "]")

Этот тестовый сценарий показывает пути STDIN и TTY, а затем подождите, пока один из них не напишет, что он STDIN.

Я запустил этот скрипт и получил сообщения ниже.

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

Итак, я выполнил команду echo 'foobar' > /dev/pts/6 и echo 'foobar' > /proc/3308/fd/0 с другого терминала. После выполнения обеих команд сообщение foobar отображается дважды на терминале, на котором запущен тестовый скрипт, но это все. Строка print("read :: [" + sys.stdin.readline() + "]") не была выполнена.

Существуют ли способы записи данных из внешних процессов в STDIN (или другие файловые дескрипторы) существующего процесса, т. Е. Вызывать выполнение строки print("read :: [" + sys.stdin.readline() + "]") из других процессов?

Ответы [ 2 ]

20 голосов
/ 21 марта 2011

Ваш код не будет работать.
/proc/pid/fd/0 является ссылкой на файл /dev/pts/6.

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

Поскольку обе команды пишут в терминал. Этот вход поступает на терминал, а не на процесс.

Это будет работать, если 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

Запустите это как:

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

Теперь из другого терминала напишите что-нибудь в /proc/pid/fd/0 и оно придет в test.py

4 голосов
/ 18 сентября 2015

Я хочу оставить здесь пример, который я нашел полезным.Это небольшая модификация приведенного выше настоящего трюка, который периодически прерывался на моей машине.

# 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, что идеально подходит для этого сценария..

...