2011-03-21 20 views
18

मैं बाहरी प्रक्रियाओं से मौजूदा प्रक्रिया के STDIN पर डेटा लिखने के तरीकों की तलाश कर रहा हूं, और स्टैक ओवरलो में How do you stream data into the STDIN of a program from different local/remote processes in Python? समान प्रश्न मिला।बाहरी प्रक्रिया से मौजूदा प्रक्रिया के एसटीडीआईएन में डेटा कैसे लिखें?

उस धागे में, @ माइकल का कहना है कि हम नीचे की तरह पथ में मौजूदा प्रक्रिया के फाइल डिस्क्रिप्टर प्राप्त कर सकते हैं, और लिनक्स पर डेटा लिखने की अनुमति दे सकते हैं।

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

यह परीक्षण स्क्रिप्ट 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() + "]") लाइन निष्पादन का आह्वान करते हैं?

+1

क्या नामित पाइप ('मैन mkfifo' देखें) क्या आप चाहते हैं? – Andy

+0

सुझाव के लिए धन्यवाद।मैं नामित पाइप पर एक नज़र डालेगा। – mooz

उत्तर

16

आपका कोड काम नहीं करेगा।
/proc/pid/fd/0/dev/pts/6 फ़ाइल का एक लिंक है।

$ गूंज 'foobar'>/dev/सार्वजनिक टेलीफोन/6
$ गूंज 'foobar'>/proc/पीआईडी ​​/ fd/0

के बाद से दोनों आदेशों टर्मिनल के लिए लिखें। यह इनपुट टर्मिनल पर जाता है, न कि प्रक्रिया के लिए।

यह काम करेगा अगर stdin intially एक पाइप है।
उदाहरण के लिए, 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' की प्रक्रिया बनाई,' प्रिंट ("read :: [" + sys.stdin.readline() + "]") निष्पादित करने का कोई तरीका नहीं है बाहरी प्रक्रिया? – mooz

+1

@mooz: AFAIK ऐसा करने का कोई तरीका नहीं है। –

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 है, जो इस स्थिति के लिए एकदम सही है का उपयोग नहीं कर सकता है के लिए मेरे पास मददगार था।