किसी zsh पाइपलाइन को किसी भी चरण से विफलता की रिपोर्ट करने के लिए, इसे चलाने से पहले PIPE_FAIL विकल्प को सक्षम करें। Mac पर Terminal में, setopt PIPE_FAIL दर्ज करें; किसी स्क्रिप्ट में, उस पंक्ति को पाइपलाइन से पहले रखें। इसके बाद पाइपलाइन अपने सबसे दाईं ओर के विफल कमांड का निकास स्थिति कोड लौटाती है, या यदि प्रत्येक कमांड सफल होती है तो शून्य लौटाती है। यदि बाद के कमांड्स द्वारा उस परिणाम को बदला नहीं जाना चाहिए, तो पाइपलाइन के तुरंत बाद $? को कैप्चर करें। The zsh options manual इस व्यवहार का दस्तावेजीकरण करता है।

एक विफल पाइपलाइन सफल क्यों दिख सकती है

डिफ़ॉल्ट रूप से, zsh किसी पाइपलाइन को उसके अंतिम कमांड का निकास स्थिति कोड देता है। इसलिए यदि कोई पिछला कमांड विफल हो जाता है लेकिन अंतिम कमांड सफल हो जाता है, तो पूरी पाइपलाइन सफल दिखाई दे सकती है। उदाहरण के लिए, नीचे दिया गया अंतिम cat तब भी सफल हो सकता है जब grep को कोई मेल खाने वाली पंक्ति नहीं मिलती है:

printf '%s\n' 'ready' | grep 'missing' | cat
print -r -- $?

zsh मैनुअल एक पाइपलाइन को | द्वारा जोड़े गए कमांड्स के रूप में परिभाषित करता है और कहता है कि इसका मान सामान्यतः अंतिम कमांड का मान होता है। शून्य स्थिति का अर्थ सफलता है; गैर-शून्य स्थिति का अर्थ है कि कमांड या पाइपलाइन ने विफलता की सूचना दी है। The zsh pipeline documentation डिफ़ॉल्ट नियम का वर्णन करता है।

पाइपलाइन के लिए PIPE_FAIL सक्षम करें

Terminal सत्र में, कमांड चलाने से पहले विकल्प सेट करें:

setopt PIPE_FAIL
printf '%s\n' 'ready' | grep 'missing' | cat
print -r -- $?

अब अंतिम स्थिति गैर-शून्य है क्योंकि cat के सफल होने के बावजूद grep विफल रहा। PIPE_FAIL पाइपलाइन में सबसे दाईं ओर की गैर-शून्य स्थिति का उपयोग करता है। यह विफलता को सार्थक बनाए रखता है और साथ ही zsh द्वारा चयनित वास्तविक स्थिति कोड भी लौटाता है। उसी सत्र में इस व्यवहार को फिर से बंद करने के लिए, unsetopt PIPE_FAIL चलाएं।

किसी स्क्रिप्ट के लिए, विकल्प को शीर्ष के पास, इंटरप्रेटर पंक्ति के बाद और किसी भी प्रभावित पाइपलाइन से पहले रखें:

#!/bin/zsh
setopt PIPE_FAIL

printf '%s\n' 'ready' | grep 'missing' | cat
pipeline_status=$?

if (( pipeline_status != 0 )); then
  print -u2 -- "Pipeline failed with status $pipeline_status"
  exit "$pipeline_status"
fi

स्पष्ट स्थिति असाइनमेंट महत्वपूर्ण है: $? का अर्थ अंतिम कमांड की स्थिति है, इसलिए बाद का print, वेरिएबल-संबंधी कमांड या कंडीशनल इसके द्वारा रिपोर्ट किए जाने वाले मान को बदल सकता है। मान को तुरंत सहेजने से स्क्रिप्ट अन्य कार्यों के बाद इसे रिपोर्ट कर सकती है या इसके साथ बाहर निकल सकती है। यह उदाहरण उस प्रोग्राम को एक विफल स्थिति लौटाता है जिसने स्क्रिप्ट लॉन्च की थी; यह किसी पिछले चरण के विफल होते ही अलग-अलग पाइपलाइन कमांड्स को चलने से नहीं रोकता है।

जब आपको प्रत्येक चरण के परिणाम की आवश्यकता हो, तो pipestatus का उपयोग करें

PIPE_FAIL पाइपलाइन का सारांश प्रस्तुत करता है। यदि आपको यह भी पहचानना है कि किस कमांड ने कौन सा कोड लौटाया है, तो zsh विशेष ऐरे pipestatus प्रदान करता है, जिसमें पिछली पाइपलाइन के प्रत्येक कमांड की स्थिति होती है। इसे तुरंत पढ़ें, क्योंकि दूसरी पाइपलाइन उन मानों को बदल देती है। The zsh parameter reference इस ऐरे का दस्तावेजीकरण करता है।

printf '%s\n' 'ready' | grep 'missing' | cat
print -r -- "Stage statuses: ${pipestatus[*]}"

इस तीन-कमांड वाले उदाहरण के लिए, आउटपुट printf के लिए शून्य, grep के लिए एक गैर-शून्य मान और cat के लिए शून्य दिखाता है। सटीक गैर-शून्य कोड कमांड पर निर्भर करता है। यदि आपको समग्र परिणाम और प्रत्येक चरण के परिणाम दोनों की आवश्यकता है, तो PIPE_FAIL का उपयोग करें और तुरंत समग्र $? को कैप्चर करें; चरणों का निदान करते समय एक अलग पाइपलाइन चलने के तुरंत बाद pipestatus का निरीक्षण करें, या स्क्रिप्ट को पहले ऐरे को रिकॉर्ड करने और उस सहेजे गए डेटा से वांछित समुच्चय की गणना करने के लिए डिज़ाइन करें। पाइपलाइन और उस स्थिति के बीच जिसे आप पढ़ना चाहते हैं, कोई अन्य कमांड या पाइपलाइन डालने से बचें।

सेटिंग को सही शेल में रखें

एक इंटरैक्टिव zsh सत्र में बाद के कमांड्स पर विकल्प लागू करने के लिए, उस सत्र में setopt PIPE_FAIL चलाएं। प्रत्येक नए zsh सत्र के लिए इसे सक्षम करने के लिए, पंक्ति को ~/.zshrc में जोड़ें, फिर एक नया Terminal विंडो खोलें या फ़ाइल को source ~/.zshrc के साथ सोर्स करें। Apple की Terminal गाइड zsh को डिफ़ॉल्ट शेल के रूप में पहचानती है, साथ ही यह भी नोट करती है कि सेटिंग्स या व्यवस्थापक एक अलग शेल का चयन कर सकते हैं। zsh-विशिष्ट सिंटैक्स पर निर्भर होने से पहले सक्रिय शेल की पुष्टि करें। Apple’s Terminal guide बताती है कि Terminal शेल का चयन कैसे करता है।

#!/bin/zsh से शुरू होने वाली स्क्रिप्ट सीधे zsh का अनुरोध करती है, चाहे Terminal के लिए कोई भी इंटरैक्टिव शेल कॉन्फ़िगर किया गया हो। यदि इसके बजाय स्क्रिप्ट किसी अन्य शेल द्वारा चलाई जाती है, तो setopt और pipestatus उस शेल के अपने पाइपलाइन नियंत्रणों के लिए पोर्टेबल विकल्प नहीं हैं। इंटरप्रेटर और सिंटैक्स को संरेखित रखें, फिर आगे का काम करने से पहले पाइपलाइन परिणाम को सुरक्षित रखें।

स्रोत