मुझे इस समस्या को हल करने में कुछ सफलता मिली है। यहां कुछ विवरणों के साथ विवरण दिए गए हैं, अगर किसी को भी इसी तरह की समस्या है तो यह पृष्ठ ढूंढता है। लेकिन अगर आप विवरणों की परवाह नहीं करते हैं, तो इसका संक्षिप्त उत्तर है :
निम्नलिखित तरीके से PTY.spawn का उपयोग करें (अपने स्वयं के आदेश के साथ):
require 'pty'
cmd = "blender -b mball.blend -o //renders/ -F JPEG -x 1 -f 1"
begin
PTY.spawn( cmd ) do |stdout, stdin, pid|
begin
stdout.each { |line| print line }
rescue Errno::EIO
puts "Errno:EIO error, but this probably just means " +
"that the process has finished giving output"
end
end
rescue PTY::ChildExited
puts "The child process exited!"
end
और यहाँ लंबा जवाब है , जिस तरह से बहुत सारे विवरण के साथ:
वास्तविक मुद्दा यह प्रतीत होता है कि यदि कोई प्रक्रिया स्पष्ट रूप से अपने स्टडआउट को फ्लश नहीं करती है, तो स्टडआउट को लिखी गई किसी भी चीज़ को वास्तव में भेजे जाने के बजाय बफर किया जाता है, जब तक कि प्रक्रिया पूरी नहीं हो जाती है, इसलिए IO को कम करने के लिए (यह स्पष्ट रूप से कई का कार्यान्वयन विवरण है सी लाइब्रेरीज़, जिससे बनाई गई थ्रूपुट को कम अक्सर IO के माध्यम से अधिकतम किया जाता है)। यदि आप आसानी से प्रक्रिया को संशोधित कर सकते हैं ताकि यह नियमित रूप से फ्लशआउट हो जाए, तो यह आपका समाधान होगा। मेरे मामले में, यह ब्लेंडर था, इसलिए स्रोत को संशोधित करने के लिए एक पूर्ण noob जैसे खुद को डराना।
लेकिन जब आप इन प्रक्रियाओं को शेल से चलाते हैं, तो वे वास्तविक समय में शेल के लिए stdout प्रदर्शित करते हैं, और stdout बफ़र्ड प्रतीत नहीं होता है। जब मुझे विश्वास होता है कि किसी अन्य प्रक्रिया से कॉल किया जाता है, तो यह केवल बफ़र है, लेकिन यदि किसी शेल से निपटा जा रहा है, तो वास्तविक समय में, स्टडआउट को अप्रभावित देखा जाता है।
इस व्यवहार को एक रूबी प्रक्रिया के साथ भी देखा जा सकता है क्योंकि बाल प्रक्रिया जिसका उत्पादन वास्तविक समय में एकत्र किया जाना चाहिए। बस एक स्क्रिप्ट बनाएं, random.rb, निम्न पंक्ति के साथ:
5.times { |i| sleep( 3*rand ); puts "#{i}" }
फिर इसे बुलाने और इसके आउटपुट को वापस करने के लिए एक रूबी स्क्रिप्ट:
IO.popen( "ruby random.rb") do |random|
random.each { |line| puts line }
end
आप देखेंगे कि आपको वास्तविक समय में परिणाम नहीं मिल रहा है जैसा कि आप उम्मीद कर सकते हैं, लेकिन बाद में सभी एक बार। STDOUT को बफ़र किया जा रहा है, भले ही आप random.rb को स्वयं चलाते हों, लेकिन यह बफ़र्ड नहीं है। इसे STDOUT.flush
random.rb में ब्लॉक के अंदर एक स्टेटमेंट जोड़कर हल किया जा सकता है । लेकिन अगर आप स्रोत नहीं बदल सकते हैं, तो आपको इसके आसपास काम करना होगा। आप इसे प्रक्रिया से बाहर नहीं निकाल सकते।
यदि सबप्रोसेस वास्तविक समय में शेल में प्रिंट कर सकते हैं, तो रूबी के साथ वास्तविक समय में भी इसे कैप्चर करने का एक तरीका होना चाहिए। और वहां है। आपको पीटीवाई मॉड्यूल का उपयोग करना होगा, जो रूबी कोर में शामिल है, मुझे विश्वास है (1.8.6 वैसे)। दुखद बात यह है कि यह प्रलेखित नहीं है। लेकिन मुझे सौभाग्य से उपयोग के कुछ उदाहरण मिले।
सबसे पहले, यह समझाने के लिए कि पीटीवाई क्या है, यह छद्म टर्मिनल के लिए खड़ा है । मूल रूप से, यह रूबी स्क्रिप्ट को उपप्रोसेस में स्वयं को प्रस्तुत करने की अनुमति देता है जैसे कि यह एक वास्तविक उपयोगकर्ता है जिसने केवल एक शेल में कमांड टाइप किया है। इसलिए कोई भी परिवर्तित व्यवहार जो केवल तब होता है जब किसी उपयोगकर्ता ने शेल के माध्यम से प्रक्रिया शुरू की है (जैसे कि STDOUT को बफर नहीं किया जा रहा है, इस मामले में)। इस तथ्य को ध्यान में रखते हुए कि एक और प्रक्रिया शुरू हुई है यह प्रक्रिया आपको वास्तविक समय में STDOUT को इकट्ठा करने की अनुमति देती है, क्योंकि यह बफर नहीं किया जा रहा है।
बच्चे के रूप में random.rb स्क्रिप्ट के साथ इस काम को करने के लिए, निम्न कोड का प्रयास करें:
require 'pty'
begin
PTY.spawn( "ruby random.rb" ) do |stdout, stdin, pid|
begin
stdout.each { |line| print line }
rescue Errno::EIO
end
end
rescue PTY::ChildExited
puts "The child process exited!"
end