कैसे BIP स्क्रिप्ट में PIPESTATUS और आउटपुट दोनों प्राप्त करें


9

मैं इस कमांड के साथ फाइल की अंतिम संशोधन तिथि प्राप्त करने का प्रयास कर रहा हूं

TM_LOCAL=`ls -l --time-style=long-iso ~/.vimrc | awk '{ print $6" "$7 }'`

इस लाइन के निष्पादन के बाद TM_LOCAL का "2012-05-16 23:18" जैसा मूल्य है

मैं यह देखने के लिए भी जाँच करना चाहूंगा कि क्या कोई त्रुटि थी। उदाहरण के लिए, यदि फ़ाइल मौजूद नहीं है, तो lsरिटर्न 2. लेकिन $?मान 0 है क्योंकि इसमें रिटर्न वैल्यू है awk

अगर मैं इस कमांड को अकेले चलाऊं, तो मैं एलएस के रिटर्न वैल्यू को देखकर जांच कर सकता हूं ${PIPESTATUS[0]}

ls -l --time-style=long-iso ~/.vimrc | awk '{ print $6" "$7 }'

लेकिन $PIPESTATUSकाम नहीं करता है जैसा कि मैंने उम्मीद की है अगर मैं पहले उदाहरण के रूप में एक चर को आउटपुट असाइन करता हूं। इस स्थिति में, $PIPESTATUSसरणी में केवल 1 तत्व होता है जो समान है$?

तो, सवाल यह है कि मैं दोनों को कैसे प्राप्त कर सकता हूं $PIPESTATUSऔर एक ही समय में एक चर को आउटपुट असाइन कर सकता हूं ?

जवाबों:


8

आप ऐसा कर सकते हैं:

TM_LOCAL=$(ls -l --time-style=long-iso ~/.vimrc | \
             awk '{ print $6" "$7 }' ; exit ${PIPESTATUS[0]} )

फिर $?से रिटर्न कोड होगा ls। यह काम नहीं करता है यदि आपको पाइप के एक से अधिक भागों से रिटर्न कोड की आवश्यकता होती है (लेकिन आप पाइपलाइन को विभाजित कर सकते हैं यदि आउटपुट बहुत बड़ा नहीं है, जैसा कि यहां है)।

यहाँ पूर्ण PIPESTATUSसरणी और आउटपुट प्राप्त करने का एक महंगा तरीका है । बहुत सुंदर नहीं है, लेकिन कुछ और नहीं मिला है:

result=$(echo -e "a\nb\nc" | \
          ( cat ; exit 1 ) | \
          ( cat ; exit 42 ) ; echo ${PIPESTATUS[@]})
output=$(head -n -1 <<< "$result")
status=($(tail -n 1 <<< "$result"))
echo "Output:"
echo "$output"
echo "Results:"
echo "${status[@]}"

जो देता है:

Output:
a
b
c
Results:
0 1 42

मेरे मामले में यह काम करता है, लेकिन मैं अभी भी इस बारे में उत्सुक हूं कि क्या पूरा पिपेस्टैटस सरणी और आउटपुट प्राप्त करने का एक तरीका है।
मुस्तफा सेरदार lanlı

3

उपयोग set -o pipefailमें bashके रूप में एक पाइप कमांड अनुक्रम में एकदम दाएँ गैर शून्य से बाहर निकलें कोड प्राप्त करने के $?। से man bash:

यदि सेट किया जाता है, तो पाइप लाइन का रिटर्न वैल्यू गैर-शून्य स्थिति के साथ बाहर निकलने के लिए अंतिम (सबसे दाएं) कमांड का मूल्य है, या यदि पाइप लाइन से सभी कमांड सफलतापूर्वक बाहर निकलते हैं। डिफाल्ट रूप में यह विकल्प निष्क्रिय है।

तब आप बस पहुंच सकते हैं $?set +o pipefailफिर से अक्षम करने के लिए उपयोग करें।


2

मैं मानती हूं कि यहां मुद्दा यह है कि जैसे ही आप एक कमांड निष्पादित करते हैं, PIPESTATUS पूरी तरह से चला जाता है। आप bash संस्करण 2 या इसके बाद के संस्करण में संपूर्ण PIPESTATUS सरणी प्राप्त कर सकते हैं:

declare -a status
status=(${PIPESTATUS[@]})

पहुँच तब ${status[0]}, ${status[1]}आदि


2

"आप क्या उम्मीद करते हैं" के साथ मुख्य समस्या यह है कि बैकक्वाट्स में एक कमांड को एक सबशेल में निष्पादित किया जाता है; $PIPESTATUSवहाँ मौजूद है और स्थिति वहाँ से लौटी है यह उसी नियमों का पालन करता है जैसे कि आपने एक निष्पादन योग्य (या शेल स्क्रिप्ट) निष्पादित किया है। Backquote कमांड की स्थिति सबसे सही ( awk) स्थिति है।

@ डैनियल बेक ने जो कहा, उसे लागू करने के लिए , pipefailइस प्रकार से उप-भाग में विकल्प सेट करें :

TM_LOCAL=`set -o pipefail; ls -l --time-style=long-iso ~/.vimrc | awk '{ print $6" "$7 }'` अब $?बाद में संग्रहीत स्थिति ls(यदि गैर-शून्य) की स्थिति होगी ।

हालांकि, मुझे लगता है कि एक स्पष्ट if [ -f ~/.vimrc ];... परीक्षण अधिक पठनीय होगा।

आप एक चर में उत्पादन प्राप्त नहीं कर सकते हैं और PIPESTATUSपूर्व के लिए एक अस्थायी फ़ाइल के बिना वापस आ गए, या बाद वाले को स्ट्रिंग में marshalling कर सकते हैं।


0

मैं ईमेल फ्रॉन क्रोन तभी भेजना चाहता था, जब निकास की स्थिति शून्य न हो

चाल यह है कि पाइपलाइन के अंत के लिए स्टैडिन प्राप्त करने के लिए आपको इसे एक उपधारा में डालने की आवश्यकता है - लेकिन यह PIPESTATUS मान को छिपाने के लिए लगता है ...

परीक्षण क्रोन कुछ आउटपुट को बाहर निकालता है और 1 या 0 के साथ बाहर निकलता है।

./testcron | (test ${PIPESTATUS[0]} -ne 0 || mail -s "testcron output" paul)

अद्यतन: पाइपलाइन आदेश तब तक दिखाई नहीं देता है जब तक पाइपलाइन कमांड प्रक्रिया नहीं होती है


0

एक विकल्प यह है कि कॉल के साथ अपने संशोधन समय प्राप्त करने से पहले अपनी फ़ाइल के अस्तित्व की जांच करें stat। चूंकि statआप टाइमस्टैम्प में थोड़ा अधिक चाहते हैं, इसलिए आप पैरामीटर विस्तार का उपयोग करके इसे ट्रिम कर सकते हैं।

GNU stat(जैसे लिनक्स पर) के साथ, आप चला सकते हैं:

[[ -f ~/.vimrc ]] && TM_LOCAL=$(stat -c '%y' ~/.vimrc 2>/dev/null)
TM_LOCAL=${TM_LOCAL%:*}  # Safe to do, even if stat fails

मैक ओएस एक्स और अन्य बीएसडी सिस्टम पर, statसिंटैक्स भिन्न होता है और एक समय प्रारूप निर्दिष्ट कर सकता है:

[[ -f ~/.vimrc ]] && TM_LOCAL=$(stat -f '%Sm' -t '%Y-%m-%d %H:%M' ~/.vimrc 2>/dev/null)

अब जीएनयू जवाब क्या है, आप कहते हैं कि परिवर्तन $TM_LOCALसुरक्षित है। यह केवल तभी सुरक्षित है जब आपको यह उम्मीद थी कि इसका पूर्व मूल्य नहीं है। मान लें कि मूल्य पहले था 2020-02-27 17:14और कोई ~/.vimrcफ़ाइल नहीं है। तुम तो होगा 2020-02-27 17। इसलिए मैं उन दो लाइनों को एक अतिरिक्त &&(या अधिमानतः इतना सुपाठ्य नहीं है) के साथ एक ifछंद का उपयोग करता हूं।
एडम काट्ज
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.