एकल पाइप वाली कमांड के लिए पाइफ़ेल सेट करना


19

मुझे नॉन-बैश स्क्रिप्ट (जैसे PHP स्क्रिप्ट) से कई पाइप किए गए शेल कमांड को निष्पादित करने की आवश्यकता है:

command1 | command2 | command3

ताकि, यदि command1गैर-शून्य निकास कोड के साथ विफल हो जाए, तो एक-दूसरे कमांड भी विफल हो जाते हैं। अब तक, मैं जो भी लेकर आया हूं वह है:

set -o pipefail && command1 | command2 | command3

लेकिन भले ही यह टर्मिनल से ठीक चलता है, यह स्क्रिप्ट से निष्पादित होने पर इसका उत्पादन करता है:

श: 1: सेट: अवैध विकल्प -o पिपीफेल


ऐसा प्रतीत होता है कि /bin/shपसंद नहीं है set -o pipefail। क्या यह वास्तव bashमें भेस में है, या यह एक अलग शेल है? जब bashइसे चलाया जाता है /bin/sh, तो क्या यह स्वीकार किया जाता है set -o pipefail?
जोनाथन लेफ़लर

@JonathanLeffler जब मैं /bin/sh set -o pipefailइसे चलाता हूं तो यही कहता है /bin/sh: 0: Can't open set(साथ वाली बात sudo)। आशा है कि मैंने सही परीक्षण किया। प्रणाली उबंटू 12 है
डेसमंड ह्यूम

आपको प्रयास करने की आवश्यकता होगी /bin/sh -c "set -o pipefail"; जैसा कि यह था, शेल वर्तमान निर्देशिका में एक स्क्रिप्ट को निष्पादित करने की कोशिश कर रहा था जिसे बुलाया setगया था और इसे नहीं मिला।
जोनाथन लेफ़लर

@JonathanLeffler /bin/sh -c "set -o pipefail"हालांकि काम नहीं कर रहा bash -c "set -o pipefail"है।
डेसमंड ह्यूम

तो, आपकी समस्या यह है कि स्क्रिप्ट को चलाया जाता है /bin/shजिसके द्वारा पहचान नहीं होती है set -o pipefail। नतीजतन, आपको यह सुनिश्चित करने की आवश्यकता होगी कि स्क्रिप्ट /bin/bashइसके बजाय चलाया जाता है /bin/sh। या, यदि आप आश्वस्त हैं, बहादुर हैं - और शायद मूर्ख - जो भी वर्तमान में या की एक प्रति से जुड़ा हुआ है, जो भी खोल के बजाय /bin/shएक लिंक, या की /bin/bashप्रतिलिपि हो। यदि आप सुनिश्चित करें कि कि /bin/shहै bash, तो आप व्यवहार जो प्रयोग कर रहे हैं bashजब के रूप में चलाने का खुलासा नहीं करता /bin/sh; के bashरूप में उपयोग करें bash
जोनाथन लेफ्लर

जवाबों:


18

बैश कमांड लाइन से आपको pipefailबाद में सेट होने से बचने के लिए एक उपखंड को आमंत्रित करना होगा :

$ (set -o pipefail && command1 | command2 | command3)

यह pipefailकोष्ठक द्वारा बनाए गए उपधारा के विकल्प के प्रभाव को सीमित करेगा (...)

एक वास्तविक उदाहरण:

$ (set -o pipefail && false | true) && echo pipefail inactive || echo pipefail active
pipefail active

यदि आप उस -cविकल्प के साथ एक स्पष्ट शेल कॉल का उपयोग करते हैं, जिसके लिए आपको उप-संस्करण की आवश्यकता नहीं है, या तो bashएक shउपनाम के साथ bash:

$ bash -c "set -o pipefail && false | true" && echo pipefail inactive || echo pipefail active
pipefail active
$ sh -c "set -o pipefail && false | true" && echo pipefail inactive || echo pipefail active
pipefail active

चूंकि आपका विकल्प shस्वीकार नहीं करता है pipefail, इसलिए मुझे यह मान लेना होगा कि यह या तो कुछ पुराना या संशोधित संस्करण है bash- या यह वास्तव में पूरी तरह से कुछ खोल है।


1
है $पहले टुकड़े में आदेश का एक हिस्सा है कि यह सिर्फ एक सुरक्षा प्रॉम्प्ट? दोनों तरह से कोशिश की, वास्तव में काम नहीं किया। जिस bash -cतरह से हमेशा काम करता है, बहुत सुंदर नहीं ..
डेसमंड ह्यूम

6

निश्चित नहीं है कि इसका उल्लेख ऊपर क्यों नहीं किया गया, लेकिन इसका pipefailउपयोग करके स्पष्ट रूप से परेशान होना संभव है set +o pipefail

set -o pipefail
command1 | command2 | command3
set +o pipefail

यदि आप किसी खंड को निष्पादित कर रहे हैं, और pipefailपहले से ही सेट के बारे में अनिश्चित हैं , तो आप पहले सुझाए गए के साथ इसका उपयोग कर सकते हैं:

# explicitly execute with pipefail set
(set -o pipefail ; command1 | command2 | command3 )
# explicitly execute with pipefail unset
(set +o pipefail ; command1 | command2 | command3 )

0

आप $ के साथ संयुक्त $ (कमांड 1) का उपयोग कर सकते हैं? :

a=$(echo "a")
[ $? -eq 0 ] && b=$(echo $a"b")
[ $? -eq 0 ] && c=$(echo $b"c")
echo $c

प्रिंट "एबीसी"

a=$(ls unexitingDir)
[ $? -eq 0 ] && b=$(echo $a"b")
[ $? -eq 0 ] && c=$(echo $b"c")
echo $c

प्रिंट ""।

"[$ -eq 0] &&" का अर्थ है कि निम्नलिखित आदेश को केवल तभी निष्पादित किया जाता है जब पिछले एक ने सुसाइड किया हो।

यह आपके प्रश्न का उत्तर नहीं देगा, लेकिन यह आपकी समस्या का समाधान है।


क्या इसका मतलब है कि मुझे हमेशा प्रत्येक कमांड के आउटपुट को एक चर में संग्रहीत करने की आवश्यकता होगी?
डेसमंड ह्यूम

हमेशा मुझे नहीं पता, लेकिन मेरे समाधान के साथ हाँ आप करेंगे (यदि आपको अपने अगले आदेश के लिए इसकी आवश्यकता है)। जब तक आप सिर्फ लिख नहीं सकतेcommand1 && command2 && command3
cglacet
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.