क्यों 2> और 1 और 1> और 2 के लिए रीडायरेक्ट आउटपुट?


36

मैं कई आदेशों का उपयोग कर आया हूं जो उपयोग करते हैं 2>&1और 1>&2, लेकिन मैं इसका उपयोग करने के उद्देश्य से अपना सिर नहीं मिला सकता हूं और जब मुझे इसका उपयोग करना चाहिए।

मैं क्या समझता हूँ?

मुझे पता है कि 1मानक आउट का 2प्रतिनिधित्व करता है और मानक त्रुटि का प्रतिनिधित्व करता है। मुझे लगता है कि समझ में 2>&1जोड़ती है के उत्पादन 2के लिए 1और इसके विपरीत।

जो मुझे नहीं मिलता

  1. मुझे इसका उपयोग कब करना चाहिए?
  2. इससे कौन सा उद्देश्य पूरा होगा?

जवाबों:


39

कभी-कभी आप stdout और stderr दोनों को एक ही स्थान पर पुनर्निर्देशित करना चाहते हैं , यह तब >&होता है जब इसका उपयोग किया जाता है - यह एक फ़ाइल विवरणक को दूसरे को इंगित करता है।


उदाहरण के लिए, यदि आप stdout और stderr दोनों को एक ही फ़ाइल में लिखना चाहते हैं (यह हो /dev/nullया नहीं output.txt), तो आप अलग-अलग रीडायरेक्ट कर सकते हैं, साथ में

app 1>/dev/null 2>/dev/null

या आप एक फ़ाइल डिस्क्रिप्टर को फ़ाइल में रीडायरेक्ट कर सकते हैं, और दूसरी फ़ाइल डिस्क्रिप्टर को पहले एक में:

app 1>/dev/null 2>&1

app 2>/dev/null 1>&2

पहले उदाहरण में, 2>&1पॉइंट फाइल डिस्क्रिप्टर # 2 से जहाँ # 1 पहले से ही इंगित कर रहा है। दूसरा उदाहरण वही प्राप्त करता है, जो स्टादर के बजाय शुरू होता है।

एक अन्य उदाहरण के रूप में, ऐसे मामले हैं जब stdout (फाइल डिस्क्रिप्टर # 1) पहले से ही वांछित स्थान की ओर इशारा कर रहा है, लेकिन आप इसे नाम से संदर्भित नहीं कर सकते हैं (यह पाइप, सॉकेट या इस तरह से जुड़ा हो सकता है)। यह अक्सर प्रक्रिया विस्तार ( ` `या $( )ऑपरेटर्स) का उपयोग करते समय होता है , जो सामान्य रूप से केवल स्टडआउट को पकड़ता है, लेकिन आप इसमें स्टाडर को शामिल करना चाह सकते हैं। इस स्थिति में, आप >&stderr को stdout को इंगित करने के लिए भी उपयोग करेंगे :

out=$(app 2>&1)

एक अन्य आम उदाहरण एक पेजर, या grep, या इसी तरह की उपयोगिता है, क्योंकि पाइप |सामान्य रूप से केवल स्टडआउट पर काम करता है, आप पाइप का उपयोग करने से पहले स्टडआउट पर पुनर्निर्देशित करेंगे:

app 2>&1 | grep hello

कैसे पता करने के लिए, जिनमें से 2>&1या 1>&2सही है? पहले से ही सेट फ़ाइल वर्णनकर्ता के अधिकार के लिए चला जाता है >&, और फ़ाइल वर्णनकर्ता आप रीडायरेक्ट करना चाहते बाईं ओर चला जाता है। ( 2>&1"पॉइंट फाइल डिस्क्रिप्टर # 2 को डिस्क्रिप्टर # 1 फाइल करने के लिए")।


कुछ गोले में आम पुनर्निर्देशन के लिए शॉर्टकट हैं; यहाँ बैश से उदाहरण हैं:

  • 1> को छोटा किया जा सकता है >

  • 1>foo 2>&1को >&fooया&>foo

  • 2>&1 | program सेवा मेरे |& program


मुझे नहीं पता था कि ऐसा करने app 1>/dev/null 2>&1का मतलब होगा कि 2> और 1 उस फ़ाइल को इंगित करेगा जो 1 पहले से ही रीडायरेक्ट कर रही थी। मैं इसे आसानी से कर सकता हूँ app > /dev/null &>?
मूंगफली का मटका

मुझे समझने में मुश्किल हो रही है the already set up fd goes to the right of >&, and the fd you want to redirect goes to the left। पहले से सेट की गई फ़ाइल डिस्क्रिप्टर से आपका क्या मतलब है? इसका क्या मतलब है?
मूंगफलीमंडी


क्षमा करें, जब तक आप मुझे निर्देश देने का इरादा नहीं कर रहे थे, मैं आपके द्वारा बताए गए कथन का पालन नहीं करता।
मूँगफली के दाने

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

2

एक स्थिति जब आपको इसकी आवश्यकता होती है जब आप straceएक पेजर में आउटपुट प्रदर्शित करना चाहते हैं । straceअपने आउटपुट को मानक त्रुटि पर प्रिंट करता है और पाइप आम तौर पर मानक आउटपुट को मानक इनपुट से जोड़ता है , इसलिए आपको रीडायरेक्ट का उपयोग करना होगा:

strace -p $pid 2>&1 | less

आपका क्या मतलब है pipes generally connect standard output to standard input?
मूँगफली के दाने

2
मेरा मतलब है कि पाइप ( |) पहले कमांड के मानक आउटपुट को लेते हैं और इसे दूसरे कमांड के मानक इनपुट से जोड़ते हैं।
jpalecek

2

कभी-कभी आप दोनों stdout( 1) और stderr( 2) को एक ही स्थान ( /dev/nullउदाहरण के लिए) पर पुनर्निर्देशित करना चाहते हैं । इसे प्राप्त करने का एक तरीका यह होगा:

$ program 1>/dev/null 2>/dev/null

लेकिन ज्यादातर लोगों को रीडायरेक्ट करके ऐसा छोटा stderrकरने stdoutके साथ 2>&1:

$ program 1>/dev/null 2>&1

इससे भी छोटा संस्करण है:

$ program >&- 2>&-

1

2: यह तब होता है जब आपके पास मानक त्रुटि और मानक आउट दोनों से उत्पादन होगा, और आप उन्हें एक ही स्ट्रिंग में रचना करना चाहते हैं।

1: जब आप मानक त्रुटि और मानक आउट दोनों के आउटपुट में हेरफेर करना चाहते हैं।


हेराफेरी से आपका क्या मतलब है? मेरी समझ यह है कि कुछ भी अनुप्रेषित >2/ प्रेषित / अशक्त है। या मैं पूरी तरह से गलत है?
मूँगफली के दाने

वह सही नहीं है। हेरफेर से मेरा मतलब है कि इसे grep या कुछ इसी तरह से पाइप करें। एक उदाहरण के लिए यहाँ देखें ।
soandos

0

मैं इसे एक अलग नौकरी शुरू करने के लिए उपयोग करता हूं:

someProgram 2>&1 >& my.log &

तब मैं लॉग आउट कर सकता हूं, और कुछ अंश अभी भी चल रहे होंगे। कार्यक्षमता GNU स्क्रीन, tmux और कुछ अन्य कार्यक्रमों द्वारा प्रदान की जाती है - लेकिन यहाँ यह बाहरी निर्भरता में से किसी के साथ हासिल की जाती है।


1
यह केवल तब तक काम करता है जब तक कि कार्यक्रम में भेजा जाने वाला कोई SITEUP न हो। बेहतर उपयोग nohupया disownऐसे मामलों में।
22

@ श्लोक: ठीक है। लेकिन अगर मैं प्रोग्राम के लिए SITEUP नहीं भेजूंगा - कोई भी, सही नहीं होगा?
Adobe

नहीं, नियंत्रण टर्मिनल S नाईटअप के साथ लॉगआउट की प्रक्रियाओं को चेतावनी देगा। व्यवहार में, यदि आप SSH के माध्यम से एक दूरस्थ शेल चलाते हैं और बाहर निकलते हैं, तो उदाहरण के लिए, आपकी प्रक्रिया मर जाएगी।
slhck

@ एलशॉक: यह सच नहीं हो सकता है: मैं इसे कुछ वर्षों के लिए उपयोग करता हूं - मैं ssh का लॉगआउट करता हूं, और प्रक्रिया अभी भी चल रही है।
Adobe

मुझे इसे और अधिक विस्तार से देखना होगा, लेकिन सिर्फ कार्यक्रमों को पृष्ठभूमि में रखना मेरे लिए सभी मामलों में काम नहीं आया है, और यह निश्चित रूप से मेरे स्थानीय मशीन पर भी काम नहीं करता है। ज़श और बैश यहाँ भी अलग तरह से व्यवहार करते हैं, ऐसा लगता है।
19

0

कल्पना कीजिए कि एक निर्देशिका है जिसका नाम tryइन तीन फाइलों में है:file file1 and file2.

अब इस कमांड को रन करें:

cat file file1 file2 file3

पहली तीन फाइलें खुलती हैं लेकिन catचौथी को खोलते समय एक त्रुटि होती है क्योंकि यह मौजूद नहीं है।

अब चलाएं:

cat file file1 file2 file3 1>outfile 2>&1

आपको स्क्रीन पर कोई आउटपुट दिखाई नहीं देगा: सबसे पहले 1>outfileकमांड के आउटपुट outfileको रीडायरेक्ट करेगा और फिर इसे 2>&1खोलने के file3लिए प्रयास करते समय डाली गई त्रुटि को रीडायरेक्ट करेगा outfile

1>&2 इसी तरह काम करता है और मानक उत्पादन में त्रुटि धारा को पुनर्निर्देशित करता है।

उम्मीद है की यह मदद करेगा!


0

वैकल्पिक परिदृश्य: टर्मिनल कमांड दूसरे टर्मिनल में आउटपुट दिखाते हैं

ttyउन्हें पहचानने के लिए प्रत्येक टर्मिनल में कमांड का उपयोग करें:

$ tty
/dev/pts/0

$ tty
/dev/pts/1

इन TTYs को मानते हुए, पहले स्टडआउट को दूसरे पर पुनर्निर्देशित करने के लिए, इसे पहले टर्मिनल में चलाएं:

exec 1>/dev/pts/1

नोट: अब हर कमांड आउटपुट pts / 1 पर दिखाई देगा

Pts / 0 के डिफ़ॉल्ट व्यवहार को रोकने के लिए:

exec 1>/dev/pts/0

प्रदर्शन के लिए यह वीडियो देखें ।


0

मामला जब stderout को पुनः निर्देशित करने का मामला पहले से ही यहां कवर किया गया है (उदाहरण के लिए फ़िल्टर (grep) त्रुटि का उपयोग करें)।

दूसरे मामले में stdout को stderr पर रीडायरेक्ट किया जाता है। एक सामान्य usecase (मेरे लिए कम से कम) "इको" (मेरे गोले में) के साथ मुद्रित करने के लिए चेतावनी / त्रुटि संदेश भेजने के लिए है (ताकि वे उपयोगकर्ता का ध्यान अधिक आसानी से पकड़ सकें)।

उदाहरण के लिए,

echo "file \"${file\" does not exist..." 1>&2
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.