bash - في shell ، ماذا يعني "2>& 1"؟





unix redirect (13)


لقد وجدت هذه المشاركة الرائعة في إعادة التوجيه: كل شيء عن عمليات إعادة التوجيه

إعادة توجيه الإخراج القياسي والخطأ القياسي إلى ملف

أمر $ &> ملف

يستخدم هذا الكبل الواحد عامل التشغيل &> لإعادة توجيه كل من دفق الإخراج - stdout و stderr - من الأمر إلى الملف. هذا هو اختصار bash لسرعة إعادة توجيه كلتا التدفقات إلى نفس الوجهة.

إليك كيفية ظهور جدول واصفات الملفات بعد إعادة توجيه كل من الدفقات:

كما ترون كل من stdout و stderr الآن أشر إلى ملف. لذلك مكتوبة أي شيء مكتوب على stdout وستدرر إلى ملف.

هناك عدة طرق لإعادة توجيه كل من الدفقات إلى نفس الوجهة. يمكنك إعادة توجيه كل مجموعة بث واحد تلو الآخر:

$ command> file 2> & 1

هذه طريقة شائعة أكثر بكثير لإعادة توجيه كل من الدفقين إلى ملف. يتم إعادة توجيه stdout الأول إلى ملف ، ومن ثم يتم تكرار stderr ليكون نفس stdout. بحيث ينتهي كل من التدفقات في الإشارة إلى الملف.

عندما ترى bash عدة عمليات إعادة توجيه ، فإنها تعالجها من اليسار إلى اليمين. دعونا نخطو الخطوات ونرى كيف يحدث ذلك. قبل تشغيل أي جدول واصف ملف أوامر باش يبدو مثل هذا:

الآن bash يعالج ملف إعادة التوجيه الأول> الملف. لقد رأينا ذلك من قبل ونجعل نقطة stdout ملف:

الباش التالي يرى عملية إعادة التوجيه الثانية 2 & 1. لم نشهد إعادة التوجيه هذه من قبل. هذا واحد يكرر واصف الملف 2 ليكون نسخة من واصف الملف 1 ونحصل على:

تم إعادة توجيه كل من التدفقات إلى الملف.

لكن كن حذرا هنا! جاري الكتابة:

الأمر> ملف 2> & 1

ليست هي نفس الكتابة:

$ command 2> & 1> file

ترتيب عمليات إعادة التوجيه مهم في bash! يعيد هذا الأمر توجيه الإخراج القياسي إلى الملف فقط. ستظل stderr الطباعة إلى المحطة. لفهم سبب حدوث ذلك ، فلنبدأ في الخطوات من جديد. لذا ، قبل تشغيل الأمر ، يبدو جدول واصفات الملفات على النحو التالي:

الآن bash يعيد عمليات إعادة التوجيه إلى اليمين. يرى لأول مرة 2 & 1 حتى يكرر stderr إلى stdout. يصبح جدول واصف الملف:

الآن سيشاهد bash ملف إعادة التوجيه الثاني> ويعيد توجيه المعيار إلى الملف:

هل ترى ماذا يحدث هنا؟ يشير Stdout الآن إلى الملف ولكن stderr لا يزال يشير إلى المحطة! كل شيء مكتوب على stderr لا يزال يطبع على الشاشة! لذا كن حذرا للغاية مع ترتيب عمليات إعادة التوجيه!

لاحظ أيضًا أنه في bash ، اكتب هذا:

أمر $ &> ملف

هو بالضبط نفس:

$ command> & file

في shell Unix ، إذا أردت دمج stderr و stdout في تدفق stdout لمزيد من المعالجة ، يمكنني إلحاق ما يلي في نهاية الأمر الخاص بي:

2>&1

لذلك ، إذا كنت تريد استخدام "الرأس" على الناتج من g ++ ، يمكنني القيام بشيء كالتالي:

g++ lots_of_errors 2>&1 | head

حتى أتمكن من رؤية الأخطاء القليلة الأولى فقط.

دائمًا ما أجد صعوبة في تذكر ذلك ، ويجب أن أذهب دائمًا للبحث عنه ، وذلك لأنني لا أفهم بشكل كامل تركيب هذه الخدعة. هل يمكن لأي شخص أن يكسر هذا الأمر ويشرح شخصية الحرف ما "2> & 1" تعني؟




هذا هو مثل paasing الخطأ إلى stdout أو الطرفية. أي. كمد ليس أمر $ كمد 2> اسم الملف القط اسم الملف غير موجود

الخطأ الذي تم إرساله إلى الملف مثل 2> & 1 خطأ تم إرساله إلى المحطة




واصف الملف 1 هو الإخراج القياسي (stdout).
واصف الملف 2 هو الخطأ القياسي (stderr).

وإليك طريقة واحدة لتذكر هذه البنية (على الرغم من أنها ليست دقيقة تمامًا): في البداية ، قد تبدو 2>1 طريقة جيدة لإعادة توجيه stderr إلى stdout. ومع ذلك ، فسيتم تفسيره بالفعل على أنه "إعادة توجيه stderr إلى ملف مسمى 1 ". & يشير إلى أن ما يلي هو واصف ملف وليس اسم ملف. لذلك يصبح البناء: 2>&1 .




2>&1 هو بناء قذيفة POSIX. في ما يلي تعطل ، رمز مميز برمز مميز:

2 : واصف ملف الإخراج " خطأ قياسي ".

>& : تكرار عامل واصف ملف الإخراج (متغير مشغل إعادة توجيه الإخراج > ). وبالنظر إلى [x]>&[y] ، يتم إنشاء واصف الملف المدرج بـ x ليكون نسخة من واصف ملف الإخراج y .

1 واصف ملف الإخراج " الإخراج القياسي ".

التعبير 2>&1 نسخ ملف واصف 1 إلى الموقع 2 ، بحيث يذهب أي إخراج مكتوب إلى 2 ("خطأ معياري") في بيئة التنفيذ إلى نفس الملف الذي تم وصفه أصلاً بواسطة 1 ("الإخراج القياسي").

المزيد من التوضيح:

واصف الملف : "عدد صحيح فريد وغير سلبي لكل عملية يستخدم لتحديد ملف مفتوح لغرض الوصول إلى الملفات."

الإخراج / الخطأ القياسي : راجع الملاحظة التالية في قسم Redirection من مستندات shell:

يتم تمثيل الملفات المفتوحة بالأرقام العشرية بدءًا من الصفر. أكبر قيمة ممكنة هي محددة بالتطبيق ؛ ومع ذلك ، يجب أن تدعم كافة التطبيقات من 0 إلى 9 على الأقل ، شاملة ، لاستخدام التطبيق. تسمى هذه الأرقام "واصفات الملف". تحتوي القيم 0 و 1 و 2 على معانٍ خاصة واستخدامات تقليدية ويتم تضمينها في بعض عمليات إعادة التوجيه ؛ يشار إليها كمدخل قياسي ، خرج قياسي ، وخطأ معياري ، على التوالي. عادة ما تأخذ البرامج مدخلاتها من الإدخال القياسي ، وتكتب الخرج على المخرجات القياسية. عادة ما تتم كتابة رسائل الخطأ على خطأ معياري. يمكن أن يسبق مشغلي إعادة التوجيه رقم واحد أو أكثر (مع عدم السماح بأحرف متداخلة) لتعيين رقم واصف الملف.




تشير الأرقام إلى واصفات الملفات (fd).

  • الصفر هو stdin
  • واحد هو stdout
  • اثنان هو stderr

2>&1 يعيد التوجيهات من 2 إلى 1.

يعمل هذا لأي عدد من واصفات الملفات إذا كان البرنامج يستخدمها.

يمكنك إلقاء نظرة على /usr/include/unistd.h إذا نسيتها:

/* Standard file descriptors.  */
#define STDIN_FILENO    0   /* Standard input.  */
#define STDOUT_FILENO   1   /* Standard output.  */
#define STDERR_FILENO   2   /* Standard error output.  */

لقد قلت أني قمت بكتابة أدوات C التي تستخدم واصفات ملفات غير قياسية لتسجيل مخصص بحيث لا تراها إلا إذا قمت بإعادة توجيهها إلى ملف أو شيء ما.




بشرط أن /foo غير موجود على نظامك و /tmp

$ ls -l /tmp /foo

ستقوم بطباعة محتويات /tmp وطباعة رسالة خطأ لـ /foo

$ ls -l /tmp /foo > /dev/null

سوف ترسل محتويات /tmp إلى /dev/null وطباعة رسالة خطأ لـ /foo

$ ls -l /tmp /foo 1> /dev/null

سوف تفعل بالضبط نفس الشيء (لاحظ 1 )

$ ls -l /tmp /foo 2> /dev/null

سيتم طباعة محتويات /tmp وإرسال رسالة الخطأ إلى /dev/null

$ ls -l /tmp /foo 1> /dev/null 2> /dev/null

سوف ترسل كلاً من القائمة بالإضافة إلى رسالة الخطأ إلى /dev/null

$ ls -l /tmp /foo > /dev/null 2> &1

هو الاختزال




الناس ، تذكر دائما تلميح paxdiablo حول الموقع الحالي لهدف إعادة التوجيه ... من المهم.

بلدي التذكر الشخصية للمشغل 2>&1 هو:

  • فكر & بمعنى 'and' أو 'add' (الحرف هو ampers - و ، أليس كذلك؟)
  • وهكذا يصبح: "إعادة توجيه 2 (stderr) إلى حيث 1 (stdout) بالفعل / حالياً وإضافة كلتا التدفقات" .

يعمل نفس التذكر نفسه مع إعادة التوجيه الأخرى المستخدمة بكثرة أيضًا ، 1>&2 :

  • فكر في المعنى & and أو add ... (يمكنك الحصول على فكرة حول علامة العطف ، نعم؟)
  • لذلك يصبح: إعادة توجيه 1 (stdout) إلى حيث 2 (stderr) بالفعل / حالياً وإضافة كلتا التدفقات ' .

وتذكر دومًا: يجب عليك قراءة سلاسل عمليات إعادة التوجيه "من النهاية" ، من اليمين إلى اليسار ( وليس من اليسار إلى اليمين).




يرسل هذا البناء مسار الخطأ القياسي ( stderr ) إلى الموقع الحالي stdout القياسي ( stdout ) - يبدو أن قضية العملة هذه قد أهملت بالإجابات الأخرى.

يمكنك إعادة توجيه أي مؤشر إخراج إلى آخر باستخدام هذه الطريقة ولكن غالبًا ما يتم استخدامه لتوجيه تدفق stdout و stderr إلى دفق واحد للمعالجة.

بعض الأمثلة هي:

# Look for ERROR string in both stdout and stderr.
foo 2>&1 | grep ERROR

# Run the less pager without stderr screwing up the output.
foo 2>&1 | less

# Send stdout/err to file (with append) and terminal.
foo 2>&1 |tee /dev/tty >>outfile

# Send stderr to normal location and stdout to file.
foo >outfile1 2>&1 >outfile2

لاحظ أن ذلك الأخير لن يقوم بتوجيه stderr إلى outfile2 - فإنه يعيد توجيهه إلى ما كان stdout عند مواجهة الوسيطة ( outfile1 ) ثم إعادة توجيه stdout إلى outfile2 .

هذا يسمح ببعض الخداع المتطور.




إعادة توجيه الإدخال

إعادة توجيه الإدخال يؤدي الملف الذي ينتج اسمه عن توسيع الكلمة ليتم فتحه للقراءة على واصف الملف n ، أو الإدخال القياسي (واصف الملف 0) إذا لم يتم تحديد n.

التنسيق العام لإعادة توجيه الإدخال هو:

      [n]<word

إعادة توجيه الإخراج

إعادة توجيه الإخراج يؤدي الملف الذي ينتج اسمه من توسيع الكلمة المراد فتحها لكتابة على واصف الملف n أو الإخراج القياسي (واصف الملف 1) إذا لم يتم تحديد n. إذا لم يكن الملف موجودا، يتم إنشاؤه؛ إذا كان موجودًا يتم اقتطاعها إلى حجم صفر.

التنسيق العام لإعادة توجيه الإخراج هو:

      [n]>word

نقل واصفات الملف

نقل واصفات الملفات عامل إعادة التوجيه

      [n]<&digit-

نقل رقم واصف الملف إلى واصف الملف n ، أو الإدخال القياسي (واصف الملف 0) إذا لم يتم تحديد n. يتم إغلاق الرقم بعد التكرار إلى n.

وبالمثل ، فإن مشغل إعادة التوجيه

      [n]>&digit-

نقل رقم واصف الملف إلى واصف الملف n ، أو الإخراج القياسي (واصف الملف 1) إذا لم يتم تحديد n.

المرجع:

man bash
اكتب /^REDIRECT لتحديد موقع قسم redirection ، اعرف المزيد ..

نسخة على الانترنت هنا:
http://www.gnu.org/software/bash/manual/bashref.html#Redirections

ملاحظة:

الكثير من الوقت ، كان man أداة قوية لتعلم لينكس




بعض الحيل حول إعادة التوجيه

قد يكون لبعض الخصائص اللغوية الخاصة بهذا الأمر سلوكيات مهمة. هناك بعض العينات الصغيرة حول إعادة التوجيه ، STDERR ، STDOUT والحجج الطلب .

1 - الكتابة أو إلحاق؟

Symbole > mean redirection .

  • > يعني الإرسال إلى ملف مكتمل بالكامل ، واستبدال الهدف إذا كان موجودًا (راجع ميزة bash noclobber في # 3 لاحقًا).
  • >> يعني إرسال بالإضافة إلى أن إلحاق الهدف إذا وجدت.

أي حالة ، سيتم إنشاء الملف إذا لم تكن موجودة.

2 - سطر الأوامر shell هو أمر يعتمد !!

لاختبار ذلك ، نحتاج إلى أمر بسيط يرسل شيئًا من المخرجات :

$ ls -ld /tmp /tnt
ls: cannot access /tnt: No such file or directory
drwxrwxrwt 118 root root 196608 Jan  7 11:49 /tmp

$ ls -ld /tmp /tnt >/dev/null
ls: cannot access /tnt: No such file or directory

$ ls -ld /tmp /tnt 2>/dev/null
drwxrwxrwt 118 root root 196608 Jan  7 11:49 /tmp

(نتوقع ليس لديك دليل يدعى /tnt ، بالطبع ؛). حسنا ، لدينا ذلك!

لذلك دعونا نرى:

$ ls -ld /tmp /tnt >/dev/null
ls: cannot access /tnt: No such file or directory

$ ls -ld /tmp /tnt >/dev/null 2>&1

$ ls -ld /tmp /tnt 2>&1 >/dev/null
ls: cannot access /tnt: No such file or directory

سطر الأوامر الأخير تفريغ STDERR إلى وحدة التحكم ، يبدو أنه ليس السلوك المتوقع ... ولكن ...

إذا كنت ترغب في إجراء بعض تصفية الرسائل حول أحد ouput ، أو الآخر أو كليهما:

$ ls -ld /tmp /tnt | sed 's/^.*$/<-- & --->/'
ls: cannot access /tnt: No such file or directory
<-- drwxrwxrwt 118 root root 196608 Jan  7 12:02 /tmp --->

$ ls -ld /tmp /tnt 2>&1 | sed 's/^.*$/<-- & --->/'
<-- ls: cannot access /tnt: No such file or directory --->
<-- drwxrwxrwt 118 root root 196608 Jan  7 12:02 /tmp --->

$ ls -ld /tmp /tnt >/dev/null | sed 's/^.*$/<-- & --->/'
ls: cannot access /tnt: No such file or directory

$ ls -ld /tmp /tnt >/dev/null 2>&1 | sed 's/^.*$/<-- & --->/'

$ ls -ld /tmp /tnt 2>&1 >/dev/null | sed 's/^.*$/<-- & --->/'
<-- ls: cannot access /tnt: No such file or directory --->

لاحظ أن سطر الأوامر الأخير في هذه الفقرة هو نفسه تمامًا كما في المثل السابق ، حيث كتبت لا يبدو أنه السلوك المتوقع (لذلك ، قد يكون هذا السلوك متوقعًا).

حسنًا ، هناك حيل صغيرة حول عمليات إعادة التوجيه ، لإجراء عمليات مختلفة على كل من عمليات المغادرة :

$ ( ls -ld /tmp /tnt | sed 's/^/O: /' >&9 ) 9>&2  2>&1  | sed 's/^/E: /'
O: drwxrwxrwt 118 root root 196608 Jan  7 12:13 /tmp
E: ls: cannot access /tnt: No such file or directory

Nota: سيحدث &9 واصف بشكل عفوي بسبب ) 9>&2 .

ملحق: مع وجود إصدار جديد من bash ( >4.0 ) ، هناك ميزة جديدة وبناء أكثر مثيرًا للقيام بهذا النوع من الأشياء:

$ ls -ld /tmp /tnt 2> >(sed 's/^/E: /') > >(sed 's/^/O: /')
O: drwxrwxrwt 17 root root 28672 Nov  5 23:00 /tmp
E: ls: cannot access /tnt: No such file or directory

ونهائي لمثل هذا التنسيق الناتج المتتالي:

$ ((ls -ld /tmp /tnt |sed 's/^/O: /' >&9 ) 2>&1 |sed 's/^/E: /') 9>&1| cat -n
     1  O: drwxrwxrwt 118 root root 196608 Jan  7 12:29 /tmp
     2  E: ls: cannot access /tnt: No such file or directory

ملحق: نفس الصيغة الجديدة ، بطريقتين:

$ cat -n <(ls -ld /tmp /tnt 2> >(sed 's/^/E: /') > >(sed 's/^/O: /'))
     1  O: drwxrwxrwt 17 root root 28672 Nov  5 23:00 /tmp
     2  E: ls: cannot access /tnt: No such file or directory

حيث تنتقل STDOUT خلال فلتر محدد ، STDERR إلى آخر وأخيراً يتم دمج المخرجات من خلال مرشح الأوامر الثالث.

3 - كلمة عن خيار noclobber و >| بناء الجملة

هذا حول الكتابة :

على الرغم من أن set -o noclobber يرشد bash لعدم الكتابة فوق أي ملف موجود ، فإن >| بناء الجملة تسمح لك بالمرور من خلال هذا القيد:

$ testfile=$(mktemp /tmp/testNoClobberDate-XXXXXX)

$ date > $testfile ; cat $testfile
Mon Jan  7 13:18:15 CET 2013

$ date > $testfile ; cat $testfile
Mon Jan  7 13:18:19 CET 2013

$ date > $testfile ; cat $testfile
Mon Jan  7 13:18:21 CET 2013

تتم الكتابة فوق الملف في كل مرة ، جيدًا الآن:

$ set -o noclobber

$ date > $testfile ; cat $testfile
bash: /tmp/testNoClobberDate-WW1xi9: cannot overwrite existing file
Mon Jan  7 13:18:21 CET 2013

$ date > $testfile ; cat $testfile
bash: /tmp/testNoClobberDate-WW1xi9: cannot overwrite existing file
Mon Jan  7 13:18:21 CET 2013

ممر مع >| :

$ date >| $testfile ; cat $testfile
Mon Jan  7 13:18:58 CET 2013

$ date >| $testfile ; cat $testfile
Mon Jan  7 13:19:01 CET 2013

إلغاء هذا الخيار و / أو الاستفسار إذا كان قد تم إعداده بالفعل.

$ set -o | grep noclobber
noclobber           on

$ set +o noclobber

$ set -o | grep noclobber
noclobber           off

$ date > $testfile ; cat $testfile
Mon Jan  7 13:24:27 CET 2013

$ rm $testfile

4 - آخر خدعة وأكثر ...

لإعادة توجيه كل من الناتج من أمر معين ، نرى أن بناء الجملة الصحيح يمكن أن يكون:

$ ls -ld /tmp /tnt >/dev/null 2>&1

لهذه الحالة الخاصة ، هناك صيغة مختصرة: &> ... أو >&

$ ls -ld /tmp /tnt &>/dev/null 

$ ls -ld /tmp /tnt >&/dev/null 

Nota: if 2>&1 exist، 1>&2 is a syntaxe correct too:

$ ls -ld /tmp /tnt 2>/dev/null 1>&2

4 ب- الآن ، سوف أدعك تفكر في:

$ ls -ld /tmp /tnt 2>&1 1>&2  | sed -e s/^/++/
++/bin/ls: cannot access /tnt: No such file or directory
++drwxrwxrwt 193 root root 196608 Feb  9 11:08 /tmp/

$ ls -ld /tmp /tnt 1>&2 2>&1  | sed -e s/^/++/
/bin/ls: cannot access /tnt: No such file or directory
drwxrwxrwt 193 root root 196608 Feb  9 11:08 /tmp/

4c- إذا كنت مهتمًا بمزيد من المعلومات

هل يمكن قراءة دليل غرامة عن طريق ضرب:

man -Len -Pless\ +/^REDIRECTION bash

في وحدة التحكم bash ؛-)




echo test > afile.txt

..redirects stdout إلى afile.txt . هذا هو نفس ما تفعله ..

echo test 1> afile.txt

لإعادة توجيه stderr ، عليك ..

echo test 2> afile.txt

>& is the syntax to redirect a stream to another file واصف - 0 is stdin. 1 هو stdout. 2 هو stderr.

يمكنك إعادة توجيه stdout إلى stderr عن طريق القيام ..

echo test 1>&2 # or echo test >&2

..أو العكس:

echo test 2>&1

باختصار .. 2> يعيد توجيه stderr إلى ملف (غير محدد) ، إلحاقي &1 يعيد توجيه stderr إلى stdout




0 للإدخال ، 1 ل stdout و 2 ل stderr.

نصيحة واحدة : somecmd >1.txt 2>&1 هو الصحيح ، في حين somecmd 2>&1 >1.txt خاطئ تماما مع أي تأثير!




للتحقق من وجود دليل ، يمكنك استخدام بنية بسيطة مثل:

if [ -d directory/path to a directory ] ; then
#Things to do

else #if needed #also: elif [new condition] 
# things to do
fi

يمكنك القيام بذلك أيضا في السلبية

if [ ! -d directory/path to a directory ] ; then
# things to do when not an existing directory

ملاحظة : كن حذرًا ، اترك مسافات فارغة على جانبي كل من قوستي الفتح والإغلاق.

باستخدام نفس البنية ، يمكنك استخدام:

-e: any kind of archive 

-f: file 

-h: symbolic link 

-r: readable file 

-w: writable file 

-x: executable file 

-s: file size greater than zero 






bash shell unix redirect