प्रतिध्वनि कि स्टोडर को आउटपुट


1113

क्या कोई मानक बैश उपकरण है जो गूंज की तरह कार्य करता है लेकिन स्टडआउट के बजाय स्टॉडर को आउटपुट करता है?

मुझे पता है कि मैं कर सकता हूं echo foo 1>&2लेकिन यह थोड़े बदसूरत है और, मुझे संदेह है, त्रुटि प्रवण (उदाहरण के लिए जब चीजें बदलती हैं तो संपादित गलत होने की संभावना अधिक होती है)।


जवाबों:


1450

आप ऐसा कर सकते हैं, जो पढ़ने की सुविधा प्रदान करता है:

>&2 echo "error"

>&2कॉपी विवरणक # 2 फाइल करने के लिए # 1 विवरणक फाइल करने के लिए। इसलिए, इस पुनर्निर्देशन के बाद, दोनों फ़ाइल डिस्क्रिप्टर एक ही फाइल को संदर्भित करेंगे: एक फाइल डिस्क्रिप्टर # 2 मूल रूप से संदर्भित था। अधिक जानकारी के लिए बैश हैकर्स इलस्ट्रेटेड रीडायरेक्शन ट्यूटोरियल देखें


2
मैं इस ट्रिक को कुछ समय पहले सीखता हूं। इस पेज पर इसकी कुछ अच्छी जानकारी है। tldp.org/LDP/abs/html/io-redirection.html
Marco Aurelio

46
@ BCS मुझे aliasशेल स्क्रिप्ट में ए का उपयोग करने के बारे में पता नहीं है । यह शायद उपयोग करने के लिए सुरक्षित होगाerrcho(){ >&2 echo $@; }
ब्रैडेन बेस्ट

3
> & 2 को आम तौर पर अंत में रखा जाता है। यह काम करेगा, लेकिन इसका कम बार उपयोग किया जाता है
इस्क्रेन इवोव चेर्नव

159
लगभग 40 वर्षों में मैं यूनिक्स जैसी प्रणालियों का उपयोग कर रहा हूं, यह मेरे लिए कभी नहीं हुआ है कि आप रीडायरेक्ट को कहीं भी डाल सकते हैं लेकिन अंत में। इसे इस तरह सामने रखना इसे और अधिक स्पष्ट बनाता है (या @MarcoAurelio के अनुसार "पढ़ने की सुविधा")। मुझे कुछ नया सिखाने के लिए +1।
हेफेस्टस

FYI करें: यदि आप स्ट्रिंग को प्रतिध्वनित करने के अलावा कुछ भी प्रारूपित या करना चाहते हैं तो आपको रीडायरेक्ट को अंत तक ले जाना होगा। उदाहरण के लिए errcho(){ >&2 echo $@|pr -To5;}काम नहीं करेगा। ऐसा कुछ करने के लिए आपको पिछले पाइप के बाद कहीं पुनर्निर्देशित करना होगा जैसे:errcho(){ echo $@|>&2 pr -To5;}
जॉन रेड

423

आप एक समारोह को परिभाषित कर सकते हैं:

echoerr() { echo "$@" 1>&2; }
echoerr hello world

यह स्क्रिप्ट की तुलना में तेज़ होगा और इसकी कोई निर्भरता नहीं होगी।

कैमिलो मार्टिन के बैश विशिष्ट सुझाव में "यहां स्ट्रिंग" का उपयोग किया गया है और जो कुछ भी आप इसे पास करेंगे, उसमें तर्क (एन) शामिल हैं, जो गूंज सामान्य रूप से निगल जाएगा:

echoerr() { cat <<< "$@" 1>&2; }

ग्लेन जैकमैन का समाधान भी तर्क निगलने की समस्या से बचा जाता है:

echoerr() { printf "%s\n" "$*" >&2; }

7
मुझे कहना होगा कि गूंज थोड़े अविश्वसनीय है। echoerr -ne xt"-ne xt" मुद्रित करने के लिए नहीं जा रहा है। उसके लिए बेहतर उपयोग printf
कैमिलो मार्टिन

10
ओह, आप वास्तव में बिल्ली का भी उपयोग कर सकते हैं:echoerr() { cat <<< "$@" 1>&2; }
कैमिलो मार्टिन

2
मुझे इसकी जानकारी नहीं थी। जोड़ा गया।
जेम्स रोथ

4
या,printf "%s\n" "$*" >&2
ग्लेन जैकमैन

4
@GKFX बेशक यह केवल उद्धृत करते समय सही ढंग से काम करता है। लोग अपने तार क्यों नहीं उद्धृत करते हैं यह मेरे से परे है। (जब आप उद्धृत नहीं करते हैं, तो एक या एक से अधिक $IFSव्हाट्सएप द्वारा अलग की गई हर चीज को एक अलग तर्क के रूप में भेजा जाता है, जिसका echoअर्थ है कि उन्हें 0x20एस के साथ मिलाना , लेकिन टाइप करने के लिए 2 कम वर्णों की सुविधा को दूर नहीं करने के खतरों को टाइप करने के लिए) ।
कैमिलो मार्टिन

252

चूंकि 1मानक आउटपुट है, आपको इसे किसी आउटपुट पुनर्निर्देशन के सामने स्पष्ट रूप से नाम नहीं देना है, >लेकिन इसके बजाय बस टाइप कर सकते हैं:

इको यह संदेश stderr> & 2 पर जाता है

चूँकि आप चिंतित लग रहे हैं कि 1>&2आपके लिए मज़बूती से टाइप करना मुश्किल होगा, इसलिए अतिरेक का उन्मूलन आपके 1लिए एक मामूली प्रोत्साहन हो सकता है!


59

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

echo foo >>/dev/stderr

4
क्या यह विकल्प पोर्टेबल है? किसी को पता है कि क्या यह कुछ यूनिक्स स्वाद के लिए काम नहीं कर रहा है?
दकाव

7
यह कुछ विशेष वर्णों में काम नहीं करता है, जो / dev / stderr का उपयोग नहीं कर सकता है।
ज़ाचरी वंस

12
यदि स्क्रिप्ट जो इस लाइन को निष्पादित करती है - चलो इसे कॉल करते हैं foo- का अपना स्वयं का स्टेदर पुनर्निर्देशित है - जैसे foo >foo.log 2>&1- तब echo foo >/dev/stderrइसके पहले सभी आउटपुट को क्लोब करेगा। >>इसके बजाय इस्तेमाल किया जाना चाहिए:echo foo >>/dev/stderr
doshea

इसी तरह, आपके पास है /dev/fd/2
जब्रुनी

@ डैकव यह सुनिश्चित पोर्टेबल के लिए है /proc/self/fd/2:। नीचे मेरा जवाब देखें :)
सेबस्टियन

31

नहीं, यह करने का मानक तरीका है। यह त्रुटियों का कारण नहीं होना चाहिए।


9
यह त्रुटियों का कारण नहीं होना चाहिए, लेकिन मुझे अधिक संभावना हो सकती है। OTOH यह एक बड़ी बात नहीं है।
बीसीएस

6
@ माइक डिसिमोन: यदि कोड के साथ कोई और गड़बड़ करता है, आउटपुट के आसपास फेरबदल करता है, और वास्तव में बैश नहीं जानता है, तो वे आसानी से (या गलत तरीके से) ड्रॉप कर सकते हैं 1>&2। हम सभी चाहते हैं कि ऐसा न हो, लेकिन मुझे यकीन है कि हम सभी ऐसे स्थान हैं जहाँ यह होता है।
कैस्केल

2
( echo something 1>&2 ; something else ) > log-> (echo something; cp some junk 1>&2 ; something else) > logउफ़।
बीसीएस

29
IMHO, अगर कोई कोड के साथ गड़बड़ी करता है और उसे पता नहीं है, तो यह आपकी समस्याओं का कम से कम हो सकता है।
माइक डीमोन

7
मुझे लगता है कि अगर यह एक मुद्दा होने की संभावना है, तो आपको एक अलग भाषा का उपयोग शुरू करना चाहिए: बैश को बेवकूफ बनाने की कोशिश करना एक मूर्खतापूर्ण उद्यम है।
intuited

17

यदि आपको संदेश को लॉग इन करने में कोई दिक्कत नहीं है, तो not_so_ugly तरीका है:

logger -s $msg

-S विकल्प का अर्थ है: "मानक त्रुटि के साथ-साथ सिस्टम लॉग में संदेश को आउटपुट करें।"


1
यह महान है! यह कितना पोर्टेबल है?
code_monk

@code_monk: लकड़हारा आदेश होने के लिए IEEE Std 1003.2 ( "POSIX.2") संगत, लकड़हारा आदेश util-linux पैकेज का हिस्सा है और लिनक्स कर्नेल आर्काइव ⟨से उपलब्ध है की उम्मीद है kernel.org/pub/linux/utils / उपयोग- linux⟩।
मिकू

12

यह एक साधारण STDERR फ़ंक्शन है, जो STDERR को पाइप इनपुट को पुनर्निर्देशित करता है।

#!/bin/bash
# *************************************************************
# This function redirect the pipe input to STDERR.
#
# @param stream
# @return string
#
function STDERR () {

cat - 1>&2

}

# remove the directory /bubu
if rm /bubu 2>/dev/null; then
    echo "Bubu is gone."
else
    echo "Has anyone seen Bubu?" | STDERR
fi


# run the bubu.sh and redirect you output
tux@earth:~$ ./bubu.sh >/tmp/bubu.log 2>/tmp/bubu.err

2
मुझे लगता है कि आप उर्फ ​​के साथ एक ही काम कर सकते हैं और बहुत अधिक कॉम्पैक्ट हो सकते हैं
BCS

या आप सीधे डिवाइस फ़ाइल पर पाइप कर सकते हैं echo what | /dev/stderr...
1

11

नोट: मैं पोस्ट का उत्तर दे रहा हूं- भ्रामक / अस्पष्ट नहीं "गूंज जो स्टैडर के लिए आउटपुट" प्रश्न (पहले से ही ओपी पर उत्तर दिया गया है)।

आशय दिखाने के लिए एक फ़ंक्शन का उपयोग करें और जिस स्रोत को आप चाहते हैं वह स्रोत। उदाहरण के लिए

#!/bin/bash

[ -x error_handling ] && . error_handling

filename="foobar.txt"
config_error $filename "invalid value!"

output_xml_error "No such account"

debug_output "Skipping cache"

log_error "Timeout downloading archive"

notify_admin "Out of disk space!"

fatal "failed to open logger!"

और error_handlingजा रहा है:

ADMIN_EMAIL=root@localhost

config_error() { filename="$1"; shift; echo "Config error in $filename: $*" 2>&1; }

output_xml_error() { echo "<error>$*</error>" 2>&1; }

debug_output() { [ "$DEBUG"=="1" ] && echo "DEBUG: $*"; }

log_error() { logger -s "$*"; }

fatal() { which logger >/dev/null && logger -s "FATAL: $*" || echo "FATAL: $*"; exit 100; }

notify_admin() { echo "$*" | mail -s "Error from script" "$ADMIN_EMAIL"; }

ओपी में चिंताओं को संभालने वाले कारण:

  • सबसे अच्छा वाक्यविन्यास संभव (बदसूरत प्रतीकों के बजाय सार्थक शब्द)
  • एक त्रुटि करने के लिए कठिन (खासकर यदि आप स्क्रिप्ट का पुन: उपयोग करते हैं)
  • यह एक मानक बैश उपकरण नहीं है, लेकिन यह आपके या आपकी कंपनी / संगठन के लिए एक मानक शेल लाइब्रेरी हो सकता है

अन्य कारण:

  • स्पष्टता - अन्य अनुरक्षकों को इरादा दिखाता है
  • गति - कार्य शेल स्क्रिप्ट की तुलना में तेज़ हैं
  • पुन: प्रयोज्य - एक फ़ंक्शन दूसरे फ़ंक्शन को कॉल कर सकता है
  • विन्यास - मूल स्क्रिप्ट को संपादित करने की आवश्यकता नहीं है
  • डिबगिंग - एक त्रुटि के लिए जिम्मेदार लाइन को ढूंढना आसान है (खासकर यदि आप एक टन पुनर्निर्देशन / फ़िल्टरिंग आउटपुट के साथ मर रहे हैं)
  • मजबूती - यदि कोई फ़ंक्शन गायब है और आप स्क्रिप्ट को संपादित नहीं कर सकते हैं, तो आप एक ही नाम के साथ बाहरी टूल का उपयोग करके वापस गिर सकते हैं (जैसे कि log_error को लिनक्स पर लकड़हारा को अलियास किया जा सकता है)
  • स्विचिंग कार्यान्वयन - आप लाइब्रेरी के "x" विशेषता को हटाकर बाहरी उपकरणों पर स्विच कर सकते हैं
  • अगर आप एसटीडीआरआर या कहीं और जाते हैं तो आउटपुट एग्नोस्टिक - आपको इसकी कोई परवाह नहीं है
  • निजीकरण - आप पर्यावरण चर के साथ व्यवहार को कॉन्फ़िगर कर सकते हैं

10

मेरा सुझाव:

echo "my errz" >> /proc/self/fd/2

या

echo "my errz" >> /dev/stderr

echo "my errz" > /proc/self/fd/2प्रभावी ढंग से करने के लिए उत्पादन होगा stderrक्योंकि /proc/selfमौजूदा प्रक्रिया के लिए एक लिंक है, और /proc/self/fdप्रक्रिया खोला फ़ाइल वर्णनकर्ता रखती है, और फिर, 0, 1, और 2के लिए खड़े हो stdin, stdoutऔरstderr क्रमशः।

/proc/selfलिंक MacOS पर काम नहीं करता है, तथापि, /proc/self/fd/*Android पर Termux पर उपलब्ध है, लेकिन नहीं /dev/stderrकैसे एक बैश स्क्रिप्ट से ओएस का पता लगाने के लिए? मदद कर सकते हैं कि आपको अपनी स्क्रिप्ट को किस संस्करण का उपयोग करके निर्धारित करके अधिक पोर्टेबल बनाने की आवश्यकता है।


5
/proc/selfलिंक नहीं तो मैं सीधी-सपाट के साथ रह सकते हैं, MacOS पर काम करता है /dev/stderrविधि। इसके अलावा, जैसा कि अन्य उत्तरों / टिप्पणियों में उल्लेख किया गया है, यह संभवतः >>एपेंड करने के लिए उपयोग करना बेहतर है ।
MarkHu

4
/proc/self/fd/*एंड्रॉइड पर टर्मक्स पर उपलब्ध है, लेकिन नहीं /dev/stderr
go2null

9

catजैसा कि कुछ यहाँ उल्लेख किया गया है का उपयोग न करें। catएक है कार्यक्रम है, जबकि echoऔर printfपार्टी कर रहे हैं (शेल) builtins। एक कार्यक्रम या अन्य स्क्रिप्ट लॉन्च करना (ऊपर भी उल्लेख किया गया है) का मतलब है कि इसकी लागत के साथ एक नई प्रक्रिया बनाएं। बिल्डिंस का उपयोग करना, लेखन कार्य काफी सस्ते हैं, क्योंकि एक प्रक्रिया (-नियोजन) को बनाने (निष्पादित) करने की कोई आवश्यकता नहीं है।

सलामी बल्लेबाज पूछता है कि "स्टैडर्र के लिए आउटपुट ( पाइप ) के लिए कोई मानक उपकरण है ", इसका जवाब है: नहीं ... क्यों? ... rediredcting पाइप यूनिक्स (Linux ...) और bash (sh) जैसे सिस्टम में एक एलेमेंटरी कॉन्सेप्ट है जो इन कॉन्सेप्ट्स को बनाता है।

मैं सलामी बल्लेबाज से सहमत हूं कि इस तरह के नोटिस के साथ पुनर्निर्देशित करना: &2>1आधुनिक प्रोग्रामर के लिए बहुत सुखद नहीं है, लेकिन यह बैश है। बैश को विशाल और मजबूत कार्यक्रमों को लिखने का इरादा नहीं था, यह कम कीपर्स के साथ काम करने में मदद करने के लिए इरादा है; ;-)

और कम से कम, आप पंक्ति में कहीं भी पुनर्निर्देशन रख सकते हैं:

$ echo This message >&2 goes to stderr 
This message goes to stderr

1
केवल प्रदर्शन के कारण समय से पहले अनुकूलन के कारण कार्यक्रमों का उपयोग न करने के लिए देवों को बताना। एग्रेसिव, आसान-टू-फॉलो दृष्टिकोणों को हार्ड-टू-समझने वाले कोड पर प्राथमिकता दी जानी चाहिए जो बेहतर प्रदर्शन करता है (मिलीसेकंड के आदेश पर)।
ग्यूपैडपॉक

@GuyPaddock क्षमा करें, आपने इसे ठीक से नहीं पढ़ा है। एफआईआर; इसके बारे में पुनर्निर्देशित पाइप जो अच्छी तरह से बैश द्वारा नियंत्रित किया जाता है। यदि कोई (बदसूरत) सिंटैक्स पसंद नहीं करता है तो कैसे रीडायरेक्ट करता है, तो उसे बैश स्क्रिप्ट को लागू करना बंद करना चाहिए या बैश तरीका सीखना चाहिए। दूसरा; आपको पता होना चाहिए कि एक बैश बिलिन को यस्ट कॉल की तुलना में एक नए प्रोजेस को लॉन्च करना कितना महंगा है।
रिटर्न 42

1
किसी को बैश बिल्ट-इन बनाम के प्रदर्शन व्यापार-बंदों को जानने देने catऔर किसी को बिल्ली का उपयोग न करने का निर्देश देने के बीच अंतर है क्योंकि यह धीमा है। अनगिनत उपयोग के मामले हैं जहां बिल्ली सही विकल्प है, इसलिए मैं आपके उत्तर पर आपत्ति करता हूं।
गाईडपैडॉक

@GuyPaddock सलामी बल्लेबाज के लिए कहा echo प्रतिस्थापन के । यहां तक ​​कि अगर वह उपयोग करता है cat, तो उसे बैश पुनर्निर्देशन का उपयोग करना होगा। वैसे भी। तो, catयहाँ उपयोग करने के लिए कोई अर्थ नहीं है। BTW मैं catएक दिन में 100 बार उपयोग करता हूं , लेकिन कभी भी इस संदर्भ में नहीं पूछा कि आप किसके लिए गए थे ... आपको मिल गया?
वापसी

8

एक और विकल्प जिसे मैंने हाल ही में ठोकर खाई है वह है:

    {
        echo "First error line"
        echo "Second error line"
        echo "Third error line"
    } >&2

मल्टी-लाइन एरर आउटपुट कम एरर प्रोन बनाते समय यह केवल बैश बिल्ट-इन का उपयोग करता है (क्योंकि आपको &>2हर लाइन में जोड़ना याद नहीं है )।


1
विश्वास नहीं कर सकता, जब आप बैश-रीडायरेक्ट का उपयोग करने की सलाह देते हैं, तो आप मुझे वोट देते हैं और अपने जवाब में आप बैश-रीडायरेक्ट का उपयोग कर रहे हैं।
वापसी

1
@ return42 मैंने आपका जवाब नीचे दिया क्योंकि सभी ने ओपी को बताया था कि जो उन्होंने शुरू किया था उससे बेहतर कोई जवाब नहीं है .. यह वास्तव में कोई जवाब नहीं है। मुझे आपके उत्तर में एक उप-शेल सुझाव भी दिखाई नहीं दे रहा है ... आपका उत्तर वास्तव में ओपी को सलाह देता है कि वह catकिसी भी अन्य उपयोगिता का उपयोग न करें , जो प्रश्न के लिए ऑफ-टॉपिक हो।
ग्यूपैडपॉक 19


6

read एक शेल बिल्टिन कमांड है जो स्टडर को प्रिंट करता है, और इसे पुनर्निर्देशन की चालें किए बिना प्रतिध्वनि की तरह इस्तेमाल किया जा सकता है:

read -t 0.1 -p "This will be sent to stderr"

-t 0.1समय समाप्त कि अक्षम, पढ़ने के मुख्य कार्यक्षमता एक चर में stdin की एक पंक्ति के भंडारण है।


5
ओएस एक्स पर बैश "0.1"
जेम्स रोथ

2

एक स्क्रिप्ट बनाओ

#!/bin/sh
echo $* 1>&2

वह आपका उपकरण होगा।

या यदि आप अलग फाइल में स्क्रिप्ट नहीं रखना चाहते हैं तो एक फंक्शन करें।


6
इसके लिए एक फ़ंक्शन होना बेहतर है (जैसे जेम्स रोथ का जवाब), और सभी तर्कों के साथ पारित करने के लिए बेहतर है, न कि पहले।
Cascabel

2
एक समारोह बेहतर क्यों होगा? (या, वैकल्पिक रूप से: "यह समझाने के लिए बेहतर है कि यह बेहतर क्यों होगा ...")
ओगरे भजन 33

3
@ OgrePsalm33 एक कारण बेहतर होगा कि किसी स्क्रिप्ट को कॉल करते समय, आम तौर पर एक नया शेल इंस्टेंस बनाया जाता है ताकि स्क्रिप्ट को निष्पादित करने के लिए एक वातावरण प्रदान किया जा सके। दूसरी ओर, एक फ़ंक्शन को वर्तमान में चल रहे शेल के वातावरण में रखा गया है। एक फ़ंक्शन को कॉल करना, इस मामले में, एक अधिक कुशल संचालन होगा क्योंकि शेल के एक और उदाहरण के निर्माण से बचा जाएगा।
डिस्टेंसन

-10

मैक ओएस एक्स: मैंने स्वीकार किए गए उत्तर और कुछ अन्य उत्तरों की कोशिश की और उन सभी का परिणाम मेरे मैक पर STDOUT नॉट STDERR लिखने में हुआ।

यहाँ पर्ल का उपयोग करके मानक त्रुटि को लिखने का एक पोर्टेबल तरीका है:

echo WARNING! | perl -ne 'print STDERR'

योग्य आप सभी चाहते हैं, लेकिन यह समाधान है जो मैं वास्तव में अपने कोड में उपयोग करता हूं!
नूह सुस्मैन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.