2011-08-19 14 views
7

मैं एक ऐसी स्क्रिप्ट पर काम कर रहा हूं जो IO.popen का उपयोग किसी अन्य प्रोग्राम को खोलने और लगातार डेटा को पढ़ने के लिए करता है। यह इस तरह है:रूबी IO.popen STDOUT बफरिंग

process = IO.popen(["/the/program", "argument", "argument"]) 

loop do 
    line = process.gets 
    puts "#{line}" 
end 

(वास्तविक कार्यक्रम सिर्फ उत्पादन मुद्रण, जाहिर है की तुलना में अधिक है - कि सिर्फ एक उदाहरण है।)

मुद्दा मैं में चल रहा हूँ कि popen STDOUT बफरिंग किया जा रहा है है खुली प्रक्रिया से। मैंने प्रोग्राम को सीधे एक खोल से और पॉपन के माध्यम से, साइड-बाय-साइड के माध्यम से चलाकर पुष्टि की है, और रूबी को एक समय में कभी भी एक पंक्ति नहीं मिलती है। यह हमेशा एक समय में कई लाइनें प्राप्त करता है, और देरी हो रही है।

मैं

STDOUT.sync = true 

की कोशिश की है ... popen से पहले, लेकिन वह कुछ भी नहीं बदला है।

प्रश्न में प्रोग्राम निश्चित रूप से \ n एक नई लाइन के रूप में उपयोग कर रहा है, इसलिए यह मुद्दा नहीं है।

+0

क्या आपने 'process.sync = true' को आजमाया था? – DNNX

+0

@Eddie क्या आपने इसे समझ लिया? –

उत्तर

5

क्या आपके पास अन्य कार्यक्रम का स्रोत है? आपको या तो अपने आउटपुट को फ्लश करने के लिए अन्य प्रोग्राम को मजबूर करने की आवश्यकता है, या अपनी स्क्रिप्ट को पीटीआई की तरह दिखाना है (pty मानक lib देखें)।

this question देखें कि क्या हो रहा है इसके बारे में अच्छी व्याख्या के लिए।

संपादित: Pty नमूना कोड:

require 'pty' 
PTY.spawn "some-command" do |r,w,p| 
    loop { puts r.gets } 
end 
+0

यह अंतिम पंक्ति को प्रिंट करने में विफल रहता है अगर यह एक नई लाइन में समाप्त नहीं होता है (उदाहरण के लिए यदि कुछ-आदेश echo -n एबीसी है)। –

3

मैं /the/program संदेह बफरिंग है जब उसे पता चलता है stdout एक टर्मिनल नहीं है - आप, बिल्ली के माध्यम से पाइप द्वारा परीक्षण कर सकते हैं जैसे:

"/the/program" "argument" "argument" | cat 

उपर्युक्त उत्तर, अगर यह समस्या है, तो इसे हल करेगा, यानी:

#!/usr/bin/env ruby 

require 'pty' 
PTY.spawn "./the-program testing one Two three" do |r,w,p| 
    loop { puts "GOT: #{r.gets}" } 
end 

कुछ भाषाओं (जैसे C) का पता लगाने अगर stdout एक टर्मिनल है और परिवर्तन बफ़र लाइन के लिए - देखने Is stdout line buffered, unbuffered or indeterminate by default?

एक उदाहरण के रूप में जब यह काम करता है, मैं एक साधारण बैश स्क्रिप्ट उत्पादन के लिए प्रत्येक तर्क और समय, एक एक पर इस्तेमाल किया समय के बीच, 3 सेकंड के बीच और रूबी स्क्रिप्ट के बीच एक समस्या के बिना काम किया। मैंने इस उदाहरण के लिए ईओफ़ डिटेक्शन जोड़ा।

संशोधित स्क्रिप्ट:

#!/usr/bin/env ruby 

process = IO.popen(["./the-program", "testing", "one", "Two", "three"]) 

while !process.eof? 
    line = process.gets 
    puts "GOT: #{line}" 
end 

-कार्यक्रम सामग्री:

#!/bin/bash 

for arg 
do 
    echo $arg 
    date 
    sleep 3 
done 

मैं गहरे लाल रंग का संस्करण 1.9.3 और 2.1.2

$ ruby ,p 
GOT: testing 
GOT: Mon Jun 16 06:19:00 EST 2014 
GOT: one 
GOT: Mon Jun 16 06:19:03 EST 2014 
GOT: Two 
GOT: Mon Jun 16 06:19:06 EST 2014 
GOT: three 
GOT: Mon Jun 16 06:19:09 EST 2014 
$ 

साथ की कोशिश की अगर मैं एक सी का उपयोग इसके बजाए प्रोग्राम, फिर समस्या पुन::

#include <stdio.h> 

main(int argc, char **argv) 
{ 
     int i; 

     for (i=0; i<argc; i++) { 
       printf("%s\n", argv[i]); 
       sleep(3); 
     } 
} 
संबंधित मुद्दे