web-dev-qa-db-ja.com

外部プロセスから既存のプロセスのSTDINにデータを書き込む方法は?

外部プロセスから既存のプロセスのSTDINにデータを書き込む方法を探していて、同様の質問が見つかりました 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/6_および_echo 'foobar' > /proc/3308/fd/0_コマンドを実行しました。両方のコマンドを実行した後、メッセージfoobarがテストスクリプトが実行されているターミナルに2回表示されますが、それだけです。行print("read :: [" + sys.stdin.readline() + "]")は実行されませんでした。

外部プロセスから既存のプロセスのSTDIN(または他のファイル記述子)にデータを書き込む、つまり他のプロセスからlineprint("read :: [" + sys.stdin.readline() + "]")の実行を呼び出す方法はありますか?

24
mooz

コードは機能しません。
/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に送信されます

21

ここで、私が役に立ったと思う例を残したいと思います。それは、私のマシンで断続的に失敗した上記の真のトリックのわずかな変更です。

# 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を使用できなかったので、このシナリオに最適でした。

5
Martín Coll