ما هي stdin وstdout وstderr على Linux؟

النقاط الرئيسية

  • تنشئ أوامر Linux ثلاثة تدفقات بيانات (stdin وstdout وstderr) يمكن استخدامها لنقل البيانات حول أمر ما
  • stdin هو مجرى الإدخال، وstdout هو مجرى الإخراج، وstderr هو مجرى الخطأ في Linux.
  • يتيح لك إعادة التوجيه إعادة توجيه المخرجات أو الأخطاء إلى وجهات مختلفة، مثل الملفات أو الأنابيب.



stdin, stdout، و stderr هناك ثلاثة تدفقات بيانات يتم إنشاؤها عند تشغيل أمر Linux. يمكنك استخدامها لمعرفة ما إذا كانت البرامج النصية الخاصة بك يتم توجيهها أو إعادة توجيهها. سنوضح لك كيفية القيام بذلك.


تيارات الانضمام إلى نقطتين

بمجرد أن تبدأ في التعرف على أنظمة التشغيل Linux وأنظمة التشغيل الشبيهة بـUnix، ستصادف المصطلحات stdin, stdout، و stederr .هذه هي ثلاثة تيارات قياسية يتم إنشاؤها عند تنفيذ أمر Linux. في الحوسبة، يكون التدفق هو الشيء الذي يمكنه نقل البيانات. في حالة هذه التدفقات، تكون هذه البيانات عبارة عن نص.

تحتوي تدفقات البيانات، مثل تدفقات المياه، على طرفين. فهي تحتوي على مصدر وتدفق خارجي. أي أمر Linux تستخدمه يوفر طرفًا واحدًا لكل تدفق. يتم تحديد الطرف الآخر بواسطة shell الذي أطلق الأمر. سيتم توصيل هذا الطرف بنافذة المحطة الطرفية، أو توصيله بأنبوب، أو إعادة توجيهه إلى ملف أو أمر آخر، وفقًا لسطر الأوامر الذي أطلق الأمر.


تدفقات Linux القياسية: stdin، stdout، stderr

في لينكس، stdin هو دفق الإدخال القياسي. يقبل هذا الدفق النص كمدخل له. يتم تسليم إخراج النص من الأمر إلى الغلاف عبر stdout (المخرج القياسي). يتم إرسال رسائل الخطأ من الأمر عبر stderr (خطأ معياري) تيار.

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

يتم التعامل مع التدفقات مثل الملفات

في لينكس، يتم التعامل مع التدفقات كما لو كانت ملفات. يمكنك قراءة نص من ملف، ويمكنك كتابة نص في ملف. وكلا الإجراءين يتضمن تدفقًا من البيانات. لذا فإن مفهوم التعامل مع تدفق البيانات كملف ليس بالأمر الصعب.


يتم تخصيص رقم فريد لكل ملف مرتبط بعملية ما لتحديده. يُعرف هذا باسم موصوف الملف. كلما كان من المطلوب تنفيذ إجراء على ملف، وصف الملف يتم استخدامه لتحديد الملف.

يتم استخدام هذه القيم دائمًا لـ stdin, stdout, و stderr:

  • 0: معيار الدين
  • 1: مخرج قياسي
  • 2: ستدير

الرد على الأنابيب وإعادة التوجيه

لتسهيل تقديم شخص ما لموضوع ما، هناك تقنية شائعة تتمثل في تعليم نسخة مبسطة من الموضوع. على سبيل المثال، في قواعد اللغة، يُقال لنا أن القاعدة هي “I قبل E، باستثناء C”. ولكن في الواقع، هناك هناك المزيد من الاستثناءات لهذه القاعدة ثم هناك حالات تطيعه.

وعلى نحو مماثل، عندما نتحدث عن stdin, stdout، و stderr من المناسب أن نستعين بالمبدأ المقبول الذي يقول إن العملية لا تعرف ولا تهتم بنقطة انتهاء تدفقاتها الثلاثة القياسية. فهل ينبغي للعملية أن تهتم بما إذا كان ناتجها سيذهب إلى المحطة الطرفية أم أنه سيعاد توجيهه إلى ملف؟ وهل يمكنها حتى أن تميز ما إذا كان مدخلها يأتي من لوحة المفاتيح أم أنه يتم توجيهه إليها من عملية أخرى؟


في الواقع، تعرف العملية ذلك – أو على الأقل يمكنها اكتشاف ذلك، إذا اختارت التحقق – ويمكنها تغيير سلوكها وفقًا لذلك إذا قرر مؤلف البرنامج إضافة هذه الوظيفة.

يمكننا أن نرى هذا التغيير في السلوك بسهولة شديدة. جرّب هذين الأمرين:

ls

ls في نافذة المحطة الطرفية

ls | cat

إخراج ls في نافذة المحطة الطرفية

ال ls يتصرف الأمر بشكل مختلف إذا كان ناتجه (stdout) يتم توجيهه إلى أمر آخر. إنه ls الذي يتحول إلى إخراج عمود واحد، فهو ليس تحويلًا تم إجراؤه بواسطة cat. و ls يفعل الشيء نفسه إذا تم إعادة توجيه إخراجه:


ls > capture.txt

capture.txt في نافذة المحطة الطرفية” data-img-url=”https://static1.howtogeekimages.com/wordpress/wp-content/uploads/2019/08/41.png” src=”https://static1.howtogeekimages.com/wordpress/wp-content/uploads/2019/08/41.png” style=”display:block;height:auto;max-width:100%;”/>

cat capture.txt

ملف cat capture.txt في نافذة المحطة الطرفية

إعادة توجيه stdout وstderr

هناك ميزة في توصيل رسائل الخطأ بواسطة دفق مخصص. وهذا يعني أنه يمكننا إعادة توجيه إخراج الأمر (stdout) إلى ملف ولا يزال بإمكانك رؤية أي رسائل خطأ (stderr) في نافذة المحطة الطرفية. يمكنك الرد على الأخطاء إذا كنت بحاجة إلى ذلك، عند حدوثها. كما يمنع رسائل الخطأ من تلويث الملف الذي stdout تمت إعادة توجيهه إلى.


اكتب النص التالي في محرر واحفظه في ملف يسمى error.sh.

#!/bin/bash
echo "About to try to access a file that doesn't exist"
cat bad-filename.txt

جعل البرنامج النصي قابلاً للتنفيذ باستخدام هذا الأمر:

chmod +x error.sh

يردد السطر الأول من البرنامج النصي النص إلى نافذة المحطة الطرفية، عبر stdout يحاول السطر الثاني الوصول إلى ملف غير موجود. سيؤدي هذا إلى إنشاء رسالة خطأ يتم تسليمها عبر stderr.

قم بتشغيل البرنامج النصي باستخدام هذا الأمر:

./error.sh

./error.sh في نافذة المحطة الطرفية

يمكننا أن نرى أن كلا تياري الإخراج، stdout و stderr، وقد تم عرضها في نوافذ المحطة الطرفية.

الإخراج من البرنامج النصي error.sh في نافذة المحطة الطرفية


دعونا نحاول إعادة توجيه الإخراج إلى ملف:

./error.sh > capture.txt

capture.txt في نافذة المحطة الطرفية” data-img-url=”https://static1.howtogeekimages.com/wordpress/wp-content/uploads/2019/08/3.png” src=”https://static1.howtogeekimages.com/wordpress/wp-content/uploads/2019/08/3.png” style=”display:block;height:auto;max-width:100%;”/>

رسالة الخطأ التي يتم تسليمها عبر stderr لا يزال يتم إرساله إلى نافذة المحطة الطرفية. يمكننا التحقق من محتويات الملف لمعرفة ما إذا كان stdout تم إخراج النتيجة إلى الملف.

cat capture.txt

ملف cat capture.txt في نافذة المحطة الطرفية

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


محتويات ملف capture.txt في نافذة المحطة الطرفية

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

لإعادة التوجيه صراحة stdoutاستخدم تعليمات إعادة التوجيه هذه:

1>

لإعادة التوجيه صراحة stderrاستخدم تعليمات إعادة التوجيه هذه:

2>

دعونا نحاول إجراء اختبارنا مرة أخرى، وهذه المرة سوف نستخدم 2>:

./error.sh 2> capture.txt

إخراج Error.sh غير موجود.

تم إعادة توجيه رسالة الخطأ و stdoutecho تم إرسال الرسالة إلى نافذة المحطة:


يتم إرسال stdout إلى المحطة الطرفية.

دعونا نرى ما هو موجود في ملف capture.txt.

cat capture.txt

ملف cat capture.txt في نافذة المحطة الطرفية

ال stderr الرسالة موجودة في capture.txt كما هو متوقع.

يحتوي ملف Capture.txt على المحتوى الذي نتوقعه.


إعادة توجيه كل من stdout وstderr

بالتأكيد، إذا كان بإمكاننا إعادة توجيه أي منهما stdout أو stderr إلى ملف مستقل عن بعضهما البعض، هل ينبغي أن نكون قادرين على إعادة توجيههما في نفس الوقت، إلى ملفين مختلفين؟

نعم، يمكننا ذلك. هذا الأمر سوف يوجه stdout إلى ملف يسمى capture.txt و stderr إلى ملف يسمى error.txt.

./error.sh 1> capture.txt 2> error.txt

إرسال stderr وstdout إلى ملفين منفصلين.

نظرًا لأن كلا من تدفقي الإخراج – الإخراج القياسي والخطأ القياسي – يتم إعادة توجيههما إلى ملفات، فلا يوجد إخراج مرئي في نافذة المحطة الطرفية. يتم إرجاعنا إلى موجه سطر الأوامر كما لو لم يحدث شيء.

لن يعرض المحطة الطرفية أي شيء، حيث يتم إعادة توجيه الإخراج.


دعونا نتحقق من محتويات كل ملف:

cat capture.txt

cat error.txt

يحتوي ملفينا النصيين error.txt و capture.txt على المعلومات الصحيحة.

إعادة توجيه stdout وstderr إلى نفس الملف

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

يمكننا تحقيق ذلك باستخدام الأمر التالي:

./error.sh > capture.txt 2>&1

دعونا نكسر ذلك.

  • ./error.sh: يقوم بتشغيل ملف البرنامج النصي error.sh.
  • > capture.txt: إعادة توجيه stdout البث إلى ملف capture.txt. > هو اختصار لـ 1>.
  • 2>&1: يستخدم هذا الأمر تعليمات إعادة التوجيه &>. تسمح لك هذه التعليمات بإخبار الغلاف بجعل أحد الدفقات يصل إلى نفس الوجهة التي يصل إليها دفق آخر. في هذه الحالة، نقول “إعادة توجيه الدفق 2، stderr، إلى نفس الوجهة التي يتجه إليها التيار 1، stdout، يتم إعادة توجيهه إلى.”


طريقة مختصرة لإعادة توجيه كلا المخرجات إلى ملف واحد.

لا يوجد مخرج مرئي، وهذا أمر مشجع.

مرة أخرى، لا يوجد إخراج في المحطة.

دعونا نتحقق من ملف capture.txt ونرى ما بداخله.

cat capture.txt

يحتوي ملف Capture.txt بشكل صحيح على مخرجات كل من stderr وstdout.

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


لإعادة توجيه مخرجات التدفق وإلقائها بعيدًا بصمت، قم بتوجيه المخرجات إلى /dev/null.

اكتشاف إعادة التوجيه داخل البرنامج النصي

لقد ناقشنا كيف يمكن للأمر أن يكتشف ما إذا كان يتم إعادة توجيه أي من التدفقات، ويمكنه اختيار تغيير سلوكه وفقًا لذلك. هل يمكننا تحقيق ذلك في نصوصنا الخاصة؟ نعم، يمكننا ذلك. وهي تقنية سهلة للغاية لفهمها واستخدامها.

اكتب النص التالي في محرر واحفظه باسم input.sh.

#!/bin/bash
if ( -t 0 ); then
echo stdin coming from keyboard
else echo stdin coming from a pipe or a file
fi

استخدم الأمر التالي لجعله قابلاً للتنفيذ:

chmod +x input.sh

الجزء الذكي هو اختبار بين قوسين مربعين. ال -t (الطرفية) يعود الخيار true (0) إذا كان الملف المرتبط بوصف الملف ينتهي في نافذة المحطة الطرفيةلقد استخدمنا موصوف الملف 0 كحجة للاختبار، والذي يمثل stdin.

لو stdin إذا تم توصيله بنافذة طرفية، فسوف يثبت الاختبار صحته. إذا stdin إذا تم توصيله بملف أو أنبوب، فسوف يفشل الاختبار.


يمكننا استخدام أي ملف نصي مناسب لإنشاء مدخلات للبرنامج النصي. هنا نستخدم ملفًا يسمى dummy.txt.

./input.sh < dummy.txt

توجيه الإدخال من البرنامج النصي.

يُظهِر الناتج أن البرنامج النصي يدرك أن الإدخال لا يأتي من لوحة المفاتيح، بل من ملف. إذا اخترت ذلك، فيمكنك تغيير سلوك البرنامج النصي وفقًا لذلك.

يتعرف بشكل صحيح على أنه قادم من أنبوب أو ملف.

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

cat dummy.txt | ./input.sh


28-1

يتعرف البرنامج النصي على أن مدخلاته يتم توجيهها إليه. أو بالأحرى، يتعرف مرة أخرى على أن stdin لم يتم توصيل الدفق بنافذة المحطة الطرفية.

يتعرف بشكل صحيح على أنه قادم من أنبوب أو ملف.

دعنا نشغل البرنامج النصي بدون أنابيب أو عمليات إعادة توجيه.

./input.sh

تشغيل البرنامج النصي للإدخال.


ال stdin تم توصيل الدفق بنافذة المحطة الطرفية، ويقوم البرنامج النصي بالإبلاغ عن ذلك وفقًا لذلك.

للتحقق من نفس الشيء مع تدفق الإخراج، نحتاج إلى نص برمجي جديد. اكتب ما يلي في محرر واحفظه باسم output.sh.

#!/bin/bash
if ( -t 1 ); then
echo stdout is going to the terminal window
else
echo stdout is being redirected or piped
fi

استخدم الأمر التالي لجعله قابلاً للتنفيذ:

chmod +x input.sh

التغيير الوحيد المهم في هذا البرنامج النصي هو الاختبار الموجود بين قوسين مربعين. نحن نستخدم الرقم 1 لتمثيل موصوف الملف لـ stdout.

دعنا نحاول ذلك. سنقوم بتوصيل الناتج عبر cat.

./output | cat

32-1

يتعرف البرنامج النصي على أن مخرجاته لا تذهب مباشرة إلى نافذة المحطة الطرفية.


يتم إخراج الإخراج من نافذة المحطة الطرفية.

يمكننا أيضًا اختبار البرنامج النصي عن طريق إعادة توجيه الإخراج إلى ملف.

./output.sh > capture.txt

الإخراج إلى capture.txt

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

نافذة طرفية فارغة أخرى ناتجة عن إرسال الإخراج إلى ملف نصي.


يمكننا إلقاء نظرة داخل ملف capture.txt لمعرفة ما تم التقاطه. استخدم الأمر التالي للقيام بذلك.

cat capture.sh

يحتوي ملف Capture.txt على تقرير يفيد بأن الأمر تم توجيهه.

مرة أخرى، يكشف الاختبار البسيط في البرنامج النصي الخاص بنا أن stdout لم يتم إرسال الدفق مباشرة إلى نافذة المحطة الطرفية.

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

./output.sh

تشغيل output.sh بدون أي وسيطات.

وهذا بالضبط ما نراه.


stdout يذهب إلى المحطة الطرفية.

تيارات الوعي

إن معرفة كيفية معرفة ما إذا كانت البرامج النصية الخاصة بك متصلة بنافذة المحطة الطرفية، أو أنبوب، أو يتم إعادة توجيهها، يسمح لك بتعديل سلوكها وفقًا لذلك.

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

كما هو الحال عادة، فإن المزيد من المعرفة تجلب المزيد من الخيارات.


أضف تعليق