एक नामित पाइप के लिए स्वचालित ईओएफ को रोकें, और जब मैं चाहता हूं तो एक ईओएफ भेजें


12

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

#!/bin/sh
mkfifo P
program < P & : # Run in background
# < P tail -n +1 -f | program
echo some stuff > P # Prevent EOF?
cat more_stuff.txt > P # Prevent EOF?
send_eof > P # How can I do this?
# fg

जवाबों:


13

जैसा कि दूसरों ने संकेत दिया है, एक पाइप के पाठक को ईओएफ प्राप्त होता है, जब कोई लेखक नहीं बचा है। तो समाधान यह सुनिश्चित करने के लिए है कि हमेशा एक लेखक इसे खुला रखे। उस लेखक को कुछ भी भेजने की जरूरत नहीं है, बस उसे खुला रखें।

चूंकि आप एक शेल स्क्रिप्ट का उपयोग कर रहे हैं, इसलिए सबसे सरल उपाय यह है कि शेल को लिखने के लिए पाइप खोलने के लिए कहा जाए। और फिर इसे बंद कर दें जब आप कर लें।

#!/bin/sh
mkfifo P
exec 3>P # open file descriptor 3 writing to the pipe
program < P
# < P tail -n +1 -f | program
echo some stuff > P
cat more_stuff.txt > P
exec 3>&- # close file descriptor 3

ध्यान दें कि यदि आप अंतिम पंक्ति को छोड़ देते हैं, तो फ़ाइल डिस्क्रिप्टर 3 स्वचालित रूप से बंद हो जाएगा (और इस प्रकार पाठक ईओएफ प्राप्त करता है) जब स्क्रिप्ट आती है। सुविधा से अलग, यह भी एक प्रकार की सुरक्षा प्रदान करता है यदि स्क्रिप्ट किसी तरह जल्दी समाप्त करने के लिए थी।


2
इस exec 3>Pकारण से हैश में है, क्यों?
वांग

@ यह नहीं होना चाहिए। यदि ऐसा होता है, तो आप संभवतः प्रश्न में POC कोड के समान कार्य नहीं कर रहे हैं। एकमात्र कारण मैं सोच सकता हूं कि यह ब्लॉक होगा यदि आप इसके बजाय कुछ कर रहे हैं exec 2>P, और आपके पास ट्रेस मोड चालू है ( set -x), जिसमें बैश पाइप पर लिखने जा रहा है, लेकिन कोई पाठक नहीं है, इसलिए यह इंतजार करना बंद कर देता है कुछ पढ़ना है।
पैट्रिक

1
@Wang @Patrick वास्तव exec 3>Pमें मेरी मशीन पर भी लटका हुआ है। इसका कारण यह है कि वहाँ से पढ़ने की कोई प्रक्रिया नहीं है P। इस प्रकार, समाधान लाइनों को स्वैप करना था exec 3>Pऔर program < P &(एम्परसैंड को जोड़ना ताकि कार्यक्रम पृष्ठभूमि में चलता हो)।
मैकिस्क

2

अंतिम लेखक के चले जाने पर एक पाइप EOF प्राप्त करता है। इससे बचने के लिए, सुनिश्चित करें कि हमेशा एक लेखक होता है (एक प्रक्रिया जिसमें लेखन के लिए पाइप खुला होता है, लेकिन वास्तव में कुछ भी नहीं लिखता है)। ईओएफ भेजने के लिए, उस आरक्षित लेखक को हटा दें।

mkfifo P
while sleep 1; do :; done >P &
P_writer_pid=$!
send_eof_to_P () {
  kill $P_writer_pid
}

0

ईओएफ के बीच अंतर करने के कार्यक्रम का कोई तरीका नहीं है, जिसका अर्थ है "यह छोड़ने का समय है" और एक ईओएफ का मतलब है कि "एक लेखक किया जाता है, लेकिन किसी और से अधिक इनपुट हो सकता है"।

यदि आपके पास अपने कार्यक्रम के व्यवहार को संशोधित करने की क्षमता है, तो एक अनंत लूप में रीडिंग करें (एक पुनरावृत्ति ईओएफ तक रहता है) और इसे एक विशिष्ट कमांड स्ट्रिंग भेजें जिसका अर्थ है "छोड़ने का समय"। उस तार को भेजना send_eofआपके प्रश्न में कमांड का काम होगा ।

एक अन्य विकल्प:

( echo some stuff; cat more_stuff.txt ) >P

या

{ echo some stuff; cat more_stuff.txt; } >P
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.