Linux: التدفقات القياسية وإعادة التوجيه
لينكس يعامل كل برنامج كـ"مرشح" — يستقبل الإدخال من مكان ما، يعالجه، ويُخرج النتائج. قنوات الإدخال والإخراج هي التدفقات القياسية.
📋 المتطلبات المسبقة: يجب إكمال
- الدرس 5: عمليات الملفات والدلائل
1. ما ستتعلمه
- مفاهيم المدخل القياسي والمخرج القياسي والخطأ القياسي
- الفرق بين
>و>> 2>لإعادة توجيه الأخطاء&>لإعادة توجيه التدفقات معًا- تطبيقات
/dev/null
2. قصة شاشة مليئة بالأخطاء
(1) الألم: مخرجات مختلطة تصعب إيجاد ما تحتاجه
شغّل شياو مينغ apt update، فاختلطت رسائل النجاح مع رسائل الخطأ الحمراء على الشاشة. أراد فقط حفظ النتائج الناجحة وعرض الأخطاء منفصلة.
(2) فصل المخرجات بإعادة التوجيه
علّمه بوب استخدام إعادة التوجيه:
# حفظ رسائل النجاح في success.log، والأخطاء في error.log
sudo apt update > success.log 2> error.log
# عرض الأخطاء
cat error.log
(3) الفائدة: تحكم دقيق في المخرجات
تعلّم شياو مينغ توجيه مخرجات مختلفة إلى تدفقات منفصلة — ملفات السجل تسجل النجاحات فقط، والطرفية تعرض المعلومات المهمة فقط، والأخطاء محفوظة منفصلة لاستكشافها.
3. نقاط المعرفة
(1) التدفقات القياسية الثلاثة
عند بدء برنامج لينكس، يستقبل تلقائيًا ثلاثة واصفات ملفات:
| واصف الملف | الاسم | الاتصال الافتراضي | الغرض |
|---|---|---|---|
| 0 | stdin | لوحة المفاتيح | إدخال البرنامج |
| 1 | stdout | شاشة الطرفية | مخرج البرنامج العادي |
| 2 | stderr | شاشة الطرفية | مخرج أخطاء البرنامج |
┌──────────┐
stdin ──→│ │──→ stdout
(keyboard)│ Program │ (screen)
│ │──→ stderr
└──────────┘ (screen)
(2) معاملات إعادة التوجيه
| المعامل | المعنى | مثال |
|---|---|---|
> |
كتابة stdout إلى ملف (كتابة فوق) | ls > files.txt |
>> |
إلحاق stdout بملف | echo "done" >> log.txt |
< |
قراءة stdin من ملف | sort < list.txt |
2> |
كتابة stderr إلى ملف | cmd 2> error.log |
2>> |
إلحاق stderr بملف | cmd 2>> error.log |
&> |
كتابة stdout وstderr معًا إلى ملف | cmd &> all.log |
&>> |
إلحاق stdout وstderr معًا بملف | cmd &>> all.log |
2>&1 |
دمج stderr في stdout | cmd > log.txt 2>&1 |
ℹ️ ملاحظة:
>يكتب فوق (محتوى الملف الموجود يُمحى)، بينما>>يُلحق (يضيف في نهاية الملف). استخدم>>عندما تحتاج حفظ السجلات التاريخية؛ واستخدم>عندما تحتاج حالة نظيفة. استخدام>بالخطأ قد يكتب فوق ملفات سجل مهمة.
(3) /dev/null — الثقب الأسود
/dev/null هو ملف جهاز خاص — أي بيانات تُكتب إليه تُهمل، والقراءة منه لا تُعيد شيئًا.
/dev/null هو "جهاز الثقب الأسود" في لينكس — النواة تتجاهل البيانات المكتوبة مباشرة على مستوى المحرك، دون استخدام مساحة قرص، ولا يمتلئ أبدًا. يُستخدم عادةً لكتم مخرجات الأوامر: command &> /dev/null يكتم كل المخرجات تمامًا، وcommand 2> /dev/null يكتم الأخطاء فقط.
# تجاهل كل المخرجات
command > /dev/null 2>&1
# أو الصيغة الأقصر
command &> /dev/null
# تجاهل الأخطاء فقط
command 2> /dev/null
# تجاهل المخرج العادي فقط
command > /dev/null
(4) ▶ مثال: حفظ مخرجات أمر في ملف
# كتابة فوق
ls ~ > home-directory.txt
cat home-directory.txt
# إلحاق
echo "A new line" >> home-directory.txt
echo "Another line" >> home-directory.txt
cat home-directory.txt
الإخراج:
TEXTDesktop Documents Downloads A new line Another line
(5) ▶ مثال: فصل المخرج العادي عن مخرج الخطأ
# حفظ رسائل النجاح، عرض الأخطاء منفصلة
find /etc -name "*.conf" > found.txt 2> errors.txt
# عرض النتائج
echo "=== Found config files ==="
head -5 found.txt
echo "=== Error messages ==="
cat errors.txt
الإخراج:
TEXT=== Found config files === /etc/adduser.conf /etc/ca-certificates.conf /etc/debconf.conf /etc/deluser.conf /etc/fuse.conf === Error messages === find: '/etc/ssl/private': Permission denied
(6) ▶ مثال: دمج المخرجات
# الطريقة 1: &> (bash 4+)
grep -r "error" /var/log/ &> all-results.txt
# الطريقة 2: 2>&1 (أكثر قابلية للنقل)
grep -r "error" /var/log/ > all-results.txt 2>&1
# كلتا الطريقتين تعطيان نفس النتيجة — stdout وstderr يذهبان لنفس الملف
> 💡 نصيحة: ترتيب `2>&1` مهم! `cmd > log.txt 2>&1` صحيح — أولًا أعد توجيه stdout إلى ملف، ثم ادمج stderr في stdout (الذي يشير الآن للملف). إذا كُتبت كـ`cmd 2>&1 > log.txt`، سيتداخل stderr أولًا مع stdout للشاشة، ثم يُعاد توجيه stdout للملف، تاركًا stderr يذهب للشاشة.
الإخراج:
TEXT$ wc -l all-results.txt 42 all-results.txt
(7) ▶ مثال: /dev/null لكتم المخرجات
# تنفيذ صامت تمامًا
sudo apt update > /dev/null 2>&1
# صيغة أقصر
sudo apt update &> /dev/null
# كتم الأخطاء فقط
find / -name "*.py" 2> /dev/null
الإخراج:
TEXT(لا مخرجات — كل الأخطاء والنتائج العادية مكتومة)
(8) ▶ مثال: heredoc — تضمين نص متعدد الأسطر في السكريبتات
# إنشاء ملف إعدادات متعدد الأسطر
cat << EOF > nginx.conf
server {
listen 80;
server_name example.com;
root /var/www/html;
}
EOF
# إلحاق نص متعدد الأسطر
cat << EOF >> ~/.bashrc
# Add PATH
export PATH="\$PATH:\$HOME/scripts"
EOF
# المتغيرات في heredoc لن تُوسَّع (استخدم 'EOF' بين علامتي اقتباس)
cat << 'EOF' > greeting.sh
#!/bin/bash
echo "Hello, $USER" # $USER يبقى كاسم متغير
EOF
الإخراج:
TEXTserver { listen 80; server_name example.com; root /var/www/html; }
(9) ▶ مثال شامل: إدارة المخرجات أثناء تجميع برنامج
# تجميع برنامج C، تسجيل المخرجات والأخطاء منفصلة
gcc main.c -o app \
> build.log \ # Compilation success messages
2> build-errors.log # Compilation error messages
# إذا نجح التجميع، build-errors.log فارغ
# إذا فشل التجميع، اعرض الأخطاء
if [ -s build-errors.log ]; then
echo "❌ Compilation failed, errors:"
cat build-errors.log
else
echo "✅ Compilation successful!"
fi
❓ أسئلة شائعة
س: ما الفرق بين
>و|(أنبوب)؟ ج: \1
س: ماذا يعني
2>&1؟ ج: \1
س: لماذا أستخدم
&>بدلًا من2>&1؟ ج:&>اختصار في bash 4+ أكثر إيجازًا.2>&1أكثر قابلية للنقل (يعمل في sh أيضًا). كلاهما يفعل نفس الشيء.
س: هل
/dev/nullفراغ؟ هل يمكن أن يمتلئ؟ ج: لا. البيانات المكتوبة إلى/dev/nullتُهمل من النواة مباشرة، دون استخدام أي مساحة قرص. هو أساسًا "ثقب أسود بسعة لا نهائية."
س: هل يجب أن تكون EOF في heredop بأحرف كبيرة؟ ج: لا.
EOFمجرد اتفاق؛ يمكنك استخدام أي سلسلة (EOLأوENDأو__EOF__). المهم أن علامتا البداية والنهاية تتطابقان تمامًا.
📖 ملخص
- المدخل القياسي (stdin/0) → البرنامج → المخرج القياسي (stdout/1) + الخطأ القياسي (stderr/2)
>يكتب فوق، و>>يُلحق، و2>يعيد توجيه الأخطاء&>يدمج المخرجات، و/dev/nullيهمل المخرجات2>&1يدمج stderr في stdout (انتبه للترتيب)- heredoc
<< EOF ... EOFيضمّن نصًا متعدد الأسطر في السكريبتات
📝 تمارين
- أساسي (صعوبة ⭐): احفظ مخرجات
ls -la |فيhome-list.txt، ثم ألحق التاريخ الحالي بـ>> - متوسط (صعوبة ⭐⭐): شغّل
find / -name "*.py" 2> errors.txtلعرض أخطاء رفض الصلاحية، ثم استخدم&>لالتقاط stdout وstderr في ملف واحد، واستخدم/dev/nullلكتم مخرج الأخطاء - متقدم (صعوبة ⭐⭐⭐): استخدم heredoc لإنشاء ملف إعدادات بـ5 أسطر محتوى، ثم اكتب سكريبتًا يوضح طرق إعادة التوجيه الأربع (
>و2>و&>و>>) ويشرح متى تستخدم كلًا منها