2014-04-15 7 views
5

मैं फीफो के साथ कुछ आसान करने की कोशिश कर रहा था: रेखाएं पढ़ें, लेकिन सभी एक बार में नहीं, और यह अप्रत्याशित रूप से "काम नहीं किया"।एक शेल स्क्रिप्ट में mkfifo का उपयोग करके

यह ठीक है:

$ f=$(mktemp -u) 
$ mkfifo $f 
$ { seq 5 > $f; } & 
[1] 2486 
$ while read line; do echo $line; done < $f 
1 
2 
3 
4 
5 
[1]+ Done     { seq 10 > $f; } 

लेकिन अगर मैं लाइनों को पढ़ने के एक-एक करके की कोशिश, पहले पढ़ने सफल होता है और 2 पढ़ने रुक जाता है।

$ { seq 5 > $f; } & 
[1] 2527 
$ read line < $f; echo $line 
1 
[1]+ Done     { seq 5 > $f; } 
$ read line < $f; echo $line 
[hangs here...] 

क्या कोई इसे समझा सकता है? मैं सभी 5 लाइनों को एक-एक करके क्यों नहीं पढ़ सकता? शेष डेटा के साथ क्या हुआ?


मुझे पता चला मैं पंक्ति-दर-पंक्ति अगर मैं एक फ़ाइल विवरणक बनाने फीफो रीडायरेक्ट करने के लिए पढ़ सकते हैं:

$ { seq 5 > $f; } & 
[1] 2732 
$ exec 3<$f 
[1]+ Done     { seq 5 > $f; } 
$ read -u 3 line && echo $line || echo no more data 
1 
$ read -u 3 line && echo $line || echo no more data 
2 
$ read -u 3 line && echo $line || echo no more data 
3 
$ read -u 3 line && echo $line || echo no more data 
4 
$ read -u 3 line && echo $line || echo no more data 
5 
$ read -u 3 line && echo $line || echo no more data 
no more data 
$ exec 3<&- 

मैं अभी भी मध्य परिदृश्य समझ में नहीं आता। क्या कोई समझा सकता है?


संस्करण जानकारी:

$ bash --version 
GNU bash, version 4.2.25(1)-release (i686-pc-linux-gnu) 
Copyright (C) 2011 Free Software Foundation, Inc. 
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> 

This is free software; you are free to change and redistribute it. 
There is NO WARRANTY, to the extent permitted by law. 
$ mkfifo --version 
mkfifo (GNU coreutils) 8.13 
Copyright (C) 2011 Free Software Foundation, Inc. 
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>. 
This is free software: you are free to change and redistribute it. 
There is NO WARRANTY, to the extent permitted by law. 

Written by David MacKenzie. 
+0

यह संस्करण और बैश बनाम ksh या ?? से संबंधित हो सकता है।क्या आप वह जानकारी जोड़ सकते हैं। (मुझे किसी भी मामले में जवाब नहीं पता होगा ;-()। इस तिमाही में सबसे दिलचस्प सवाल! – shellter

+0

ओएसएक्स मैवरिक्स और उबंटू वर्चुअलबॉक्स पर बिल्कुल वही व्यवहार। –

+0

आपका तीसरा परिदृश्य repro'd नहीं किया जा सकता है। – devnull

उत्तर

5

मुझे लगता है कि क्या होता है यह है:

$ read line < $f, पढ़ने के लिए फीफो खोलता है एक पंक्ति पढ़ता है, तो फीफो बंद कर देता है। एक बार पाठक अपनी तरफ फीफो बंद कर देता है, लेखक (seq 5 > $f) भी बंद हो जाता है। जब आप अगली बार फीफो खोलते हैं तो उस समय कोई भी इसे लिखता नहीं है, इसलिए read ब्लॉक।

while के साथ FIFO while आदेश समाप्त होने तक पढ़ने के लिए खुला है, लेखक को फीफो को और लाइनें भेजने की अनुमति देता है।

आप lsof -p $$ का उपयोग यह सत्यापित करने के लिए कर सकते हैं कि प्रत्येक बिंदु पर कौन सी फ़ाइलें खुली हैं (नहीं)।

+1

धन्यवाद। मुझे लगता है कि जीएनयू जानकारी पृष्ठ कहता है: "एक प्रक्रिया फीफो खोलती है लेखन के लिए फ़ाइल, और दूसरा पढ़ने के लिए "- जो आप कहते हैं उसका अर्थ है। –

2

ऐसा लगता है कि यहां FIFO के बारे में कुछ भ्रम है।

आप जब कहते हैं:

read line < $f 

यह,, फीफो खोलने चाहते हैं की तलाश पढ़ा है, और बंद करने के बाद यह के साथ किया जा। इससे कोई फ़र्क नहीं पड़ता कि आप एक रेखा या संपूर्ण डेटा पढ़ते हैं या नहीं।

तो जब आप फिर से पढ़ने का प्रयास करते हैं, तो read प्रतीक्षा करता रहता है।

यह इंतजार कर रहा है, वहीं कहकर देखें:

echo foo > $f 

और तुम नोटिस चाहते हैं कि read सफल रहा है।

यदि आप दोनों मामलों में सिस्टम कॉल की निगरानी कर रहे थे, तो आप देखेंगे कि दूसरा read फीफो से पढ़ने का इंतजार कर रहा है।

सुनिश्चित नहीं है कि आप यहां क्या हासिल करने की कोशिश कर रहे हैं लेकिन आपका अवलोकन अपेक्षाकृत लाइनों के साथ काफी अधिक है।

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