اذهب إلى المحتوى

البحث في الموقع

المحتوى عن 'سطر أوامر'.

  • ابحث بالكلمات المفتاحية

    أضف وسومًا وافصل بينها بفواصل ","
  • ابحث باسم الكاتب

نوع المحتوى


التصنيفات

  • الإدارة والقيادة
  • التخطيط وسير العمل
  • التمويل
  • فريق العمل
  • دراسة حالات
  • التعامل مع العملاء
  • التعهيد الخارجي
  • السلوك التنظيمي في المؤسسات
  • عالم الأعمال
  • التجارة والتجارة الإلكترونية
  • نصائح وإرشادات
  • مقالات ريادة أعمال عامة

التصنيفات

  • مقالات برمجة عامة
  • مقالات برمجة متقدمة
  • PHP
    • Laravel
    • ووردبريس
  • جافاسكربت
    • لغة TypeScript
    • Node.js
    • React
    • Vue.js
    • Angular
    • jQuery
    • Cordova
  • HTML
  • CSS
    • Sass
    • إطار عمل Bootstrap
  • SQL
  • لغة C#‎
    • ‎.NET
    • منصة Xamarin
  • لغة C++‎
  • لغة C
  • بايثون
    • Flask
    • Django
  • لغة روبي
    • إطار العمل Ruby on Rails
  • لغة Go
  • لغة جافا
  • لغة Kotlin
  • لغة Rust
  • برمجة أندرويد
  • لغة R
  • الذكاء الاصطناعي
  • صناعة الألعاب
  • سير العمل
    • Git
  • الأنظمة والأنظمة المدمجة

التصنيفات

  • تصميم تجربة المستخدم UX
  • تصميم واجهة المستخدم UI
  • الرسوميات
    • إنكسكيب
    • أدوبي إليستريتور
  • التصميم الجرافيكي
    • أدوبي فوتوشوب
    • أدوبي إن ديزاين
    • جيمب GIMP
    • كريتا Krita
  • التصميم ثلاثي الأبعاد
    • 3Ds Max
    • Blender
  • نصائح وإرشادات
  • مقالات تصميم عامة

التصنيفات

  • مقالات DevOps عامة
  • خوادم
    • الويب HTTP
    • البريد الإلكتروني
    • قواعد البيانات
    • DNS
    • Samba
  • الحوسبة السحابية
    • Docker
  • إدارة الإعدادات والنشر
    • Chef
    • Puppet
    • Ansible
  • لينكس
    • ريدهات (Red Hat)
  • خواديم ويندوز
  • FreeBSD
  • حماية
    • الجدران النارية
    • VPN
    • SSH
  • شبكات
    • سيسكو (Cisco)

التصنيفات

  • التسويق بالأداء
    • أدوات تحليل الزوار
  • تهيئة محركات البحث SEO
  • الشبكات الاجتماعية
  • التسويق بالبريد الالكتروني
  • التسويق الضمني
  • استسراع النمو
  • المبيعات
  • تجارب ونصائح
  • مبادئ علم التسويق

التصنيفات

  • مقالات عمل حر عامة
  • إدارة مالية
  • الإنتاجية
  • تجارب
  • مشاريع جانبية
  • التعامل مع العملاء
  • الحفاظ على الصحة
  • التسويق الذاتي
  • العمل الحر المهني
    • العمل بالترجمة
    • العمل كمساعد افتراضي
    • العمل بكتابة المحتوى

التصنيفات

  • الإنتاجية وسير العمل
    • مايكروسوفت أوفيس
    • ليبر أوفيس
    • جوجل درايف
    • شيربوينت
    • Evernote
    • Trello
  • تطبيقات الويب
    • ووردبريس
    • ماجنتو
    • بريستاشوب
    • أوبن كارت
    • دروبال
  • الترجمة بمساعدة الحاسوب
    • omegaT
    • memoQ
    • Trados
    • Memsource
  • برامج تخطيط موارد المؤسسات ERP
    • تطبيقات أودو odoo
  • أنظمة تشغيل الحواسيب والهواتف
    • ويندوز
    • لينكس
  • مقالات عامة

التصنيفات

  • آخر التحديثات

أسئلة وأجوبة

  • الأقسام
    • أسئلة البرمجة
    • أسئلة ريادة الأعمال
    • أسئلة العمل الحر
    • أسئلة التسويق والمبيعات
    • أسئلة التصميم
    • أسئلة DevOps
    • أسئلة البرامج والتطبيقات

التصنيفات

  • كتب ريادة الأعمال
  • كتب العمل الحر
  • كتب تسويق ومبيعات
  • كتب برمجة
  • كتب تصميم
  • كتب DevOps

ابحث في

ابحث عن


تاريخ الإنشاء

  • بداية

    نهاية


آخر تحديث

  • بداية

    نهاية


رشح النتائج حسب

تاريخ الانضمام

  • بداية

    نهاية


المجموعة


النبذة الشخصية

تم العثور على 7 نتائج

  1. تتوفر آلاف الأوامر لمستخدمي سطر أوامر لينُكس، لكن كيف تستطيع تذكرها جميعًا؟ الجواب هو أنَّك لا تحتاج إلى ذلك؛ فالقوة الحقيقية للحاسوب تظهر عندما يقوم بالعمل عوضًا عنك، وذلك باستخدام سكربتات الصدفة (Shell Scripts) لأتمتة المهام. ما هي سكربتات الصدفة؟ بأبسط تعريفٍ لها: سكربت الصّدفة هو ملف يحتوي على سلسلة من الأوامر التي تقرأها الصَدَفة (shell) وتنفِّذ الأوامر التي فيها كما لو أنها أُدخِلَت مباشرةً من سطر الأوامر. الصَدَفة هي برمجية فريدة من نوعها، وذلك لأنها توفر واجهة سطرية (أي من سطر الأوامر) للتعامل مع النظام مع كونها مُفسِّر (interpreter) للسكربتات. وكما سنرى لاحقًا، أيّ شيء يمكنك القيام به في سطر الأوامر يمكن فعله في سكربتات الصدفة، وأغلبية الأشياء التي تستطيع كتابتها في سكربتات الصدفة يمكن تنفيذها مباشرةً في سطر الأوامر. سنُركِّز في هذه السلسلة على الميزات التي تُستخدم عادةً عند كتابة السكربتات. كتابة أول سكربت لك يجب أن تفعل ثلاثة أشياء لكي تكتب سكربت شِل: كتابة السكربت السماح للصَدَفة (shell) بتنفيذه (أي إعطاؤه إذن التنفيذ x) وضعه في مكانٍ تستطيع الصَدَفة العثور عليه فيه سكربت الصّدفة ما هو إلا ملف يحتوي على نص عادي؛ فلا يلزمك إلا محرر نصي لكتابة سكربتات الصدفة. "المحرر النصي" هو برنامج -يشبه برامج التحرير المكتبي- يستطيع قراءة وكتابة ملفات ASCII النصية. هنالك الكثير من المحررات النصية المتوفرة على نظام لينُكس سواءً كانت سطريةً (أي تعمل من سطر الأوامر) أم رسوميةً؛ هذه قائمة تحتوي على أشهرها: vi أو vim: المحرر النصي السطري الشهير في نظام يونكس المعروف بصعوبة فهم بنية الأوامر فيه؛ لكنه -على الكفة الأخرى- محرر كفؤ وقوي جدًا وخفيف وسريع. سيؤتي تعلم vi أُكله لأنه متوفر على جميع الأنظمة الشبيهة بِيونكس (Unix-like). النسخة الموجودة من vi في أغلبية توزيعات لينُكس هي النسخة المُحسَّنة التي تدعى vim. Emacs: كبير المحررين في عالم النصوص الذي برمَجَه ريتشارد ستالمان. يحتوي محرر Emac (أو يستطيع أن يحتوي) على كل ميزة يمكن أن تتواجد في أي محرر نصي على الإطلاق! يجدر بالذكر أنَّ مستخدمي vi و Emacs يشتبكون مع بعضهم (على الإنترنت بالطبع!) محاولين إثبات أنَّ محررهم هو الأفضل. nano: هو برنامج سطري شبيه بالمحرر النصي المضمَّن مع عميل البريد الإلكتروني pine، وهو سهل الاستخدام لكن ميزاته قليلة. أنصح عادةً باستخدام nano لمَن يتعامل مع سطر الأوامر لأول مرة. gedit: هو محرر رسومي يأتي مع سطح مكتب غنوم (Gnome). kate: هو محرر رسومي ذو ميزات متقدمة تُسهِّل كتابة السكربتات ويأتي مع حزمة برمجيات كدي (KDE). افتح الآن محررك النصي المفضَّل واكتب فيه أول سكربت لك: !/bin/bash My first script echo "Hello World!" إذا كنتَ سريع البديهة، فمن المرجح أنَّك عرفت كيف تلصق النصوص في المحرر النصي الذي اخترته. إذا فتحت أيّ كتابٍ عن البرمجة من قبل، فستتعرف مباشرةً على برنامج "Hello World" التقليدي الذي يُجسِّده المثال السابق. احفظ الملف باسمٍ ذي معنى (ربما hello_world). أول سطر في الملف مهمٌ وله تأثيرٌ خاص، إذ يُسمى "shebang" وسيخبر الصَدَفة أيّ مُفسِّر عليها استدعاؤه لتفسير هذا السكربت، الذي هو في حالتنا ‎/bin/bash. تستعمل لغات السكربتات الأخرى مثل perl و awk و tcl و php و python هذه الآلية. السطر الثاني في الملف هو تعليق. أيّ شيء يأتي بعد علامة يُعتبر تعليقًا وستتجاهله الصَدَفة تمامًا. لكن عندما يزداد تعقيد برامجك فستصبح التعليقات مهمة جدًا، إذ يستعملها المبرمجون لشرح ما حولها لتسهيل فهم الآخرين له. آخر سطر في السكربت السابق هو الأمر echo الذي يطبع ما يليه على الشاشة. ضبط الأذونات علينا الآن إعطاء إذن التنفيذ لسكربت الصّدفة الذي كتبناه، وذلك بالأمر chmod كما يلي: $ chmod 755 hello_world الإذن "755" سيسمح لك بالقراءة والكتابة والتنفيذ، بينما سيتمكن بقية المستخدمين من قراءة وتنفيذ السكربت فقط. أما إذا أردت أن يكون السكربت خاصًا بك (أي أنَّك الوحيد الذي تستطيع قراءته وتنفيذه) فضع "700" بدلًا من "755". راجع درس مبادئ أذونات الملفات على لينكس للمزيد من المعلومات. وضع الملف في المكان الصحيح تستطيع عند هذه المرحلة تشغيل السكربت كما يلي: $ ./hello_world يجب أن تشاهد العبارة "Hello World!‎" على الشاشة، وإن لم ترها فانظر أين حفظت السكربت، وانتقل إلى ذاك المجلد (بالأمر cd) ثم جرب مرِّة أخرى. علينا الآن أن نتوقف قليلًا ونتحدث عن المسارات. عندما تكتب اسم أحد الأوامر فلن يبحث النظام (أو بالأحرى "الصَدَفة") عن ذاك البرنامج في جميع مجلدات حاسوبك لأن ذلك سيستغرق وقتًا طويلًا؛ ولكنك لاحظت أيضًا كيف أنَّك لا تحتاج إلى تحديد المسار الكامل للبرامج التي تريد تشغيلها وستظن أنَّ الصَدَفة تعرف أين تجدها. حسنًا، أنت محق: الصَدَفة تعرف أين تجد البرمجيات، لأنها -أي الصَدَفة- تحتوي على قائمة بالمجلدات التي تتواجد فيها الملفات التنفيذية (أي البرامج)، وستبحث داخل المجلدات في تلك القائمة عن البرامج، فإن لم تجد ما تبحث عنه في أحد تلك المجلدات فستظهر رسالة الخطأ الشهيرة command not found. يمكنك أن ترى تلك القائمة بكتابة الأمر الآتي: $ echo $PATH الذي سيطبع قائمة مفصولة بنقطتين رأسيتين للمجلدات التي سيتم البحث فيها عن البرامج إذا لم يُحدَّد مسارها الكامل. لاحظ كيف أننا حدَّدنا المسار (‎./‎) عند محاولتنا تشغيل السكربت سابقًا. يمكنك إضافة مجلدات إلى تلك القائمة باستخدام الأمر الآتي، حيث directory هو مسار المجلد الذي تريد إضافته: $ export PATH=$PATH:directory لكن من المستحسن أن تُعدِّل ملف ‎.bashrc‎ أو ‎.profile (اعتمادًا على توزيعتك) لتضمين الأمر السابق فيه، وبهذا سيُنفَّذ في كل مرّة تُسجِّل دخولك فيها. تسمح بعض توزيعات لينُكس بإنشاء مجلد خاص بكل مستخدم ليضع فيه برامجه الشخصية، ويدعى ذاك المجلد bin وهو مجلد فرعي موجود في مجلد المنزل (home) الخاص بك. إن لم يكن موجودًا، فتستطيع إنشاءه بالأمر: $ mkdir bin انقل السكربت إلى مجلد bin (ربما تستخدم الأمر mv) ثم اكتب: $ hello_world وسيعمل السكربت. لاحظ أنَّك قد تحتاج في بعض التوزيعات (مثل أوبنتو) إلى بدء جلسة (session) جديدة حتى تتعرَّف الصَدَفة على المجلد bin. ترجمة -وبتصرّف- للمقال Writing Your First Script And Getting It To Work لصاحبه William Shotts.
  2. لدينا السكربت التالي: #!/bin/bash # sysinfo_page - A script to produce a system information HTML file ##### Constants TITLE="System Information for $HOSTNAME" RIGHT_NOW=$(date +"%x %r %Z") TIME_STAMP="Updated on $RIGHT_NOW by $USER" ##### Functions system_info() { echo "<h2>System release info</h2>" echo "<p>Function not yet implemented</p>" } # end of system_info show_uptime() { echo "<h2>System uptime</h2>" echo "<pre>" uptime echo "</pre>" } # end of show_uptime drive_space() { echo "<h2>Filesystem space</h2>" echo "<pre>" df echo "</pre>" } # end of drive_space home_space() { # Only the superuser can get this information if [ "$(id -u)" = "0" ]; then echo "<h2>Home directory space by user</h2>" echo "<pre>" echo "Bytes Directory" du -s /home/* | sort -nr echo "</pre>" fi } # end of home_space ##### Main cat <<- _EOF_ <html> <head> <title>$TITLE</title> </head> <body> <h1>$TITLE</h1> <p>$TIME_STAMP</p> $(system_info) $(show_uptime) $(drive_space) $(home_space) </body> </html> _EOF_ تعمل أغلبية الميزات التي فيه عملًا سليمًا، لكن هنالك بعض الميزات التي أرغب بإضافتها: أريد تحديد اسم ملف الخرج في سطر الأوامر، بالإضافة إلى ضبط اسم ملف افتراضي إن لم يُحدِّد المستخدم اسم الملف. أريد توفير نمط تفاعلي يسأل المستخدم عن اسم الملف ويُحذِّر المستخدم إن كان الملف موجودًا ويسأله إذا كان يريد إعادة الكتابة فوقه. من البديهي توفر خيار للمساعدة يعرض رسالة توضِّح كيفية الاستخدام. تتطلب جميع الميزات السابقة استخدام الخيارات والوسائط في سطر الأوامر، وتوفِّر لنا الصَدَفة المعاملات الموضعية (positional parameters) للوصول إليها. المعاملات الموضعية هي سلسلة من المتغيرات (من ‎$0‎ إلى ‎$9) التي تحتوي على قيم الوسائط في سطر الأوامر. لنتخيل تنفيذ الأمر الآتي: $ some_program word1 word2 word3 إذا كان some_program سكربت صَدَفة، فسيستطيع قراءة كل عنصر من عناصر السطر السابق لأنَّ المعاملات الموضعية تحتوي على ما يلي: سيحتوي المتغير ‎$0 على "some_program" سيحتوي المتغير ‎$1 على "word1" سيحتوي المتغير ‎$2 على "word2" سيحتوي المتغير ‎$3 على "word3 هذا هو السكربت الذي تستطيع تجربته لتشاهد ما سبق عمليًا: #!/bin/bash echo "Positional Parameters" echo '$0 = ' $0 echo '$1 = ' $1 echo '$2 = ' $2 echo '$3 = ' $3 اكتشاف وجود وسائط في سطر الأوامر عليك عادةً التحقق من وجود وسائط لكي يتصرَّف برنامجك وفقها؛ وهنالك طريقتان لفعل ذلك. أولهما هي التحقق من احتواء المتغير ‎$1 لأي قيمة كما يلي: #!/bin/bash if [ "$1" != "" ]; then echo "Positional parameter 1 contains something" else echo "Positional parameter 1 is empty" fi تحتوي الصَدَفة على متغير اسمه ‎$#‎ الذي يحتوي على عدد الوسائط في سطر الأوامر، وهذه هي الطريقة الثانية. #!/bin/bash if [ $# -gt 0 ]; then echo "Your command line contains $# arguments" else echo "Your command line contains no arguments" fi خيارات سطر الأوامر العديد من البرامج، وخصوصًا تلك التي أتت من مشروع GNU، تدعم خيارات طويلة ومختصرة لسطر الأوامر. فمثلًا، ستستعمل الخيار المختصر ‎-h لعرض رسالة المساعدة لأغلبية البرامج أو الخيار الطويل ‎--help. تُسبَق أسماء الخيارات الطويلة عادةً بشرطتَين (--). سنستعمل هذا العرف في سكربتاتنا. interactive= filename=~/sysinfo_page.html while [ "$1" != "" ]; do case $1 in -f | --file ) shift filename=$1 ;; -i | --interactive ) interactive=1 ;; -h | --help ) usage exit ;; * ) usage exit 1 esac shift done الشيفرة السابقة معقدة بعض الشيء، تحملني قليلًا ريثما أشرحها لك. السطران الأولان سهلان، لم نضبط قيمةً للمتغير interactive، مما يُشير إلى أنَّ المستخدم لم يطلب الوضع التفاعلي، ثم ضبطنا المتغير filename إلى قيمة افتراضية، حيث سيُستخدَم هذا الاسم إن لم يُحدَّد اسمٌ آخر في سطر الأوامر. أصبح لدينا الآن قيمٌ افتراضية في حال لم يضع المستخدم أيّة خيارات في سطر الأوامر. أنشأنا بعد ذلك حلقة while التي تمر على جميع عناصر سطر الأوامر وتتحقق من قيمها عبر كتلة case، التي تكتشف وضع كل خيار من الخيارات الممكنة وتتعامل معه كما يجب. الجزء المهم في السكربت السابق هو آلية عمل حلقة التكرار. تعتمد الحلقة السابقة على الأمر shift. الأمر shift هو أمرٌ مضمَّن في الصَدَفة ويتعامل مع المعاملات الموضعية، حيث يؤدي إلى "إزاحة" أرقام جميع المعاملات وذلك بإنقاص 1 منها وذلك في كل مرة يُستدعى فيها. سيصبح ‎$2 -على سبيل المثال- ‎$1، و ‎$3 سيصبح ‎$2، و ‎ $4سيصبح ‎$3، وهكذا. جرِّب السكربت الآتي: #!/bin/bash echo "You start with $# positional parameters" # Loop until all parameters are used up while [ "$1" != "" ]; do echo "Parameter 1 equals $1" echo "You now have $# positional parameters" # Shift all the parameters down by one shift done الحصول على وسيط أحد الخيارات يتطلب الخيار ‎-f ذكر اسم الملف الذي ستُحفَظ فيه المخرجات بعده. يمكننا استخدام shift مرةً أخرى للحصول على اسم العنصر التالي من وسائط سطر الأوامر وإسناد قيمته إلى المتغير filename. سنتحقق لاحقًا من قيمة filename للتأكد أنَّها تُمثِّل اسم ملف صحيح. دمج مفسر خيارات سطر الأوامر مع السكربت علينا الآن نقل بعض الأقسام من مكانها، وإضافة دالة لعرض طريقة استخدام الخيارات التي أضفناها أخيرًا إلى السكربت، وسنضيف اختبارًا للتأكد من صحة تفسير خيارات سطر الأوامر. سيبدو السكربت بعد التعديل كالآتي: #!/bin/bash # sysinfo_page - A script to produce a system information HTML file ##### Constants TITLE="System Information for $HOSTNAME" RIGHT_NOW=$(date +"%x %r %Z") TIME_STAMP="Updated on $RIGHT_NOW by $USER" ##### Functions system_info() { echo "<h2>System release info</h2>" echo "<p>Function not yet implemented</p>" } # end of system_info show_uptime() { echo "<h2>System uptime</h2>" echo "<pre>" uptime echo "</pre>" } # end of show_uptime drive_space() { echo "<h2>Filesystem space</h2>" echo "<pre>" df echo "</pre>" } # end of drive_space home_space() { # Only the superuser can get this information if [ "$(id -u)" = "0" ]; then echo "<h2>Home directory space by user</h2>" echo "<pre>" echo "Bytes Directory" du -s /home/* | sort -nr echo "</pre>" fi } # end of home_space write_page() { cat <<- _EOF_ <html> <head> <title>$TITLE</title> </head> <body> <h1>$TITLE</h1> <p>$TIME_STAMP</p> $(system_info) $(show_uptime) $(drive_space) $(home_space) </body> </html> _EOF_ } usage() { echo "usage: sysinfo_page [[[-f file ] [-i]] | [-h]]" } ##### Main interactive= filename=~/sysinfo_page.html while [ "$1" != "" ]; do case $1 in -f | --file ) shift filename=$1 ;; -i | --interactive ) interactive=1 ;; -h | --help ) usage exit ;; * ) usage exit 1 esac shift done # Test code to verify command line processing if [ "$interactive" = "1" ]; then echo "interactive is on" else echo "interactive is off" fi echo "output file = $filename" # Write page (comment out until testing is complete) # write_page > $filename إضافة النمط التفاعلي يمكن إضافة النمط التفاعلي بهذه الشيفرة: if [ "$interactive" = "1" ]; then response= echo -n "Enter name of output file [$filename] > " read response if [ -n "$response" ]; then filename=$response fi if [ -f $filename ]; then echo -n "Output file exists. Overwrite? (y/n) > " read response if [ "$response" != "y" ]; then echo "Exiting program." exit 1 fi fi fi تحققنا أولًا من أنَّ النمط التفاعلي مُفعَّل، وإلا فلا حاجة إلى فعل شيء. ثم سألنا المستخدم عن اسم الملف؛ لاحظ طريقة صياغة السؤال: echo -n "Enter name of output file [$filename] > " سنعرض القيمة الحالية للمتغير filename، لأنَّه لو ضغط المستخدم على زر Enter دون كتابة أيّ شيء، فستُستخدم القيمة الافتراضية للمتغير filename؛ ويتم ذلك عبر السطرين اللذان يليانه، حيث يتحققا من قيمة response؛ فإن لم تكن قيمة response فارغةً، فستُسنَد قيمة response إلى المتغير filename. وإلا فستُترَك قيمة filename على حالها، محتفظةً بقيمتها الافتراضية. بعد أن يُدخِل المستخدم اسم ملف الخرج، فسنتحقق من أنَّه موجود، فإن كان موجودًا، فسنسأل المستخدم إن كان يريد استبداله، وإن لم يكن جواب المستخدمy، فسينتهي تنفيذ البرنامج دون كتابة الملف. ترجمة -وبتصرّف- للمقال Positional Parameters لصاحبه William Shotts.
  3. بعد أن ازدادت السكربتات التي نكتبها تعقيدًا، فأحببت أن أشير إلى بعض الأخطاء الشائعة التي قد تصادفك أثناء مسيرتك. سنتعرض في هذا الدرس مثالًا ونعمل على تحليل الأخطاء التي قد نرتكبها، ولنسمِّ ذاك السكربت trouble.bash، تأكد من كتابة السكربت كما هو موجود حرفيًا. #!/bin/bash number=1 if [ $number = "1" ]; then echo "Number equals 1" else echo "Number does not equal 1" fi يجب أن يُخرِج السكربت السابق السطر "Number equals 1"، لأنَّ المتغير number يساوي 1، إن لم تحصل على المخرجات التي توقعتها، فتحقق من صحة كتابتك للسكربت، فربما ارتكبتَ خطأً… المتغيرات الفارغة عدِّل السطر الثالث من السكربت من: number=1 إلى: number= ثم شغِّل السكربت مرةً أخرى، وستحصل هذه المرة على المخرجات الآتية: $ ./trouble.bash /trouble.bash: [: =: unary operator expected. Number does not equal 1 كما لاحظت، عَرَضَت الصَدَفة bash رسالة خطأ عندما شغلنا السكربت، وربما ظننتَ أنَّ حذف القيمة "1" من السطر الثالث قد أدى إلى خطأٍ بنيوي (syntax error) لكن هذا ليس صحيحًا، ألقِ نظرةً إلى رسالة الخطأ مجددًا: ./trouble.bash: [: =: unary operator expected يمكننا ملاحظة أنَّ ‎./trouble.bash يُبلِّغ عن الخطأ، الذي يرتبط -بشكلٍ أو بآخر- مع ]؛ تذكَّر أنَّ ] هو اختصارٌ للأمر المُضمَّن في الصَدَفة test. ومن رسالة الخطأ السابقة استطعنا تحديد أنَّ الخطأ يحدث في السطر الخامس وليس الثالث. عليّ القول بادئ الأمر أنَّه لا توجد أيّة مشكلة في السطر الثالث، حيث number=‎ صحيحة بنيويًا؛ فقد ترغب في بعض الأحيان بحذف القيمة المُخزَّنة في متغيّر. يمكنك التحقق من سلامة هذه الصياغة بكتابتها وتجربتها في سطر الأوامر: $ number= $ أرأيت! لا توجد رسالة خطأ، لكن ما هو الشيء الخاطئ في السطر الخامس؟ لقد جربناه قبل تعديل السكربت ولم يكن يسبب أيّة مشاكل. لكي نفهم هذا الخطأ، علينا أن ننظر إلى الموضوع من وجهة نظر الصَدَفة. وَضَعَت الصَدَفة، في السطر الخامس، قيمة المتغير number عندما رأت ‎$number. ففي أول محاولة لتشغيل السكربت (أي عندما كان number=1)، بدَّلَت الصدفة المتغير ‎$number بالرقم 1 كما يلي: if [ 1 = "1" ]; then لكننا عندما أزلنا قيمة المتغير (number=‎)، فستحاول الصدفة تنفيذ ما يلي: if [ = "1" ]; then وهذا خطأ، ويُفسِّر أيضًا ما تبقى من رسالة الخطأ التي حصلنا عليها. المُعامِل = هو معامِل ثنائي، الذي يعني أنَّه يتوقع وجود عنصرين (كل عنصر على طرف). وما تحاول الصَدَفة إخبارنا به هو أنَّ هنالك عنصرٌ واحدٌ فقط، ولهذا يجب وضع معامل أحادي (مثل !) الذي يتطلب وجود عنصر وحيد فقط. علينا تعديل السطر الخامس إلى ما يلي لحل هذه المشكلة: if [ "$number" = "1" ]; then وسترى الصَدَفة ما يلي (إذا كانت قيمة number=‎): if [ "" = "1" ]; then وبهذا تجنبنا هذا الخطأ. تعلمنا من هذا الخطأ أمرًا مهمًا عند كتابة السكربتات: خذ بعين الاعتبار ماذا سيحدث لو كانت قيمة أحد المتغيرات فارغة. غياب إحدى علامات الاقتباس عدِّل السطر السادس وأزل علامة إغلاق الاقتباس من نهاية السطر: echo "Number equals 1 ثم شغِّل السكربت مرةً أخرى وستحصل على: $ ./trouble.bash ./trouble.bash: line 8: unexpected EOF while looking for matching " ./trouble.bash: line 10 syntax error: unexpected end of file هذه مشكلةٌ أخرى شائعةٌ تُسبِّب مشاكل في أماكن أخرى في السكربت. ماذا يحدث لو استمرت الصَدَفة بحثها عن علامة إغلاق الاقتباس لمعرفة نهاية سلسلةٍ نصيةٍ ما، لكنها وصلت إلى نهاية الملف ولم تجدها. يصعب كثيرًا اكتشاف هذا النوع من الأخطاء في السكربتات الطويلة؛ وهذا أحد الأسباب التي تدفعك لتجربة السكربتات بين الحين والآخر عندما تكتبها لوجود كمية قليلة من الشيفرات الجديدة التي عليك اختبارها. أرى أيضًا أنَّ استخدام المحررات النصيّة التي توفِّر تلوينًا للشيفرات يساعد كثيرًا في الكشف عن مثل هذه الأخطاء. عزل مكان المشكلة قد تكون عملية إيجاد الأخطاء والعِلل في برنامجك صعبة ومحبطة، هذه بعض التقنيات التي قد تستفيد منها: اعزل أجزاءً من الشيفرات بوضع علامة تعليق قبل الأسطر التي لا تريد أن تنفذها الصَدَفة. طبِّق هذا على كتلة من الشيفرات لكي ترى إن اختفت مشكلة معيّنة. وبهذه الآلية ستعرف ما هو الجزء الذي يسبب (أو لا يسبب) المشكلة. على سبيل المثال، لو عدنا إلى السكربت الذي فيه علامة اقتباس ناقصة، فيمكننا أن نعزل المشكلة كالآتي: #!/bin/bash number=1 if [ $number = "1" ]; then echo "Number equals 1 #else # echo "Number does not equal 1" fi سنعلم بعد وضع عبارة else في تعليق ثم تشغيل السكربت أنَّ المشكلة ليس في عبارة else حتى لو أشارت رسالة الخطأ إلى ذلك. استخدم الأمر echo للتحقق من القيم. فبعد أن تكتسب خبرة في تتبع العلل، ستكتشف أنَّ العلل ستتواجد في مكانٍ مختلف عن المكان الذي تتوقع وجودها فيه. إحدى المشاكل الشائعة هي افتراضك أنَّ التسلسل المنطقي لبرنامجك صحيحٌ تمامًا، وعندما ترى مشكلة في مرحلة ما في البرنامج فستفترض أنَّها موجودة هناك؛ وهذا خاطئ في معظم الحالات. يمكنك وضع أوامر echo في الشيفرة أثناء محاولة تنقيح (debugging) الأخطاء لكي تحصل على رسائل تؤكد لك أنَّ البرنامج يعمل كما تتوقع. هنالك نوعان من الرسائل التي عليك وضعها. الغرض من أول نوع هو الإعلان أنَّ التنفيذ قد وصل إلى مكان معيّن في البرنامج، ولقد رأينا ذلك سابقًا عند كتابتنا لشيفرات وهمية في الدوال التي أضفناها. وهذا مفيد لكي تعلم أنَّ مسار تنفيذ البرنامج مماثل تمامًا لما نتوقعه. النوع الثاني يعرض قيم المتغيرات المستخدمة في الحسابات أو الاختبارات. قد تجد في بعض الأحيان قسمًا من السكربت لا يُنفَّذ تنفيذًا سليمًا لأنك افترضت أنَّ شيئًا ما في ما سبقه من الشيفرات صحيحٌ؛ إلا أنَّ فيه مشكلةً تؤدي إلى فشل تنفيذ ما يليه من الشيفرات. مراقبة تشغيل السكربت من الممكن أنَّ تعرض لك bash ما الذي يحدث عندما تُشغِّل السكربت. وذلك بإضافة الخيار ‎-x في أول سطر من السكربت كما يلي: #!/bin/bash -x وعندما ستُشغِّل السكربت، فستعرض bash كل سطر ستحاول تنفيذه (بعد تعويض قيم المتغيرات…). تُسمى هذه التقنية بالتتبع (tracing)، وهذا مثالٌ عنها: $ ./trouble.bash + number=1 + '[' 1 = 1 ']' + echo 'Number equals 1' Number equals 1 تستطيع أيضًا أن تستعمل الأمر set داخل السكربت لتفعيل أو تعطيل التتبع. استخدم set -x لتشغيل التتبع و set +x لتعطيل التتبع، مثال: #!/bin/bash number=1 set -x if [ $number = "1" ]; then echo "Number equals 1" else echo "Number does not equal 1" fi set +x ترجمة -وبتصرّف- للمقال Stay Out Of Trouble لصاحبه William Shotts.
  4. سنشرع في بناء تطبيق مفيد بدءًا من هذا الدرس، سيُنتِج هذا التطبيق مستند HTML يحتوي على معلومات عن نظامك. قضيتُ وقتًا طويلًا في التفكير حول الطريقة التي عليّ اتباعها لشرح برمجة سكربتات الصدفة، ووجدت أنَّ الطريقة التي اعتمدتها مختلفة عن أغلبية الشروحات التي رأيتها، فالأغلبية تُفضِّل شرحًا هيكليًا لمختلف ميزات الصَدَفة bash، ويفترضون أنَّ لديك معرفة مسبقة مع إحدى لغات البرمجة؛ وعلى الرغم من أنني لا أعتبر أنَّ لديك خلفية برمجية، إلا أنني مدرك أنَّ نسبة كبيرة من الأشخاص العاملين في مجال التقنية يعرفون البنية الأساسية لصفحات HTML، لذلك سيُنتِج برنامجنا صفحة ويب. سنكتشف ميزات الصَدَفة bash أثناء بنائنا للسكربت، وسنتعرف على الأدوات اللازمة لحل المشكلات التي ستواجهنا. كتابة ملف HTML باستخدام سكربت كما تعلم، تكون بنية ملف HTML كالآتي: <html> <head> <title> The title of your page </title> </head> <body> Your page content goes here. </body> </html> بأخذ ذلك بعين الاعتبار، يمكننا أن نكتب سكربتًا يمكنه إخراج المحتوى السابق: #!/bin/bash # sysinfo_page - A script to produce an html file echo "<html>" echo "<head>" echo " <title>" echo " The title of your page" echo " </title>" echo "</head>" echo "" echo "<body>" echo " Your page content goes here." echo "</body>" echo "</html>" يمكن أن يُستخدم السكربت كالآتي (تذكَّر أنَّ الرمز < هو رمز إعادة توجيه المخرجات، وهنا سنعيد توجيه المخرجات إلى ملف باسم sysinfo_page.html): $ sysinfo_page > sysinfo_page.html قيل أنَّ أعظم المبرمجين قدرًا هم أكسلهم! حيث يكتبون برامج ليريحوا أنفسهم من بعض الأعمال؛ وبالمثِل: عندما يكتب المبرمجون الأذكياء برنامجًا، فإنهم يحاولون تقليل مقدار الكتابة التي يكتبونها. أول تحسين سنفعله للسكربت هو التخلص من الاستعمال المتكرر لأمر echo والاستعاضة عنه بأمرٍ واحد (سنحيط كامل مستند HTML بعلامات اقتباس): #!/bin/bash # sysinfo_page - A script to produce an HTML file echo "<html> <head> <title> The title of your page </title> </head> <body> Your page content goes here. </body> </html>" أصبح من الممكن احتواء الأسطر الجديدة في النص داخل علامتَي الاقتباس، وبهذا يمكن أن يمتد الوسيط (argument) المُمرَّر إلى الأمر echo على أكثر من سطر. بغض النظر أنَّ ما سبق تحسينٌ واضحٌ، إلا أنَّ فيه قصورًا لأنَّ شيفرات HTML تحتوي عادةً على علامات اقتباس، مما يجعلها تتعارض مع علامات الاقتباس المحيطة بالوسيط، لكن يمكننا "تهريب" (escape) علامة الاقتباس بوضع شرطة خلفية مائلة \ قبلها. لكننا نريد تجنب كتابة المزيد من الأحرف! إذًا علينا البحث عن طريقة أفضل لطباعة النص. لحسن الحظ توفر لنا الصَدَفة bash طريقةً لفعل ذلك اسمها here script. #!/bin/bash # sysinfo_page - A script to produce an HTML file cat << _EOF_ <html> <head> <title> The title of your page </title> </head> <body> Your page content goes here. </body> </html> _EOF_ here script (يُسمى أحيانًا here document) هو شكل من أشكال إعادة توجيه المخرجات، الذي يوفِّر طريقةً لتضمين محتوى سيُمرِّر إلى مجرى الدخل القياسي (standard input stream) لأحد الأوامر. مُرِّرَت -في المثال السابق- كتلةٌ نصيةٌ إلى مجرى الدخل القياسي للأمر cat. الشكل العام لإنشاء here script: command << token content to be used as command's standard input token يمكن اختيار أي سلسلة نصية لكي تكون العلامة الرمزية (token)، لكنني استخدمت __EOF__ ‏(EOF هو اختصارٌ شهير للعبارة End Of File أي نهاية الملف) لشيوعها، لكنك تستطيع استخدام أي سلسلة تشاء، لطالما أنَّها لا تتعارض مع كلمةٍ محجوزةٍ في bash. العلامة الرمزية التي تُنهي here script يجب أن تُطابِق تمامًا تلك التي بدأته، وإلا فستعامل محتويات السكربت المتبقية على أنَّها دخل قياسي للأمر المُحدَّد. هنالك خدعة إضافية يمكنك استخدامها مع here script تسمح لك بمحاذاة (indent) المحتوى المُمرَّر عبر here script لتحسين قابلية قراءة السكربت. يمكنك فعل ذلك بتعديل السكربت كالآتي: #!/bin/bash # sysinfo_page - A script to produce an HTML file cat <<- _EOF_ <html> <head> <title> The title of your page </title> </head> <body> Your page content goes here. </body> </html> _EOF_ تبديل علامة ‎>> إلى ‎<<-‎ سيؤدي إلى تجاهل مسافات الجدولة (tab) البادئة (لكن لن يتم تجاهل الفراغات) في here script؛ لن يحتوي ناتج الأمر cat على أيّة مسافات جدولة بادئة. حسنًا، لنُعدِّل محتويات ملف HTML لكي نبيّن ما الغرض من صفحة الويب: #!/bin/bash # sysinfo_page - A script to produce an HTML file cat <<- _EOF_ <html> <head> <title> My System Information </title> </head> <body> <h1>My System Information</h1> </body> </html> _EOF_ سنجعل السكربت في الدرس القادم يُظهِر معلومات حقيقة من نظامنا. ترجمة -وبتصرّف- للمقال Here Scripts لصاحبه William Shotts.
  5. قبل أن تبدأ في كتابة سكربتات جديدة، عليّ أن أشير إلى أنَّك تملك بعض السكربتات الموجودة مسبقًا، وضِعَت هذه السكربتات في مجلد المنزل الخاص بك عندما أُنشِئ حسابك، وتُستعمل لضبط سلوك جلسات سطر الأوامر في حاسوبك؛ تستطيع تعديل هذه السكربتات لتغيير بعض الأمور. سنلقِي نظرةً على سكربتَين من هذه السكربتات في هذا الدرس لكي نتعلم بعض المفاهيم الجديدة والمهمة عن الصَدَفة. يُبقي النظام على مجموعة من المعلومات حول جلستك تدعى "البيئة" (environment)، تحتوي البيئة على أشياء مثل المجلدات التي سيتم البحث فيها عن البرمجيات (PATH)، واسم المستخدم، واسم الملف الذي سيُحفَظ فيه بريدك الإلكتروني، وغير ذلك. يمكنك رؤية قائمة كاملة لضبط البيئة بالأمر set. هنالك نوعان من الأوامر التي تحتويها البيئة، وتُعرَف بالاختصارات (aliases) ودوال الصّدفة (shell functions). ما هو منشأ البيئة؟ تبدأ صَدَفة bash عندما تُسجِّل دخولك إلى النظام، وتقرأ سلسلة من ملفات الضبط تُسمى "ملفات بدء التشغيل" أو "ملفات البدء" (startup files) التي تُعرِّف البيئة الافتراضية التي يتشارك فيها جميع المستخدمين؛ ثم ستقرأ ملفات بدء إضافية موجودة في مجلد المنزل الخاص بك التي تُعرِّف بيئتك الشخصية. يختلف الترتيب بحسب نوع جلسة سطر الأوامر التي بدأتها، إذ أنَّ هنالك نوعان: جلسة تحتاج إلى تسجيل دخول (login shell session) وجلسة لا تحتاج إلى تسجيل دخول (non-login shell session). الجلسة التي تحتاج إلى تسجيل دخول هي الجلسة التي تسألك عن اسم المستخدم وكلمة المرور، وذلك عندما تستعمل إحدى الطرفيات الوهمية (virtual console) على سبيل المثال. أما الجلسات التي لا تحتاج إلى تسجيل دخول فهي تحدث عادةً عندما تُشغِّل محاكي الطرفية داخل الواجهة الرسومية. تقرأ الصَدَفة التي تحتاج إلى تسجيل دخول ملف بدء أو أكثر كما هو موضَّح هنا: ‎/etc/profile: سكربت الضبط العام الذي يُطبَّق على جميع المستخدمين. ‎~/.bash_profile: ملف بدء خاص بالمستخدم، يمكن أن يُستعمل لضبط خياراتٍ أخرى غير موجودة في سكربت الضبط العام، أو لتجاوز بعضها وإعادة تعريفها. ‎~/.bash_login: إن لم يكن الملف ‎~/.bash_profile موجودًا فستحاول الصَدَفة bash قراءة هذا السكربت. ‎~/.profile: إن لم يكن الملف ‎~/.bash_profile أو ‎~/.bash_login موجودًا فستحاول الصَدَفة bash قراءة هذا الملف. هذا هو السلوك الافتراضي في التوزيعات المبنية على دبيان مثل أوبنتو. أما الصَدَفة التي لا تحتاج إلى تسجيل دخول، فتقرأ ملفات البدء الآتية: ‎/etc/bash.bashrc: سكربت ضبط عام يُطبَّق على جميع المستخدمين. ‎~/.bashrc: ملف بدء خاص بالمستخدم، يمكن أن يُستعمل لضبط خياراتٍ أخرى غير موجودة في سكربت الضبط العام، أو لتجاوز بعضها وإعادة تعريفها. إضافةً إلى قراءة ملفات الضبط السابقة، ترث الجلساتُ التي لا تحتاج إلى تسجيل دخول البيئةَ من العملية الأب (parent process) التي تكون عادةً جلسة تحتاج إلى تسجيل دخول. ألقِ نظرةً على نظامك لترى ما هي ملفات البدء التي عندك، لكن لاحظ أنَّ أغلبية الملفات السابقة تبدأ بنقطة (مما يعني أنها مخفية)، لذا عليك استخدام الخيار ‎-aمع الأمر ls. ls -a ملف ‎~/.bashrc هو أهم ملف بدء من وجه نظر المستخدم العادي لأنه يُقرَأ دائمًا. حيث تقرأه الجلسات التي لا تحتاج إلى تسجيل دخول افتراضيًا، وأغلبية ملفات البدء الخاصة بالجلسات التي تحتاج إلى تسجيل دخول تقرأ ملف ‎~/.bashrc أيضًا. إذا ألقيت نظرةً داخل ملف ‎.bash_profile‎ (الملف الآتي مأخوذ من توزيعة CentOS)، فسيبدو شبيهًا بالآتي: # .bash_profile # Get the aliases and functions if [ -f ~/.bashrc ]; then . ~/.bashrc fi # User specific environment and startup programs PATH=$PATH:$HOME/bin export PATH تذكَّر أنَّ الأسطر التي تبدأ برمز # هي تعليقات ولا تُفسَّرها الصَدَفة؛ حيث أُضيفت هذه الأسطر لشرح الشيفرة لمن يقرأها من البشر. ستجد في السطر الرابع أول الأشياء المثيرة للاهتمام: if [ -f ~/.bashrc ]; then . ~/.bashrc fi هذه هي عبارة if الشرطية، التي سنشرحها بالتفصيل في درسٍ لاحق، لكنني سأفسرها لك كالآتي: إذا كان الملف ‎~/.bashrc موجودًا، فنفِّذ محتويات ‎~/.bashrc. يمكننا أن نرى أنَّ الشيفرة القصيرة السابقة هي التي تجعل الجلسات التي تحتاج إلى تسجيل الدخول تقرأ محتويات الملف ‎.bashrc. الخطوة التالية في ملف البدء هي ضبط المتغير PATH وإضافة ‎~/bin إلى قائمة المجلدات التي سيتم البحث فيها عن الملفات التنفيذية للأوامر. وفي نهاية الملف: export PATH وظيفة الأمر export هي إخبار الصَدَفة أنَّ عليها جعل محتويات المتغير PATH متاحةً للعمليات التي تنحدر منها (الأبناء). الاختصارات aliases الاختصارات (aliases) هي طريقة سهلة لإنشاء أمر جديد يعمل اختصارًا لأمرٍ أطول. لها الشكل العام الآتي: alias name=value حيث name هو اسم الأمر الجديد و value هي السلسلة النصية التي ستُنفَّذ عند إدخال name في سطر الأوامر. لنُنشِئ اختصارا اسمه l (حرف L صغير) ولنجعله اختصارًا للأمر ls -l (أي عرض محتويات المجلد بالصيغة التفصيلية). تأكَّد أنَّ مجلد العمل الحالي هو المنزل، ثم افتح ملف ‎.bashrc باستخدام محررك النصي المُفضَّل وأضف السطر الآتي إلى نهاية الملف: alias l='ls -l' عند إضافتك للأمر alias إلى الملف، فستُنشِئ أمرًا جديدًا اسمه l الذي يكافئ ls -l. أغلِق جلسة الطرفية الحالية وابدأ واحدة جديدة لتجربة الاختصار التي أنشأناه، وذلك لإعادة قراءة محتويات الملف ‎.bashrc. يمكنك باستخدام هذه التقنية إنشاء أي عدد من الاختصارات المُخصصة لاستعمالك الشخصي، هذه إحداها: alias today='date +"%A, %B %-d, %Y"' سيُنشِئ السطر السابق اختصارا جديدا اسمه today الذي سيُظهِر تاريخ اليوم بتنسيقٍ جميل. بالمناسبة، الأمر alias هو أمر مُضمَّن في الصَدَفة (shell builtin)، أي أنَّك تستطيع إنشاء الأوامر البديلة مباشرةً من سطر الأوامر؛ لكن يجب أن تعلم بأنَّ تلك الأوامر ستزول عند إغلاقك لجلسة الطرفية الحالية. مثال: $ alias l='ls -l' دوال الصدفة ستستفيد من أمر alias عند إنشاء اختصارات لأوامر بسيطة، لكن ماذا لو أردت إنشاء شيءٍ أكثر تعقيدًا؟ عليك حينها أن تجرِّب شيئًا يسمى "دوال الصدفة" (shell functions)، التي يمكنك اعتبارها أنهَّا "سكربتات داخل سكربتات"، أو سكربتات فرعية صغيرة. لنجرب واحدةً منها! افتح ملف ‎.bashrc بمحررك وضع ما يلي بدلًا عن الاختصار today: today() { echo -n "Today's date is: " date +"%A, %B %-d, %Y" } صدِّق أو لا تصدِّق، () هو أمر مضمَّن بالصدفة أيضًا مثَلُهَ كَمَثَلِ الأمر alias، حيث يمكنك أيضًا إدخال دوال الصدفة مباشرةً من سطر الأوامر. $ today() { > echo -n "Today's date is: " > date +"%A, %B %-d, %Y" > } $ لكن تلك الدوال -مثلما هو عليه الحال مع الأمر alias- ستزول عند إغلاق جلسة الطرفية الحالية. ترجمة -وبتصرّف- للمقال Editing The Scripts You Already Have لصاحبه William Shotts.
  6. سنتحدثُ في هذا الدّرس عن الطرق التي يُوفّرها لك كلّ من Bash، نظام لينكس والطرفيّة Terminal للتّحكم بالوظائف والعمليّات. ذكرنا في درس إدارة العمليات في لينكس باستخدام الطرفية كيفية استعمال الأوامر ps ،kill و nice للتحكم بالمهام على نظامك. سنُركّز في هذا المقال على إدارة عمليّات المُقدّمة وعمليّات الخلفيّة وسنشرح كيف ترفع من مُستواك في التّحكم بالوظائف والمهام لتحصل على مُرونة أكثر عند تنفيذك للأوامر. إدارة عمليات المقدمة مُعظمُ العمليّات التي تُشغّلها على لينكس ستُنفّذ في المُقدّمة. سيبدأ الأمر بالتّنفيذ ما يمنعك من تنفيذ أي أمر آخر طوال مدة تنفيذ العمليّة. يُمكن أن تسمح العمليّة بتَفاعلِ المُستخدم، أو يُمكن أن تُنفّذ إجراءًا معيّنا ثم تنتهي. وسيُعرض أي مُستخرج على شاشة الطرفية افتراضيّا، سنتطرّق إلى الطريقة المُبسّطة لإدارة عمليّات المُقدّمة أسفله. تشغيل عملية تُشَغّلُ العمليّات في المُقدّمة افتراضيا إلى أن تنتهي أو عند تغيّر الحالة، وأثناء تشغيل العمليّات لن تتمكن من التفاعل مع الصّدفة Shell. بعض أوامر المُقدّمة تنتهي بسرعة مُرجعة المُستخدم إلى واجهة الصدفة آنيّاً، وهذا الأمر هو مثال على ذلك: echo "Hello World" هذا الأمر سيطبع "مرحبا بالعالم" على شاشة الطرفيّة ثم يرجعك إلى شاشة الأوامر. بعض أوامر المُقدمة الأخرى تأخذ وقتا أطول للتنفيذ، مانعة الولوج إلى الصّدفة أثناء التشغيل. يُمكن أن يعود السبب إلى أن الأمر يُشغل عمليّة أعقد أو أنّ العمليّة مُبرمجة للتنفيذ إلى أن تتوقف بشكل واضح أو إلى أن تتلقى مُدخلات من المُستخدم. تُعتبر أداة top من الأوامر التي تنفذ لوقت غير محدود، فبعد تشغيلها ستستمر في التنفيذ وتحديث عناصر الشاشة إلى أن يقوم المُستخدم بإنهاء العملية: top يُمكنك الخروج بالضّغط على "q". بعض العمليّات لا تملك طريقة للخروج ولتوقفها سيجب عليك استخدام طريقة أخرى. إنهاء عملية لنفترض أننا قمنا بتشغيل حلقة تكرار بسيطة في سطر الأوامر، يُمكننا تشغيل حلقة تكرار تقوم بطباعة "Hello World" كل عشر ثوان. هذه الحلقة ستستمر في الطّباعة إلى أن تُوقَف إجباريّاً: while true; do echo "Hello World"; sleep 10; done حلقات التكرار كهذه لا تملك أي زر للإلغاء، سيتوجّب علينا أن نوقف العمليّة بارسال ما يسمّى بـ الإشارة signal. تستطيع النواة في لينكس إرسال إشارات إلى العمليّات لطلب إيقاف نهائيّ للعملية أو تغيير الحالة فقط، طرفيّات لينكس عادة ما تكون مضبوطة لإرسال إشارة "SIGNT" (الإشارة رقم 2) لعمليّة المُقدّمة الحاليّة عند ضغط تركيبة المفتاحين CTRL+C. تُخبر إشارة "SIGNT" البرنامج بأن المستخدم قد طلب إنهاء العمليّة مُستخدما لوحة المفاتيح. لإيقاف حلقة التكرار التي بدأناها اضغط على مفتاحي CTRL و"c": CTRL+C سيتم إغلاق حلقة التكرار و ستتمكن من التحكم بالصّدفة Shell مجددا. إشارة "SIGNT" المُرسلة عن طريق تركيبة CTRL+C واحدة من الإشارات المتعدّدة التي يمكن إرسالها إلى البرامج، مُعظم الإشارات لا تملك تركيبة مفاتيح مُرتبطة بها، وعليك إرسال هذه الإشارات باستخدام الأمر kill عوضا عن ذلك (سوف نغطي ذلك لاحقاً). تعليق العمليات ذكرنا أعلاه أن عمليّات المُقدّمة تمنعك من تنفيذ أي أمر آخر طوال مدة تنفيذ العمليّة. ماذا لو أدركنا أنّنا نحتاج إلى شاشة الطرفية بعد أن نُشغّل عملية في المُقدمة؟ إشارة "SIGTSTP" (الإشارة رقم 20) هي إشارة من الإشارات التي يمكن إرسالها إلى عمليّات المُقدّمة. عندما نضغط تركيبة مفاتيح CTRL+Z، تُسجل الطرفيّة أمر "تعليق"، الذي يرسل إشارة "SIGTSTP" إلى عملية المُقدمة. هذا الأمر سيوقف مؤقّتا تنفيذ الأمر ويعيد التحكم بالطرفيّة. كمثال على ذلك، لنستخدم أمر ping للاتّصال ب google.com كلّ 5 ثوان. سوف نُسبق الأمر بكلمة command، ما يُخولُ لنا تجاوز أي كُنيات للصدفة (shell aliases) يُمكن لها وضع عدّ أقصى على الأمر : command ping -i 5 google.com عوضا عن إنهاء العملية باستعمال CTRL+C، أدخل CTRL+Z بدلا من ذلك. CTRL+Z سيكون المُخرج هكذا: [1]+ Stopped ping -i 5 google.com لقد تم إيقاف الأمر ping مؤقّتاً، وبذلك تستطيع الوصول إلى جلسة الصّدفة shell لكتابة الأوامر مُجدّداً. يُمكننا استعمال أداة إدارة العمليّات ps لعرضها: ps T PID TTY STAT TIME COMMAND 26904 pts/3 Ss 0:00 /bin/bash 29633 pts/3 T 0:00 ping -i 5 google.com 29643 pts/3 R+ 0:00 ps t يُمكننا ملاحظة أن عمليّة ping لا تزال ضمن القائمة، لكن العمود STAT (الخاص بحالة العمليّة) يحمل القيمة "T". صفحة الدليل الخاصة بـ ps تخبرنا أن هذا الحرف يعني أن العملية قد أوقفت عن طريق إشارة "التحكم بالعمليات". سوف نتحدّث بعمق أكثر عن كيفية تغيير حالة العمليّة،لكن في الوقت الحالي يُمكننا استئناف تنفيذ العمليّة في المُقدمة بكتابة: fg عند استكمال التنفيذ، أنهِ العمليّة باستعمال CTRL+C: CTRL+C إدارة عمليات الخلفية البديل الرئيسي لتنفيذ عمليّة في المُقدمة هو تشغيلها في الخلفيّة، عمليّة الخلفية مرتبطة بالطرفيّة التي شغّلتها منها، لكنّها لا تمنعك من الوصول إلى الصّدفة (سطر الأوامر)، عوضا عن ذلك، تُنفّذ العمليّة في الخلفيّة، تاركة لمُستخدم حريّة التفاعل مع النظام أثناء تشغيل العمليّة. بسبب الطريقة التي تتعامل بها عمليّات المقدمة مع الطرفيّة، يمكن أن تُشغّل عمليّة واحدة فقط لكل نافذة من نوافذ الطرفية. ولأن عمليّات الخلفية ترجع التحكم بالصّدفة Shell مباشرة بدون انتظار انتهاء العمليّة، يُمكن تشغيل العديد من العمليّات في الخلفيّة في الآن ذاته. تشغيل العمليات يُمكنك تشغيل عمليّة في المُقدّمة بإلحاق محرف"&" عند نهاية الأمر. يُخبر هذا الصّدفة shell بألّا تنتظر إلى حين انتهاء العملية بل تشغيلها وإرجاع التحكم بالطرفيّة للمُستخدم فوراً. ستبقى المُخرجات تُعرض على شاشة الطرفية (إلا إذا قمت بـإعادة توجيهها) لكنّك ستتمكن من كتابة أوامر إضافية أثناء استمرار تنفيذ عمليّة الخلفيّة. على سبيل المثال، يُمكن أن نبدأ أمر ping نفسه من القسم السّابق في الخلفيّة: command ping -i 5 google.com & سترى مخرجا يبدو هكذا من نظام bash للتحكم بالعمليّات : [1] 4287 وسترى أيضا المُخرج العادي من طرف الأمر ping: PING google.com (74.125.226.71) 56(84) bytes of data. 64 bytes from lga15s44-in-f7.1e100.net (74.125.226.71): icmp_seq=1 ttl=55 time=12.3 ms 64 bytes from lga15s44-in-f7.1e100.net (74.125.226.71): icmp_seq=2 ttl=55 time=11.1 ms 64 bytes from lga15s44-in-f7.1e100.net (74.125.226.71): icmp_seq=3 ttl=55 time=9.98 ms رغم هذا ستتمكن من كتابة الأوامر في الوقت عينه. سوف يُمزج المُخرج من عمليّة الخلفيّة مع المدخلات والمخرجات الخاصة بعمليّة المُقدمة التي بدأتها، لكنّها لن تتداخل مع تنفيذ عمليّة المقدّمة. جدولة عمليات الخلفية لرؤية جميع العمليّات المُتوقفة أو عمليّات الخلفية، يمكنك استعمال الأمر jobs: jobs إذا كان الأمر ping مُشغّلا في الخلفية ستكون المخرجات على الشكل التالي: [1]+ Running command ping -i 5 google.com & يُبيّن هذا أنّنا نملك عمليّة واحدة في الخلفيّة. [1] تمثّل الـ "job spec" أو رقم الوظيفة. يُمكننا الإشارة إلى هذه العمليّة عند استعمال أوامر التحكم بالعمليّات مثل kill ،fg ،bg بإضافة سابقة "%" إلى رقم الوظيفة. في هذه الحالة سنشير إلى هذه الوظيفة بالإشارة 1%. إيقاف عمليات الخلفية يُمكننا إيقاف عمليّات الخلفيّة بعدّة طرق، أكثر طريقة نجاعة هي استخدام الأمر kill مع رقم الوظيفة. كمثال، يمكن أن نوقف أمرنا المُشغَّل في الخلفيّة بكتابة: kill %1 حسب طريقة ضبط الطرفيّة التي تستخدمها، إما مُباشرة أو بعض ضغط ENTER للمرة الثانية، ستشاهدُ حالة إيقاف الوظيفة على الطرفيّة: [1]+ Terminated command ping -i 5 google.com إذا تحققنا بالأمر jobs، سنلاحظ عدم وجود أي عمليّة. تغيير حالة العملية بعد أن تعرفنا على كيفية تشغيل عمليّة أو إيقافها في الخلفيّة، يُمكننا التحدث عن كيفية تغيير حالة العمليّة. شرحنا تغيير حالة واحدة قبل قليل عند التطرق لكيفيّة إيقاف مُهمّة أو تعليق عملها باستخدام CTRL+Z. يُمكننا نقل عمليّات المقدّمة إلى الخلفيّة أو العكس عندما تكون العمليّة في حالة توقّف. نقل عمليات المقدمة إلى الخلفية إذا نسيت أن تنهي الأمر بحرف العطف "&"، لا تزال قادرا على نقل هذه العمليّة إلى الخلفيّة. الخطوة الأولى هي إيقاف العمليّة باستخدام CTRL+Z: CTRL+Z عندما تتوقف العمليّة، يُمكننا استعمال الأمر bg لتشغيلها مجدّدا في الخلفيّة: bg ستشاهد حالة الوظيفة مع حرف العطف "&" ملحقا في الأخير: [1]+ ping -i 5 google.com & يعمل الأمر bg افتراضيّا مع آخر عمليّة تمت إيقافها، إذا أوقفت العديد من العمليّات بشكل متتالٍ بدون تشغيلها مجدّدا يُمكنك الإشارة إلى العمليّة برقم الوظيفة لإرسال العمليّة الصحيحة إلى الخلفيّة. لاحظ أنّه ليست كل العمليّات قابلة للإرسال إلى الخلفيّة. ستتوقف بعض العمليّات آليّاً إذا كشفت أنها نُفّذت مع إدخال ومخرج معياري متصلة مُباشرة مع طرفيّة نشطة. نقل عمليات الخلفية إلى المقدمة يُمكننا أيضاً نقل عمليّات الخلفيّة إلى المُقدّمة باستخدام الأمر fg: fg هذا الأمر يعمل مع آخر عمليّة منقولة إلى الخلفيّة، يُشار إليها بعلامة "+" في مخرجات jobs. الأمر يقوم فوراً بتعليق العمليّة ووضعها في المُقدّمة. لتحديد وظيفة أخرى استعمل رقم الوظيفة: fg %2 عندما تُنقل الوظيفة إلى المُقدّمة يُمكنك إمّا إنهاؤها مع CTRL+C، أو تركها لتكتمل أو تعليقها وإرسالها إلى الخلفيّة من جديد. التعامل مع إشارات SIGHUP سواء كانت العمليّة في المقدّمة أو في الخلفيّة، فستبقى مرتبطة بالطرفيّة التي بدأت العمليّة منها، عندما تغلق الطرفيّة فإنها ترسل إشارة SIGHUP لجميع العمليّات (في المُقدمة، في الخلفيّة، أو المتوقّفة) المرتبطة بها. ما يُشير إلى العمليّات بالإنهاء لأن الطرفيّة المُتحكِّمة ستصبح غير مُتوفرة قريباً، ماذا لو أردت إغلاق طرفيّة مع إبقاء تنفيذ عمليّات الخلفيّة؟ هناك العديد من الطرق للقيّام بذلك، أكثر الطرق مرونة هي باستعمال مُضاعف طرفيّة (terminal multiplexer) مثل tmux أو screen، أو استعمل أداة تمنح خاصية الفصل مثل dtach. على الرغم من هذا فهذه الطرق ليست دائما خيّارا ممكنا، ففي بعض الأوقات قد لا تكون هذه البرمجيات متوفرة أو أنّك قد سبق وبدأت العمليّة التي تريدها أن تستمر في التنفيذ بعد إغلاق الطرفيّة. استعمال nohup إذا كنت تعلم أنك عند تشغيل العمليّة سترغب في إغلاق الطرفيّة قبل انتهاء العمليّة، يُمكنك تنفيذها باستخدام أمر nohup، هذا الأمر يؤمّن العمليّة من التعرض إلى الإنهاء من طرف إشارة SIGHUP وستستمر في التنفيذ عندما تُغلق الطرفيّة. وستسجل كابن للنظام الأساسي: nohup ping -i 5 google.com & سترى سطرا يبدو كالتالي، مبيّنا أن مُخرجات الأمر ستُكتب في ملف يسمى nohup.out (في المجلّد الحالي إذا ما كان قابلا للكتابة عليه، في حالة لم يكن قابلا للكتابة عليه فسيُنشئه في مُجلّد المنزل): nohup: ignoring input and appending output to 'nohup.out' والغرض منه التأكد من أن المخرجات ليست مفقودة بعد إغلاق الطرفيّة. إذا أغلقت نافذة الطرفية وفتحت أخرى، ستبقى العمليّة في طور التنفيذ، ولن تتمكن من رؤيتها في مخرجات الأمر jobs لأن كل طرفيّة تحمل صفّ وظائف خاص بها، إغلاق الطرفيّة سبّب تدمير الوظيفة ping رغم أن العمليّة ping لا تزال تُنفّذ. لإيقاف عمليّة ping، يجب عليك البحث عن معرّف العمليّة (process ID) أو PID الخاص بها، يُمكنك القيّام بذلك بالاستعانة بالأمر pggrep (هناك أيضا الأمر pkill، لكنّنا بهذه الطريقة المقسّمة إلى خطوتين نكون متأكدين من أننّا سنوقف العمليّة التي نريدها فقط). استعمل pgrep مع a- للبحث عن العمليّة: pgrep -a ping المُخرجات: 7360 ping -i 5 google.com يُمكنك بعدها إيقاف العمليّة بإلحاق معرف العمليّة (الرقم في العمود الأول) بالأمر kill: kill 7360 قد ترغب في حذف ملف nohup.out إذا لم تكن تريده بعد الآن. استعمال disown يكون الأمر nohup مُفيدا فقط عندما تعلم أنّك ستحتاج إليه عند بدأ عمليّة ما. نظام إدارة الوظائف الخاص بـ bash يتيح لنا طرقا أخرى للحصول على نتائج مماثلة مع أمر diswon. عند الضبط الافتراضي للأمر disown، يقوم الأمر بحذف الوظيفة من طابور الوظائف الخاص بالطرفيّة. ما يعني أنك لن تستطيع إدارة العمليّة باستعمال التقنيّات التي تطرقنا إليها (مثل fg ،bg ،CTRL+Z ،CTRL+C). سيُحذف فوريّا من قائمة مخرجات الأمر jobs ولن يكون مرتبطا بالطرفيّة بعد ذلك. يُستعمل الأمر عن طريق تحديد العمليّة بالاستعانة برقم وظيفتها، على سبيل المثال، لتتبرر (disown) من الوظيفة رقم 2، يمكننا كتابة: disown %2 هذا الأمر سيترك الوظيفة في حالة مثل الأمر nohup، الاستثناء الوحيد هو أن جميع المُخرجات ستُفقد بعد إغلاق الطرفيّة في حالة لم يتم إعادة توجيهها إلى ملف ما. لن ترغب عادة في حذف العمليّة من قائمة التحكم بالوظائف إذا لم تكن تريد إغلاق نافذة الطرفيّة فورا.يمكنك إضافة h- للأمر لتقوم العمليّة بتجاهل إشارات SIGHUP، وتستمرَّ في العمل كوظيفة عاديّة: disown -h %1 في هذه الحالة، يُمكنك استعمال تقنيّات التحكم بالوظائف للاستمرار في التحكم بالوظيفة إلى حين إغلاق الطرفيّة، عند إغلاق الطرفيّة، ستكون عالقا -مرة أخرى- مع عمليّة دون أي مُخرجات إذا لم تعِد توجيهها إلى ملف عندما بدأتها. للعمل على ذلك، يمكنك محاولة إعادة توجيه مخرجات العمليّة بعد أن شغلتها. هذا الأمر خارج مجال هذا الدرس. يمكنك الإطلاع على الدرس مقدمة إلى إعادة توجيه الإدخال/الإخراج (I/O) في لينكس لمزيد من المعلومات. استعمال خيار الصدفة: huponexit هناك أيضا طريقة أخرى في Bash لتجنّب مشكلة إشارات SIGHUP للعمليّة الابن، يتحكم خيّار huponexit في ما إذا كان bash سيرسل إشارة SIGHUP للعمليّة الابن عند الخروج أو لا. ملاحظة: خيّار huponexit يؤثّر على طريقة تصرف إشارات SIGHUP فقط إذا كان إغلاق جلسة الصّدفة من داخل الصّدفة نفسه. يعتبر الأمر exit أو CTRL+D من الأمثلة على إغلاق الجلسة من داخل الصّدفة. عند إنهاء جلسة صدفة من برنامج الطرفيّة (بإغلاق النافذة، ...)، لن يكون للأمر huponexit أي تأثير، عوضا عن ترك اتخاذ قرار إرسال إشارة SIGHUP لـ bash سترسل الطرفيّة بنفسها الإشارة إلى bash، والتي ستبثّ (بشكل صحيح) الإشارة إلى العمليّة الابن. رغم المحاذير أعلاه، يعتبر خيار huponexit أسهل من الطرق. يُمكنك معرفة ما إذا كانت هذه الخاصية مُشغّلة أو لا بكتابة: shopt huponexit لتشغيل الخاصيّة: shopt -s huponexit الآن، إذا قمت بالخروج من الجلسة بالأمر exit، فإن العمليّات ستستمر في العمل: exit لدى هذا الأمر نفس المحاذير حول المُخرجات مع الخيّار السابق، لذلك تأكد أنّك قمت بتوجيه مُخرجات العمليّة قبل إغلاق الطرفيّة إذا كانت مُهمّة. خاتمة سيمنحك تعلّم التحكم بالوظائف وكيفيّة إدارة عمليّات المُقدمة وعمليّات الخلفيّة مرونة أكثر عند تشغيل البرامج من سطر الأوامر. عوضا عن فتح عدّة طرفيّات أو جلسات SSH، تستطيع أن تدبّر الأمر ببضع أوامر إيقاف وإرسال إلى الخلفيّة. ترجمة -وبتصرّف- للمقال How To Use Bash's Job Control to Manage Foreground and Background Processes لصاحبه Justin Ellingwood.
  7. قدرات إعادة التوجيه (redirection) في لينكس توفّر لك العديد من الأدوات القوية التي يُمكن استخدامها لجعل جميع أنواع المهام أسهل للتنفيذ. سواءٌ كنتَ تكتبُ برمجياتٍ معقّدة أو كنتَ تقوم بإدارة الملفّات عبر سطر الأوامر، فإنّ معرفة كيفية التلاعب بتدفّقات (streams) الإدخال/الإخراج (input/output) على بيئتك الشخصية سيزيدُ من إنتاجيّتك بشكلٍ ملحوظ. التدفقات يتم توزيع الإدخال والإخراج في بيئة لينكس عبر ثلاث تدفّقات (streams) أساسية: إدخال معياري (stdin). إخراج معياري (stdout). خطأ معياري (stderr). هذه التدفّقات أيضًا مرقّمة وفق التالي: (stdin (0. (stdout (1. (stderr (2. أثناء التفاعلات المعيارية (standard interactions) بين المستخدم والطرفيّة (terminal)، فإنّه يتم نقل الإدخال المعياري عبر لوحة مفاتيح المستخدم. يتم عرض الإدخال المعياري و الخطأ المعياري على طرفية المستخدم كنصّ. بشكلٍ عام، جميع هذه التدفّقات الثلاثة يتم الإشارة إليها بـ"التدفّقات المعيارية". الإدخال المعياري تدفّق الإدخال المعياري عادةً ما يحمل البيانات من المستخدم إلى البرنامج. البرامج التي تتوقع إدخالًا معيّنًا من المستخدم تستقبل الإدخال عادةً من جهازٍ ما، مثل لوحة المفاتيح، الإدخال المعياري ينتهي عند وصوله نهاية الملف (EOF – End Of File). كما يتم وصفه بواسطة اسمه، فإنّ نهاية الملف أو "EOF" تُعلِم الحاسوب أنه لا يوجد هناك المزيد من البيانات ليتم قراءتُها. لرؤية الإدخال المعياري بصورةٍ حيّةَ، شغّل برنامج cat. كلمة Cat ترمز لـ"concatenate” أو "سَلسَلة الأشياء"، والتي تعني ربط الأشياء مع بعضها البعض على شكل سلسلة. يتم استخدام Cat بشكلٍ شائع لدمج محتويات ملفّّين. عندما يتم تشغيله لوحده فإنّ cat يقوم بفتح طرفيّته الخاصّة. cat بعد فتح cat، قم بإدخال مجموعة من الأرقام كالتالي: 1 2 3 ثم اضغط Ctrl+D. عندما تقوم بكتابة رقم والضغط على زرّ Enter، فإنّك تقوم بإرسال إدخال معياري (standard input) إلى برنامج cat الذي يعمل حاليًا، والذي هو بدوره يتوقّع وصول الإدخال إليه. يقوم برنامج cat بإرسال الإدخال الذي تُدخله إليه مرةً أخرى إلى الطرفية حيث يتم عرضه كإخراج معياري (standard output). إشارة EOF (أو نهاية مدّة حياة العملية الحالية – End of File) يُمكن أن يتم إرسالها إلى البرنامج بواسطة المستخدم عبر الضغط على مفاتحيّ Ctrl+D. بعد أن يتسلّم برنامج cat إشارة EOF فإنّ البرنامج يتوقف. الإخراج المعياري يقوم الإخراج المعياري (standard output) بكتابة البيانات التي يتم إنشاءها بواسطة البرامج. عندما لا يتم إعادة توجيه تدفّق الإخراج المعياري، فإنّه سيتم إخراج النصّ إلى الطرفية. جرّب المثال التالي: echo Sent to the terminal through standard output الخطأ المعياري يقوم الخطأ المعياري (standard error) بكتابة الأخطاء التي يتم إنشاؤها بواسطة البرامج التي فشلت في أن يتم تنفيذها في مرحلةٍ ما. تمامًا مثل الإدخال المعياري فإنّ الوجهة الافتراضية لهذا التدفّق هي شاشة الطرفيّة. عندما يتم إرسال تدفّقِ خَطَأٍ معياريٍ لبرنامجٍ إلى برنامجٍ آخر، فإنّ البيانات المُرسلة (المتكوّنة من أخطاء البرنامج) يتم إرسالها بشكلٍ موازي إلى الطرفية كذلك. فلنرى مثالًا بسيطًا عن الخطأ المعياري باستخدام ls. يقوم الأمر ls بسرد محتويات المجلّدات أو المسارات. عندما يتم تنفيذه بدون أيّ معطيات، فإنَّ أمر ls يقوم بسرد محتويات المسار الحالي. إذا تمّ تشغيله مع مسارٍ معيّن كمُعطَى، فإنّه سيقوم بسرد محتويات المسار المطلوب. ls % بما أنّ % ليس مسارًا موجودًا، فإنّه سيتم إرسال النصّ التالي كخطأٍ معياري: ls: cannot access %: No such file or directory إعادة توجيه التدفق يمتلك نظام لينكس أوامرًا مُضمّنة لإعادة توجيه كلّ تدفّق. تقوم هذه الأوامر بطباعة إخراجٍ معياري إلى ملفٍّ ما. إذا تم استهداف ملفٍّ غير موجود، فإنّه سيتم إنشاء ملفٍّ جديد باسم ذاك الملفّ ليتم الكتابة عليه. الأوامر التي يأتي معها قوسٌ واحد (إشارة >) تقوم بالكتابة فوق ملفّ الوجهة الموجود. بالأسفل تجد بعض الإشارات الشائع استخدامها مع الأوامر عند التعامل معها بالطرفية لإعادة توجيه التدفّقات: 1. الكتابة فوق الملفات > إخراج معياري. < إدخال معياري. 2> خطأ معياري. 2. الإضافة إلى الملفات الأوامر التي يتم استخدامها مع قوسين اثنين لا تقوم بالكتابة فوق الملفّّات، بل تقوم بالكتابة إلى نهاية الملفّّات: >> إخراج معياري. << إدخال معياري. 2>> خطأ معياري. فلنأخذ المثال التالي: $ cat > write_to_me.txt a b c > ctrl-d يتم استخدام cat هنا لتتم عملية الكتابة إلى أحد الملفّّات، والذي يتم إنشاؤه تلقائيًا بسبب عدم وجوده ولأن الأمر الأول يحتاجه. لطباعة محتويات الملفّ write_to_me.txt باستخدام cat: $ cat write_to_me.txt يجب أن ترى أنّ الملفّ يحتوي على التالي: a b c الآن قم بإعادة توجيه cat إلى write_to_me.txt مجددًا وقم بإدخال الأرقام التالية: $ cat > write_to_me.txt 1 2 3 > ctrl-d عندما تستعمل cat لعرض محتويات write_to_me.txt، يجب أن ترى التالي: 1 2 3 أخيرًا، قم بعمل إعادة توجيه أخرى لـ cat ولكن هذه المرّة باستخدام قوسين عوضًا عن قوسٍ واحد: cat >> write_to_me.txt a b c ctrl-d وافتح ملفّ write_to_me.txt مجددًا، وسترى التالي: 1 2 3 a b c يحتوي الملفّّ الآن على النصّ من المرّة الأخيرة لاستخدام الأمر cat والتي قبلها، لأنّ الثانية لم تقم بالكتابة فوق الأولى. الأنابيب يتم استخدام الأنابيب (Pipes) لإعادة توجيه تدفّقٍ من برنامجٍ إلى آخر. عندما يتم إرسال الإخراج المعياري الخاص بأحد البرامج إلى برنامجٍ آخر عبر أنبوب (pipe) فإنّ بيانات البرنامج الأول والتي تمّ تلقّيها من طرف البرنامج الثاني سوف لن تظهر في الطرفية. فقط البيانات المُرشّحة عبر البرنامج الثاني سوف يتم عرضها. الأنبوب في نظام لينكس يتم تمثيله بإشارة شريطٍ عمودي: *|* وكمثالٍ على أمرٍ يستخدم أنبوبًا: ls | less هذا الأمر يقوم بأخذ ناتج الأمر ls (والذي يقوم بعرض محتويات المسار الحالي الذي أنت فيه) ويقوم بتمريره عبر أنبوبٍ إلى برنامج less. يقوم less بعرض البيانات المُرسلة إليه سطرًا سطرًا بدلًا من عرضها كاملة. بشكلٍ عام، يقوم ls بعرض محتويات المسار المطلوب عبر عرض الخرج بأكمله دفعةً واحدة. عندما تقوم بتشغيل ls عبر less فإنّ كلّ مُدخَلة يتم عرضها في سطرٍ واحد فقط خاصٍ بها ولا يتم عرض الخرج كله دفعةً واحدة، بل واحدة واحدة. على الرغم من أنّ وظيفة الأنابيب قد تبدو مشابهةً لإشارات الأقوس < و << (إعادة توجيه الإخراج المعياري)، فإنّ الفرق هو أنّ الأنابيب تقوم بتوجيه الخرج من أمرٍ إلى آخر، بينما تقوم إشارات الأقواس مثل < و << بتوجيه الخرج حصرًا إلى الملفّات فقط. المرشحات المرشّحات (filters) هي عبارة عن أوامر تعدّل على أنابيب إعادة التوجيه والإخراج. لاحظ أيضًا أنّه يمكن استخدام أوامر المرشّحات وأوامر لينكس العادية دون الحاجة لاستخدام الأنابيب. find: يقوم برنامج find بعرض الملفّات التي يتطابق اسمها مع المعطيات المُمررة له. grep: يقوم برنامج grep بعرض النصّ الذي يتطابق مع النصّ المُمرر إليه. tee: مهمّة برنامج tee هي إعادة توجيه الإدخال المعياري إلى كلٍ من الإخراج المعياري وملفٍّ واحد أو أكثر. tr: يقوم برنامج tr بالبحث عن سلسلة (string) واستبدالها بواحدة أخرى. wc: عدّاد للمحارف، السطور والكلمات. أمثلة قد تعرّفت الآن على إعادة التوجيه، استخدام الأنابيب والمرشّحات الأساسية، فلنلقي نظرةً على بعض أنماط إعادة التوجيه الأساسية والأمثلة. الأمر > الملف يقوم هذا النمط بإعادة توجيه ناتج أمرٍ معين إلى ملفّ، مثال: ls ~ > root_dir_contents.txt سيقوم الأمر السابق بتمرير محتويات مجلد الجذر (root directory) وكتابتها إلى ملفٍّ يدعى root_dir_contents.txt. سيقوم أيضًا بالكتابة فوق أيّ بيانات موجودة في ذاك الملفّ كوننا نستخدم قوسًا واحدًا فقط (>). الأمر > dev/null/ dev/null/ هو ملفٌّ خاص يتم استعماله لحذف أيّ بياناتٍ يتم توجيهها له. يتم استخدامه للتخلص من الخرج الذي لا نحتاجه والذي يُمكن أن يتعارض أحيانًا مع وظيفة أمرٍ آخر أو سكربت (script). يتم إهمال أي خرجٍ يتم إرساله إلى dev/null/. في المستقبل، ربّما تقوم باستخدام إعادة توجيه الخرج الناتج عن الأوامر والأخطاء إلى dev/null/ عند كتابة سكربتات الشلّ (shell scripts). ls > /dev/null سيقوم الأمر السابق بإهمال تدفّق الإخراج المعياري (standard output stream) العائد من الأمر ls عبر تمريره إلى الملفّ dev/null/ الذي سيتخلص منه. الأمر 2> الملف يقوم هذا النمط بتوجيه تدفّق الخطأ المعياري لأمرٍ ما إلى ملفّ، حيث يقوم بالكتابة فوق محتوياته الموجودة. كمثال: mkdir '' 2> mkdir_log.txt هذا الأمر سيوجّه رسالة الخطأ الصادرة عن "اسم المسار الخاطئ" ويكتبها إلى ملفّ mkdir_log.txt. لاحظ أنّه سوف يتم إرسال رسالة الخطأ أيضًا إلى الطرفية ليتمّ عرضها كنص. الأمر >> الملف يقوم هذا النمط بتوجيه ناتج أمرٍ ما إلى ملفّ دون الكتابة فوق محتويات الملفّ الحالية. مثال: echo Written to a new file > data.txt echo Appended to an existing file's contents >> data.txt هذان الأمران سيقومان أولًا بالكتابة فوق محتويات data.txt، ومن ثمّ سيتم الكتابة أسفل المحتويات الحالية لملفّ data.txt بواسطة الأمر الثاني، محتويات الملفّ يجب أن تبدو هكذا: Written to a new file Appended to an existing file's contents الأمر 2>> الملف يقوم النمط السابق بتوجيه تدفّق خطأٍ معياري لأمرٍ ما إلى ملفّ دون الكتابة فوق محتوياته الحالية. هذا النمط مفيد لإنشاء ملفّّات السجل (log files) لبرنامجٍ أو خدمة، حيث أنّه لن يتم محو محتويات الملفّ السابقة في كلِّ مرةٍ يتم الكتابة فيها إلى الملفّ. find '' 2> stderr_log.txt wc '' 2>> stderr_log.txt يوجّه الأمر أعلاه رسالة الخطأ الصادرة عن معطىٍ خاطئ للأمر find إلى ملفٍّ يُدعى stderr_log.txt. ومن ثمّ يقوم بتوجيه رسالة الخطأ الصادرة عن استخدامٍ خاطئ للأمر wc إلى نفس الملفّ. الأمر | الأمر يقوم بتوجيه خَرْجِ الأمر الأول إلى دَخْلِ الأمر الثاني. find /var lib | grep deb هذا الأمر يبحث عبر مجلّد var/ ومجلّداته الفرعية عن الملفّات والامتدادات المُطابقة للسلسلة "deb"، ويُرجِع مسارات تلك الملفّات مع تمييز الجزء المطابق من أسماء تلك بالملفّات بالسلسلة المبحوث عنها. الأمر | tee الملف هذا النمط (والذي يتضمّن أمر tee) يقوم بتوجيه ناتج أمرٍ معيّن إلى ملفّ والكتابة فوق محتوياته ومن ثمّ يقوم بعرض الناتج المُوجّه بالطرفية. حيثُ ينشئ ملفًّّا جديدًا في حال كان الملفّ غير موجود. في سياق هذا النمط، يتم استخدام الأمر tee عادةً لعرض ناتج أمرٍ معين بينما يتمّ أيضًا حفظه إلى ملفّ. كمثال: wc /etc/magic | tee magic_count.txt هذا الأمر يقوم باستخدام الأنابيب لنقل عدد المحارف، السطور والكلمات في ملفّ etc/magic/ (الذي يتم استخدامه بواسطة صدفة لينكس لتحديد نوع الملفّّات) إلى الأمر tee، والذي بدوره يقوم بفصل ناتج الأمر wc إلى اتّجاهين، ويقوم بإرساله إلى شاشة الطرفية وملفّ magic_counts.txt. بالحديث عن الأمر tee، فتخيّل الحرف T، نهاية هذا الحرف هي البيانات الكاملة، وقمّة هذا الحرف هو البيانات عندما يتم فصلها إلى اتّجاهين (الإخراج المعياري لملفٍّ ما وشاشة الطرفية). أمر | أمر | أمر >> ملف يقوم هذا النمط بتوجيه ناتج الأمر الأوّل وترشيحه عبر الأمرين الثانيين. ومن ثمَّ يقوم بطباعة الناتج إلى ملفّ. مثال: ls ~ | grep *tar | tr e E >> ls_log.txt الخاتمة تعلّم كيفية استخدام قدرات إعادة التوجيه في لينكس عند التعامل مع الأوامر قد يكون شاقًا قليلًا، ولكنك في طريقك بالفعل لاحتراف هذه المهارات بعد إكمالك لهذا الدليل. الآن وبعد أن شاهدت أساسيات كيفية عمل إعادة التوجيه والأنابيب، فستكون قادرًا على بدء رحلتك إلى عالم برمجة سكربتات الشلّ، والذي يستخدم بشكلٍ شائع غالب البرامج والأنماط المُغطّاة في هذا الدليل. إذا كنتَ تحبّ الغوص أكثر في الأوامر التي قدّمناها في هذا الدليل، فيُمكنك ذلك باستخدام الأمر man command | less. كمثال: man tee | less هذا الأمر سيُريك قائمةً كاملة بالأوامر المتوفّرة لبرنامج tee. يمكنك استخدام هذا النمط لعرض المعلومات وخيارات الاستخدام لأيّ أمرٍ أو برنامج في نظام لينكس. ترجمة -وبتصرّف- للمقال: An Introduction to Linux I/O Redirection لصاحبه David Collazo.
×
×
  • أضف...