2013-09-01 4 views
6

के साथ काम नहीं करता है नीचे दिया गया कोड tail -f के आउटपुट को प्रिंट नहीं करता है। क्यूं कर? मैं इसे कैसे कारगर बना सकता हूं?रूबी में बैक-टिक tail -f कमांड

#myApp.rb 
`ls`    #works fine 
`tail -f filename`  #does not work. why? 
+0

'" फ़ाइल नाम "' फ़ाइल (या एक डमी सिर्फ अपने प्रश्न के लिए उपयोग किया गया नाम) का शाब्दिक नाम है? या यह एक चर का नाम है जो एक स्ट्रिंग रखता है? – sawa

+1

'filename' प्रश्न – Bhuvan

उत्तर

7

निष्पादित आदेश tail पर अनुवर्ती विकल्प -f का उपयोग कर तुरंत समाप्त नहीं जाएगा।

-f, --follow[={name|descriptor}] 
    output appended data as the file grows; 

बैकटिक प्रयोग का विचार (या %x शॉर्टकट), के रूप में system('...') का उपयोग कर करने का विरोध किया है कि इन बयानों निष्पादित आदेशों के उत्पादन में लौट रहा है। इस तरह आप एक चर में परिणाम संग्रहीत कर सकती है:

dir_content = `ls` 

tail -f किसी अन्य प्रक्रिया spawns, इस प्रक्रिया को समाप्त करने के बिना मानक आउटपुट में लिखने पर रहता है। इसलिए, आपका बयान कभी खत्म नहीं हुआ है। बयान खत्म किए बिना, एक मूल्य वापस नहीं किया जा सकता है। यदि आप बढ़ती हुई फ़ाइल को देखना और आउटपुट देखना चाहते हैं, तो प्रश्न का समाधान देखें:

Watch/read a growing log file

वैकल्पिक रूप से, तुम इतनी तरह system के माध्यम से आदेश चला सकता है:

system('tail -f filename') 

अंतर यहाँ क्या है? कमांड के आउटपुट को वापस करने के बजाय, यह सच हो जाएगा (कमांड रन सफलतापूर्वक), झूठा (असफल) या शून्य (कमांड निष्पादन विफल)। इस तथ्य के कारण, आदेश का आउटपुट tail -f पर चलने वाले रिटर्न स्टेटमेंट पर रीडायरेक्ट नहीं किया गया है, यह सामग्री को मानक आउटपुट पर प्रिंट करेगा।

यदि आप मानक आउटपुट में परिणाम प्राप्त करने के ठीक हैं तो आप इसे केवल थ्रेड ब्लॉक में डाल सकते हैं। इस प्रकार filename की बढ़ती सामग्री मानक आउटपुट पर लिखी गई है और आप अन्य रूबी कोड निष्पादित करना जारी रख सकते हैं।

Thread.new { system('tail -f filename') } 

आप तो निम्नलिखित प्रश्न जो इस तरह के दृष्टिकोण का वर्णन करने के लिए इस सवाल का जवाब पर एक नजर है पूरा नियंत्रण है, ताकि अपनी स्क्रिप्ट का एक और बिंदु पर पुनः प्राप्ति के लिए यह स्टोर करने के लिए में उत्पादन पर कब्जा करना चाहते हैं:

Continuously read from STDOUT of external process in Ruby

यह जो बनाता है और छद्म टर्मिनल का प्रबंधन करता है PTY मॉड्यूल पर आधारित है। मूल रूप से आप इस मॉड्यूल के माध्यम से एक और टर्मिनल पैदा कर सकते हैं। कोड तब ऐसा दिखाई दे सकता था:

require 'pty' 
cmd = "tail -f filename" 
begin 
    PTY.spawn(cmd) do |stdin, stdout, pid| 
    begin 
     # Do something with the output here: just printing to demonstrate it 
     stdin.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 

अंत में, एक सॉकेट दृष्टिकोण भी है। बैश में सॉकेट खोलें या socat का उपयोग करके, tail -f के आउटपुट को सॉकेट में पाइप करें और सॉकेट से रूबी में पढ़ें।

+0

के लिए एक डमी है आपकी पोस्ट एक गड़बड़ है और यह बताती है कि ऐसा क्यों होता है इसके बजाय क्या होता है। ओप पहले ही जानता है कि क्या होता है। Downvoted। जो लोग आपकी पोस्ट को ऊपर उठाते हैं उन्हें समझाया जाना चाहिए कि उन्होंने इसे क्यों उठाया। आपका तर्क इस तरह कुछ चला जाता है: यदि आप एक आदेश निष्पादित करते हैं जो मान वापस नहीं करता है, तो यह stdout पर नहीं लिख सकता है; लेकिन यदि आप एक आदेश को निष्पादित करने के लिए रूबी की सिस्टम() विधि का उपयोग करते हैं जो मान वापस नहीं करता है, तो यह stdout को लिख देगा। है ना? – 7stud

+0

मैंने किसी भी तरह से नहीं कहा है, कि यदि आप एक आदेश निष्पादित करते हैं जो कोई मान वापस नहीं करता है तो यह stdout पर नहीं लिख सकता है। इसके अलावा मैं इस सवाल से नहीं देखता कि ओपी पहले से क्या जानता है और वह क्या नहीं जानता। हालांकि टिप्पणी के लिए धन्यवाद, मैं फॉर्मूलेशन में सुधार करने की कोशिश करूंगा। –

+0

प्लैटज़िस्च ने लिखा: _ समाप्ति के बिना कोई वापसी मूल्य नहीं दिया जाएगा और इसलिए कुछ भी मुद्रित नहीं किया गया है ._ इसका क्या अर्थ है? या इसे एक और तरीके से रखने के लिए, एक कमांड का रिटर्न वैल्यू या इसके अभाव से संबंधित है कि कोई आदेश stdout पर लिख सकता है या नहीं? – 7stud

0

कारण यह काम नहीं कर रहा है क्योंकि बैकटीक्स अलग-अलग System कॉल को बैकटिक्स के भीतर चलाने के लिए अलग करते हैं। यदि आप ps aux | grep tail करते हैं, तो आप देख पाएंगे कि पूंछ प्रक्रिया वास्तव में चल रही है।

कोड कोई आउटपुट नहीं दिखा रहा है क्योंकि पूंछ को समाप्त करने और अगले बयान में आगे बढ़ने की प्रतीक्षा है - यह लटका नहीं है क्योंकि यह पूंछ कमांड के आउटपुट को प्रदर्शित कर रहा है।

सामान्य ऑपरेशन में भी, आपको tail -f कमांड के आउटपुट को बंद करने के लिए ctrl+C करना होगा। फ़ाइल बढ़ने के साथ -f का उपयोग संलग्न डेटा को आउटपुट करने के लिए किया जाता है, और इसलिए tail -f चल रहा है। ps aux | grep tail से पिड का उपयोग करके kill -9 <pid_of_tail> करने का प्रयास करें। फिर आपके रूबी कोड का शेष भाग परिणाम को आउटपुट करना शुरू कर देगा।

ls, tail without -f कॉल कॉल करते हैं क्योंकि वे स्वयं को समाप्त करते हैं।

आप रूबी से एक पूंछ करने में रुचि रखते हैं, तो आप इस file-tail मणि http://flori.github.io/file-tail/doc/index.html

1

1 पर एक नजर है सकते हैं) बैकटिक डॉक्स के अनुसार,

`cmd` 
Returns the standard output of running cmd in a subshell. 

तो अगर आप लिखें:

puts `some command` 

तब रूबी को कुछ कमांड आउटपुट प्रिंट करना चाहिए।

2) पूंछ आदमी पृष्ठों के अनुसार:

The tail utility displays the contents of file...to the standard 
output. 

लेकिन आदेश:

puts `tail -f some_file` 

इस तथ्य के बावजूद कुछ भी प्रिंट यह नहीं है कि चल रहा है:

$ tail -f some_file 

भेजता है मानक आउटपुट के लिए आउटपुट। पूंछ आदमी पृष्ठों को भी

The -f option causes tail to not stop when 
end of file is reached, but rather to wait 
for additional data to be appended to the 
[the file]. 

का कहना है कि क्या मतलब है? और यह समस्या के लिए कैसे प्रासंगिक है?

क्योंकि कार्यक्रम चलाने:

puts `tail -f some_file` 

... रुक जाता है और उत्पादन के लिए कुछ भी नहीं है, तो आप अनुमान लगा सकते हैं कि बैकटिक विधि कमान की पूरे उत्पादन पर कब्जा करने की कोशिश कर किया जाना चाहिए। दूसरे शब्दों में, बैकटिक्स विधि कमांड के मानक आउटपुट से लाइन द्वारा लाइन नहीं पढ़ती है, यानी लाइन उन्मुख इनपुट। इसके बजाए, बैकटिक्स विधि फ़ाइल उन्मुख इनपुट को पढ़ती है, यानी एक समय में एक फ़ाइल। और क्योंकि tail -f some_file कमांड मानक आउटपुट को कभी भी समाप्त नहीं करता है, बैकटिक्स विधि फ़ाइल के अंत को कभी नहीं पढ़ती है, और यह तब तक लटकती है जब यह ईओफ़ की प्रतीक्षा करती है।

3) हालांकि, कमांड के आउटपुट को पढ़ने के लिए एक ही समय एक फ़ाइल को पर एक फ़ाइल पढ़ने का एकमात्र तरीका नहीं है। आप popen():

my_prog का उपयोग कर एक समय में कमांड के आउटपुट को एक पंक्ति भी पढ़ सकते हैं।rb:

IO.popen('tail -f data.txt') do |pipe| 
    while line = pipe.gets do #gets() reads up to the next newline, then returns 
    puts line 
    end 
end 


--output(terminal window 1):-- 
$ ruby my_prog.rb 
A 
B 
C 
<hangs> 

--output(terminal window 2):-- 
echo 'D' >> data.txt 

--output(terminal window 1):-- 
A 
B 
C 
D 
<hangs> 

गूंज आदमी पृष्ठों:

The echo utility writes any specified operands...followed 
by a newline (`\n') character. 
+0

एक आकर्षण धन्यवाद की तरह काम किया :) – Faizan

संबंधित मुद्दे