البحث في الموقع
المحتوى عن 'سطر الأوامر'.
-
عندما يتعامل المستخدم مع مخدم بعيد عنه باستخدام جلسة الصدفة Shell فإن هذا الصدفة يجمع الكثير من المعلومات التي تحدد سلوك الخادم وطريقة النفاذ إلى الموارد. تكون بعض هذه الإعدادات محتواة ضمن الإعدادات وبعضها محتوى ضمن مدخلات المستخدم. يستخدم الصدفة مساحة مخصصة ينشئها عندما يتم تأسيس الجلسة مع الخادم حيث تحتوي هذه البيئة متغيرات تحدد خصائص النظام. نستعرض في المقال كيفية التعامل مع البيئة وقراءة وإعداد المتغيرات الخاصة بالبيئة والمتغيرات الخاصة بالصدفة بشكل مباشر وعن طريق ملفات الإعداد الدائمة. كيف تعمل البيئة ومتغيراتها يتم إنشاء عملية Process في كل مرة يتم فيها إنشاء جلسة صدفة جديدة، تعمل هذه العملية على جمع المعلومات التي يجب توفرها لعملية الصدفة والعمليات التي تتولد عنها. يتم الحصول على هذه المعلومات المتعلقة بالإعدادات من مجموعة متنوعة من الملفات وإعدادات النظام. توفر البيئة وسطًا تستطيع عملية الصدفة استخدامه لقراءة أو ضبط الإعدادات وتمرير هذه القيم إلى العمليات الناتجة عنها أيضًا. يتم صياغة البيئة على هيئة سلاسل نصية تمثل أزواجًا من القيم -مفتاح Key-values. ففي حال تمرير عدة قيم فيتم الفصل بينها بواسطة رمز النقطتين (:) حيث يبدو شكل كل زوج كما يلي: KEY=value1:value2:... يتم استخدام علامة التنصيص المزودجة في حال وجود فراغات ضمن القيمة كما في الشكل التالي: KEY="value with spaces" تمثل المفاتيح في هذه الحالة متغيرات والتي يمكن أن يكون لها أحد نوعين وهي إما متغيرات خاصة بالبيئة أو متغيرات خاصة بالصدفة. تعرّف متغيرات البيئة Environment Variables على أنها متغيرات يتم تعريفها من أجل جلسة الصدفة الحالية كما يتم توريثها إلى أية عمليات أو جلسات صدفة مرتبطة بالصدفة الأم. تستخدم متغيرات البيئة لتمرير المعلومات إلى العمليات التي يتم إنشاؤها من الصدفة الذي قام بإنشاء المتغير. أما متغيرات الصدفة Shell Variables فهي متغيرات محتواة بشكل حصري ضمن الصدفة الذي تم تعريفها ضمنه وتستخدم عادة لتعقب بعض المعطيات التجريبية مثل طباعة مسار العمل الحالي. نميز اصطلاحًا بين هذين النوعين أن متغيرات الجلسة تكون مكتوبة بأحرف كبيرة وذلك لتمييزها عن متغيرات البيئة التي تكتب بحروف صغيرة. طباعة متغيرات الصدفة والبيئة ترتبط كل جلسة صدفة بمتغيرات البيئة والصدفة المرتبطة بها. يمكن النفاذ إلى هذه المتغيرات بعدة طرق. نستعرض متغيرات البيئة المتاحة بتنفيذ الأمر env أو printenv وفي حال عدم إجراء أية تعديلات على طريقة العمل فالأمرين السابقين يعملان دون اختلاف. printenv يظهر عندها خرج مشابه لما يلي مع الأخذ بعين الاعتبار أن عدد المتغيرات يختلف من جهاز لآخر: SHELL=/bin/bash TERM=xterm USER=demouser LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:su=37;41:sg=30;43:ca:... MAIL=/var/mail/demouser PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games PWD=/home/demouser LANG=en_US.UTF-8 SHLVL=1 HOME=/home/demouser LOGNAME=demouser LESSOPEN=| /usr/bin/lesspipe %s LESSCLOSE=/usr/bin/lesspipe %s %s _=/usr/bin/printenv لا يوجد اختلاف أي من الأمرين السابقين يتم تنفيذه فيجب أن يبقى الخرج ذاته بالحالتين أما عن الاختلاف بين الأمرين فيظهر عند تخصيص الأمر printenv إذ يمكن أن يطبع المسارات الخاصة بالمتغيرات مثلا بتنفيذ الأمر التالي: printenv PATH فيظهر عندها خرج مشابه لما يلي: /usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games بينما يسمح الأمر env بتعديل البيئة التي تستخدمها البرامج عبر تمرير مجموعة من المتغيرات بالشكل التالي: env VAR1="value" command_to_run command_options ترث العمليات الناشئة متغيرات البيئة من العملية الأب مما يسمح بإعادة تحميل بعض القيم أو إضافة متغيرات لبيئة العملية الابن. نستعرض المتغيرات الخاصة بالصدفة باستخدام الأمر set ولكن تجدر الإشارة إلى أنه في حال تنفيذ هذا الأمر بدون أية إضافات فيتم عرض قائمة بجميع متغيرات الصدفة والبيئة وحتى المتغيرات المحلية والتوابع الخاصة بالصدفة ويتم ذلك بتنفيذ الأمر: set يظهر خرج مشابه لما يلي: BASH=/bin/bash BASHOPTS=checkwinsize:cmdhist:expand_aliases:extglob:extquote:force_fignore:histappend:interactive_comments:login_shell:progcomp:promptvars:sourcepath BASH_ALIASES=() BASH_ARGC=() BASH_ARGV=() BASH_CMDS=() . . . نظرًا لأن هذه القائمة تكون كبيرة فمن الأفضل تقليل عدد الأسطر البرمجية التي سيتم عرضها ويتم ذلك بتنفيذ الأمر التالي: set | less تبقى كمية المعلومات كبيرة وبعضها ليس مفيدًا مثل بعض التوابع لهذا يمكن تنظيف هذا الخرج بتوجيه الأمر set ليعمل ضمن نمط POSIX بحيث لن تطبع توابع الصدفة ويتم ذلك بتنفيذ الأمر التالي: (set -o posix; set) تظهر قائمة بمتغيرات البيئة والصدفة التي تم تعريفها بشكل مسبق، يمكن تنفيذ مقارنة بين خرج الأمر env و printenv لمحاولة استخلاص متغيرات الصدفة فقط ولكن ذلك لن يكون عمليًا نظرًا لتعدد الطرق التي يعرض فيها كل من الأوامر السابقة نتائجه، تتم عملية المقارنة بتنفيذ الأمر التالي: comm -23 <(set -o posix; set | sort) <(env | sort) يمكن أن يظهر في الخرج بعض متغيرات البيئة نظرًا لأنّ الأمر set يضيف قيم محاطة بإشارات تنصيص بينما لا يستخدم الأمران envو printenv هذه الطريقة مما قد يسبب بعض الاختلافات ولكن يعطي ذلك المستخدم فكرة جيدة عن المتغيرات المستخدمة ضمن البيئة. يعد الاستخدام الأهم لهذه المتغيرات أنها تسمح بإتاحة قيم دائمة تستخدم بين العمليات دون الحاجة إلى كتابتها ضمن ملفات. متغيرات الصدفة والبيئة الشائعة توجد مجموعة كبيرة من متغيرات البيئة والصدفة التي يتم استخدامها بشكل متكرر من قبل المستخدمين، نذكر منها: المتغير SHELL: يصف هذا المتغير الصدفة الذي سيقوم بتفسير الأوامر التي يدخلها المستخدم وتمريرها لنواة نظام التشغيل، يشير المتغير إلى الصدفة bash بشكل افتراضي ولكن يمكن تغيير هذه القيمة إذا اقتضت الحاجة ذلك. المتغير TERM: يحدد هذا المتغير نوع موجه الأوامر الذي سيستخدم عند تنفيذ أمر ما عن طريق الصدفة، تختلف هذه الأنواع تبعًا لمتطلبات التشغيل ولا يتم تغيير قيمة هذا المتغير عادة. المتغير USER: يحدد المستخدم الحالي الذي سجل دخول إلى نظام التشغيل. المتغير PWD: يحدد مسار العمل الحالي. المتغير OLDPWD: يحدد مسار العمل السابق، ويتم استخدام هذا المتغير لإمكانية العودة إلى المسار السابق باستخدام الأمر cd -. *المتغير LS_COLORS:يحدد نمط الألوان المستخدم والذي تتم إضافته -بشكل خياري- إلى خرج الأمر ls بيحث يتم التمييز بين أنواع الملفات عن طريق اللون مما يسهل العمل على المستخدم بشكل كبير. المتغير MAIL: يحدد المسار إلى صندوق البريد الخاص بالمستخدم. المتغير PATH: يتضمن هذا المتغير قائمة المجلدات التي سيفحصها نظام التشغيل بالترتيب للبحث عن الملفات التنفيذية الخاصة بالأوامر التي يدخلها المستخدم. المتغير LANG: يشير هذا المتغير إلى اللغة الحالية والخيارات المحلية إضافة إلى نوع ترميز المحارف المستخدم. المتغير HOME: تشير إلى مسار المجلد الافتراضي الخاص بالمستخدم الحالي. المتغير _: يشير إلى أحدث أمر قد تم تنفيذه. بالإضافة إلى متغيرات الصدفة التالية التي يصادفها معظم المستخدمون في أعمالهم: المتغير BASHOPTS: يتضمن قائمة بالخيارات المستخدمة عندما تنفيذ الأمر الخاص بالصدفة Bash ويفيد ذلك في التأكد من أنّ بيئة الصدفة ستعمل وفق ما هو متوقع أم لا. المتغير BASH_VERSION: يشير إلى رقم الإصدار الخاص بالصدفة Bash بشكل مقروء بالنسبة للمستخدم. المتغير BASHVERSINFO: يشير إلى رقم الإصدار الخاص بالصدفة Bash بشكل خاص بالآلة. المتغير COLUMNS: يشير إلى عدد الأعمدة الذي يمكن استخدامه لعرض خرج الأوامر بما يناسب الشاشة. المتغير DIRSTACK: يتضمن قائمة بالمجلدات المخصصة للمكدسات stacks والتي يتم استخدامها مع أوامر pushd وpopd. المتغير HISTFILESIZE: يشير إلى عدد الأوامر السابقة التي يتم حفظها ضمن الملف الخاص بحفظ الأوامر السابقة. المتغير HOSTNAME: يتضمن اسم المضيف الخاص بالحاسب المستخدم. المتغير IFS: يشير هذا المتغير إلى الفاصل المستخدم بين الكلمات التي يدخلها المستخدم وهي فراغ space بشكل افتراضي. المتغير PS1: يحدد هذا المتغير المؤشر الخاص بموجه الأوامر الرئيسي فنلاحظ بشكل افتراضي أنه يطبع اسم المستخدم الحالي واسم الحاسب بشكل افتراضي إلا أنه يمكن تخصيص هذه الطباعة بتعديل قيمة هذا المتغير، بينما يشير المتغير PS2 إلى تعريف المؤشرات الثانوية عندما يمتد الأمر لأكثر من سطر واحد. المتغير SHELLOPTS: يشير إلى خيارات الصدفة التي يمكن إعدادها باستخدام الأمر set. المتغير UID: يشير إلى رقم التعريف الخاص بالمستخدم UID الخاص بالمستخدم الحالي. إعداد متغيرات البيئة والصدفة تبين الفقرات التالية خطوات إنشاء النوعين السابقين من المتغيرات ويفيد ذلك في التمييز بين هذين النوعين: إنشاء متغيرات الصدفة يمكن تعريف متغير الصدفة للجلسة الحالية بسهولة عبر كتابة اسم المتغير والقيمة التي يتم إسنادها له، يتم ذلك بتنفيذ الأمر التالي: TEST_VAR='Hello World~' نلاحظ استخدام علامة التنصيص بسبب وجود فراغ ضمن قيمة المتغير أما سبب استخدام علامة التنصيص المفردة بدلًا عن المزدوجة كما وضحنا في الفقرة السابقة هو وجود إشارة التعجب والتي تعد محرفًا خاصًا ويستدعي استخدام علامة التنصيص الإفرادية معه أو استخدام محرف الهروب (/) وإلا فإنه سيتم تنفيذ الأمر الخاص بالمحرف المميز وهو في حالة إشارة التعجب استدعاء أمر تم تنفيذه مسبقًا من قائمة الأوامر. أصبح هذا المتغير متاحًا ضمن الجلسة الحالية ولكنه لن يمرر إلى الجلسات التي تنتج عنها، نستعرض هذا المتغير بتنفيذ الأمر: set | grep TEST_VAR يظهر عندها الخرج التالي: TEST_VAR='Hello World!' نتحقق من أنّ هذا المتغير ليس من ضمن متغيرات البيئة بتنفيذ الأمر التالي: printenv | grep TEST_VAR لن تظهر قيمة المتغير في هذه الحالة، نستعرض قيمة المتغير بتنفيذ الأمر echo كما في الشكل: echo $TEST_VAR يظهر عندها الخرج التالي: Hello World! يدرك الصدفة بمجرد وجود رمز $ أن النص التالي يمثل اسم متغير وليس قيمة ثابتة ليقوم بطباعتها كما هي، لنتحقق أنّ هذا المتغير لن يمرر إلى العمليات الناتجة من العملية التي قامت بإنشائه ونبدأ ذلك بإنشاء جلسة صدفة جديدة باستخدام الأمر bash كما يلي" bash echo $TEST_VAR لن تظهر قيمة المتغير في هذه الحالة، نغادر الجلسة الجديدة بتنفيذ الأمر exit الذي يعيدنا إلى جلستنا الأصلية: exit إنشاء متغيرات البيئة نستطيع تحويل متغير الصدفة إلى متغير بيئة عبر تنفيذ ما يعرف بالتصدير export وذلك بتنفيذ الأمر: export TEST_VAR يصبح عندها هذا المتغير خاصًا بالبيئة ونتحقق من ذلك بتنفيذ الأمر التالي: printenv | grep TEST_VAR ليظهر عندها الخرج التالي: TEST_VAR=Hello World! نعيد التجربة السابقة ونتأكد من تمرير المتغير إلى الجلسات الناتجة عن هذه الجلسة بتنفيذ الأوامر التالية: bash echo $TEST_VAR يظهر عندها الخرج التالي: Hello World! أي أنّ العملية الابن استطاعت الحصول على قيمة المتغير. نتأكد أيضًا من قدرتها على إنشاء متغيرات البيئة بتنفيذ الأمر: export NEW_VAR="Testing export" نتحقق من قيمة المتغير بتنفيذ الأمر: printenv | grep NEW_VAR ليظهر الخرج التالي: NEW_VAR=Testing export نعود إلى جلسة الصدفة الأصلية بتنفيذ الأمر التالي: exit ونتحقق من قيمة المتغير الذي تم إنشاؤه بتنفيذ الأمر: echo $NEW_VAR لن يظهر شيء على خرج الشاشة. يعود سبب ذلك إلى أنّ متغيرات البيئة يتم تمريرها من العملية الأب تمرر إلى العملية الابن فقط وليس بالعكس ويعد ذلك مفيدًا في منع البرامج من التأثير على بيئة التشغيل الأساسية التي تحويهم. بعد أن تم الخروج من صدفة الابن تم هدم البيئة وبالتالي إزالة المتغير ولهذا لم تظهر قيمته. إزالة وتخفيض مستوى المتغيرات يمكن للمستخدم إعادة متغير البيئة ليصبح متغير صدفة عبر عملية تعرف باسم تخفيض المستوى demote والتي تُنفّذ بالشكل التالي: export -n TEST_VAR ننفذ الأمر التالي للتحقق بأن هذا المتغير لم يعد خاصًا بالبيئة: printenv | grep TEST_VAR ولكن يجب أن يظهر ضمن قائمة متغيرات الصدفة ونتحقق من ذلك بتنفيذ الأمر: set | grep TEST_VAR ليظهر عندها الخرج التالي: TEST_VAR='Hello World!' نستطيع إزالة المتغير سواء كان متغير بيئة أم متغير صدفة باستخدام الأمر unset بالشكل التالي: unset TEST_VAR ونتأكد من أنّ المتغير لم يعد موجودًا بتنفيذ الأمر التالي: echo $TEST_VAR لن يظهر أي خرج على الشاشة لأن المتغير تمت إزالته. إعداد متغيرات البيئة عند تسجيل الدخول تستخدم العديد من البرامج متغيرات البيئة لتحدد بعض خصائص عملها، وبما أنّ بعض القيم مهمة فلا داعي إلى إعدادها في كل مرة يتم فيها تأسيس جلسة عمل كما أنّ بعض قيم هذه المتغيرات ترتبط بالمستخدم والذي يتم تحديده بعد تسجيل الدخول. الاختلاف بين جلسات الصدفة التفاعلية وغير التفاعلية وذات تسجيل الدخول وبدون تسجيل الدخول يقرأ صدفة bash العديد من ملفات الإعداد المتعلّقة ببدء الجلسة، ومن أهم الاختلافات بين الجلسات أن عملية إنشاء الصدفة تمت بتسجيل دخول login أو بدون تسجيل دخول non-login. تبدأ جلسة الصدفة مع تسجيل الدخول بمصادقة المستخدم user authentication كما يتم عند تسجيل الدخول إلى مخدم باستخدام بروتوكول الاتصال الآمن SSH حيث يتم طلب اسم المستخدم وكلمة المرور أما إذا أنشأ المستخدم جلسة صدفة جديدة باستخدام الأمر bash كما تم في المثال السابق فإنه في هذه الحالة أنشأ جلسة صدفة دون تسجيل دخول حيث لن يُسأل المستخدم عن اسم المستخدم وكلمة المرور. يتم التمييز أيضًا بين الجلسات فيما إذا كانت تفاعلية Interactive أو غير تفاعلية Non-Interactive حيث أنّ الجلسة التفاعلية تتصل بموجه أوامر محدد أما جلسة الصدفة غير التفاعلية فلا تحقق ذلك. إذا تصنف كل جلسة صدفة بأنها تفاعلية أم لا وأنها تمت بتسجيل دخول أم بدونه. تعد جلسة الصدفة التي تبدأ عند استخدام بروتوكول SSH مثالًا على جلسة الصدفة التفاعلية التي تتم بتسجيل دخول بينما يعد تشغيل نص برمجي ما عن طريق موجه الأوامر مثالًا على جلسة صدفة غير تفاعلية بدون تسجيل دخول علمًا أن جلسة موجه الأوامر يمكن أن تكون مزيجًا من الخصائص السابقة. يتم في حالة جلسة الصدفة التي تتطلب تسجيل دخول قراءة الإعدادات والتفاصيل من الملف /etc/profile ومن ثم تبحث عن أول ملف خاص بالصدفة ضمن المجلد الأساسي الخاص بالمستخدم للحصول على أية إعدادات إضافية خاصة بالمستخدم حيث تقرأ الملف الموجود في المسار~/.bash_profile أو ضمن المسار ~/.bash_login أو ضمن المسار ~/.profile وفي حال لم تعثر على ملف فلن تبحث في أية مجلدات أخرى. أما في حالة جلسة الصدفة التي تتم دون تسجيل دخول فتتم قراءة الملف /etc/bash.bashrc ومن ثم قراءة الملف ~/.bashrc الخاص بالمستخدم لبناء البيئة. أما الصدفة غير التفاعلي فيقرأ متغير البيئة BASH_ENV الذي يحوي مسار إلى ملف إعدادات والذي يستخدمه من أجل تعريف البيئة الجديدة. صياغة متغيرات البيئة يتيح عدد الملفات الكبير المتعلق بمكان تعريف متغيرات البيئة المرونة في العمل حيث يمكن ضبط بعض الإعدادات لحالات معينة عند تسجيل الدخول مثلًا وعدم إتاحتها في حال عدم تسجيل الدخول ولكن عمليًا تظهر الحاجة إلى تعريف بعض المتغيرات التي تكون مشتركة ضمن جميع أنواع الصدفة المتاحة. يتيح نظام التشغيل لينكس هذا الخيار، فعندما يحتاج المستخدم إلى تعريف متغيرات بيئة خاصة بالمستخدم بحيث تكون متاحة سواء سجل المستخدم الدخول أم لا فيمكن استخدام الملف ~/.bashrc والذي يمكن تعديله باستخدام محرر النصوص المتاح كما يلي: nano ~/.bashrc يتضمن هذا الملف عددًا كبيرًا من المتغيرات ومعظمها يكون متعلقًا بإعدادات الصدفة bash والتي ليست متعلقة فعليًا بمتغيرات البيئة. يمكن إعداد المتغيرات كما تم إعدادها بموجه الأوامر بالشكل التالي: export VARNAME=value يمكن إضافة أي متغير بيئة ضمن أي سطر في الملف ~/.bashrc بشرط عدم دمجه بمتغير آخر أو كتابته ضمن حلقة تكرار موجودة مسبقًا.نحفظ الملف ونغلقه وعند بدء جلسة صدفة جديدة يتم التصريح عن متغير البيئة الجديد وقراءته وتمريره لبيئة الصدفة أما إذا رغب المستخدم بإجبار الجلسة الحالية على قراءة هذا الملف فيتم ذلك بتنفيذ الأمر التالي: source ~/.bashrc يمكن عند الحاجة لاستخدام متغيرات يمكن استخدامها ضمن نظام التشغيل كاملًا إضافتها إلى الملف /etc/profile أو /etc/bash.bashrc أو /etc/environment. الخاتمة توجد متغيرات الصدفة والبيئة دومًا ضمن جلسات الصدفة حيث تعد هذه المتغيرات ذات فائدة كبيرة بالنسبة للمستخدمين. يعد الاستخدام الأساسي لهذه المتغيرات أن تتحكم العملية الأب بكامل تفاصيل العمليات الأبناء لها سواء تم ذلك عن طريق الملفات أو بدونها. توجد العديد من الحالات التي يعد استخدام متغيرات البيئة ضروريًا فعلى سبيل المثال، تعتمد بعض آليات نشر وتوزيع التطبيقات على متغيرات البيئة لإعداد المصادقة authentication والاحتفاظ ببعض المعلومات الهامة حيث لا يمكن الاحتفاظ بهذه المعلومات ضمن ملفات نظرًا لحساسيتها حيث أنها قد تصبح قابلة للقراءة من قبل جهات غير مخولة بالاطلاع على المحتوى. ترجمة وبتصرف للمقال How To Read and Set Environmental and Shell Variables on Linux لصاحبه Justin Ellingwood. اقرأ أيضًا مدخل إلى كتابة سكربتات الصدفة Shell Scripts؟ ما هو سطر الأوامر؟ أهم 20 أمرا في نظام التشغيل لينكس لجميع المستخدمين
-
دعنا نفترض أنَّك تكتب سلسلة من البرامج التعليمية لـ Blender وأنك تستخدم PrintScreen لأخذ لقطات الشاشة. يمنحك هذا دليلًا مليئًا بالصور الضخمة غير المُحسَّنة للتحميل إلى صفحة ويب وعرضها. آخر شيء تريد القيام به هو تغيير حجمها يدويًا. انت محظوظ! باستخدام خيار تغيير الحجم -resize يمكنك بسرعة وسهولة تغيير حجم هذه الصور إلى حجم يمكن التحكم فيه. ضع كل الصور التي تريد توسيع نطاقها في مجلد وانتقل إلى موقع الدليل عبر سطر الأوامر. ثم أدخل الأمر التالي: mogrify -resize 960x528 *.png يقوم هذا الأمر بتغيير حجم جميع ملفات png. في الدليل إلى حجم 960 بكسل في 528 بكسل. ربَّما الارتفاع ليس بنفس أهمية العرض. يمكنك ببساطة كتابة الأمر السابق على النحو التالي: mogrify -resize 960 *.png سيؤدي هذا إلى تغيير حجم جميع صورك إلى 960 بكسل، وسيتمُّ تغيير الارتفاع وفقًا لذلك، محافظًا على نسبة العرض إلى الارتفاع. ربما لديك الطول والعرض الذي تريده، لكنك ترغب في الحفاظ على نسبة العرض إلى الارتفاع. يمكنك إدخال الأمر على النحو التالي: mogrify -resize 960x528! *.png سيؤدِّي ذلك إلى توسيع نطاق صورك إلى 960 × 528 بكسل متى كان ذلك ممكناً، لكنَّه سيحافظ على نسبة العرض إلى الارتفاع لتلك الصور التي لن يتم تكبيرها إلى هذه الأبعاد بالضبط. ترجمة -وبتصرّف- للمقال ImageMagick Tutorial: How To Batch Resize Images on the Command Line لصاحبه Jared
-
- imagemagick
- الصور
-
(و 1 أكثر)
موسوم في:
-
دعنا نفترض أنك تكتب سلسلة من البرامج التعليمية على Blender وأنك تستخدم مفتاح PrintScreen لالتقاط لقطات الشاشة. إنَّ مفتاح PrintScreen رائع، لكنه يمسك بكل شيء. ربَّما لا تريد أن يظهر تطبيقك في كل صورة. وربما لا تريد تحرير عشرات الصور يدويًا. أنت محظوظ! لدى برنامج ImageMagick وسيلة سهلة لاستخدام وظيفة الاقتصاص للصور التي يمكنك تنفيذها بسرعة وسهولة من سطر الأوامر. إذا لم تكن قد قمت بالفعل بتثبيت البرنامج، فاحصل على ImageMagick بالطريقة السهلة: sudo apt-get install imagemagick ضع كل الصور التي تريد اقتصاصها في مجلد وانتقل إليه عبر سطر الأوامر. في المثال الذي أستخدمه هنا، أرغب في قطع البيكسلات السفلية البالغ عددها 25 بكسل من سلسلة صور png. نفِّذْ الأمر التالي للقيام بذلك: mogrify -format png -gravity south -chop 0x25 *.png الرايات التي استعملناها مع الأمر هي: :-format png ينص الخيار بإخراج الملف بصيغة png. :-gravity south ينصُّ الخيار ببدء الاقتصاص من أسفل الصورة. :-chop 0x25 ينصُّ الخيار بقصَّ 25 بكسلًا من الارتفاع. *.png: ينصُّ الخيار بتطبيق جميع ما سبق على أي ملف ذو اللاحقة png. أدناه ملفي الأصلي: والصورة المشذبة حديثا: ترجمة -وبتصرّف- للمقال ImageMagick Tutorial: How To Batch Crop Images on the Command Line لصاحبه Jared
-
- imagemagick
- اقتصاص الصور
-
(و 2 أكثر)
موسوم في:
-
سنتعلم في هذا الدرس من سلسلة مدخل إلى كتابة سكربتات الصدفة كيفية إضافة "ذكاء" إلى سكربتاتنا، فإلى الآن كان يحتوي مشروعنا على سلسلة من الأوامر التي يبدأ تنفيذها من بداية الملف ويستمر سطرًا بسطر إلى أن يصل إلى نهاية الملف. لكن إمكانيات أغلبية البرامج أكبر من ما سبق، حيث تستطيع "اتخاذ القرارات" وإجراء عمليات مختلفة بناءً على مجموعة من الشروط. توفِّر الصَدَفة عدِّة أوامر يمكننا استخدامها للتحكم في جريان تنفيذ البرنامج، وسنتعلم في هذا الدرس: if test exit الأمر if أول أمر سنلقي عليه نظرةً هو الأمر if، يبدو من أول وهلة أنَّ الأمر if بسيط جدًا، لأنه يتخذ قرارًا بناءً على "حالة الخروج" (exit status) لأحد الأوامر. الشكل العام لأمر if: if commands; then commands [elif commands; then commands...] [else commands] fi حيث commands هي مجموعة أوامر. قد تبدو الأمور مربكةً بعض الشيء في البداية، لكن قبل شرح الأمر if بالتفصيل، لنلقِ نظرة على آلية معرفة الصَدَفة لنجاح أو فشل تنفيذ أمر ما. حالة الخروج تُرسِل الأوامر (بما في ذلك السكربتات ودوال الصدفة التي نكتبها) قيمة إلى النظام عند انتهاء تنفيذها تُسمى "حالة الخروج" (exit status)؛ هذه القيمة (والتي هي عدد صحيح يتراوح ما بين 0 و 255) تُشير إلى نجاح أو فشل تنفيذ الأمر. من الأعراف البرمجية أن تكون القيمة 0 تعني نجاح التنفيذ وأي قيمة أخرى تعني فشله. توفِّر الصَدَفة معاملًا (parameter) خاصًا لتفحص حالة الخروج لآخر أمر مُنفَّذ: $ ls -d /usr/bin /usr/bin $ echo $? 0 $ ls -d /bin/usr ls: cannot access /bin/usr: No such file or directory $ echo $? 2 نفَّذنا -في المثال السابق- الأمر ls مرتين، حيث نُفِّذ تنفيذًا سليمًا في أول مرة، فلو عرضنا قيمة المعامل $? فسنرى أنها تساوي الصفر؛ ثم نفَّذنا الأمر ls مرةً أخرى لكنه عرض رسالة خطأ وعندما طبعنا قيمة المعامل $? مرةً أخرى فسنرى أنَّها تساوي 2، مما يشير إلى أنَّ آخر أمر قد نُفِّذ واجه مشكلةً. تستعمل بعض الأوامر حالات خروج مختلفة لتوفير معلومات حول الخطأ، لكن العديد من الأوامر تستعمل الرقم 1 فقط للإشارة إلى باقي أنواع الأخطاء. تحتوي صفحات الدليل man عادةً على قسم مُعنوَن "Exit Status" يشرح ما هي أرقام حالات الخروج المحتملة، لكن تذكَّر أنَّ 0 تُشير دائمًا إلى نجاح التنفيذ. توفِّر الصَدَفة أمرَين مُضمَّنين فيها بسيطين للغاية، كلُ ما يفعلانه هو الانتهاء بحالة خروج 0 أو 1. ينجح تنفيذ الأمر true دائمًا ويفشل تنفيذ الأمر false دائمًا: $ true $ echo $? 0 $ false $ echo $? 1 يمكننا استخدام هذه الأوامر لتجربة عبارة if الشرطية. ما تفعله عبارة if هو أنَّها تتحقق من نجاح أو فشل تنفيذ الأوامر التي تليها: $ if true; then echo "It's true."; fi It's true. $ if false; then echo "It's true."; fi $ يُنفَّذ الأمر echo "It's true." عندما يُنفَّذ الأمر الذي يلي كلمة if بنجاح، ولن يُنفَّذ عندما يفشل تنفيذ الأمر الذي يلي كلمة if. الأمر test يُستخدَم الأمر test كثيرًا مع الأمر if لإنتاج القيمة true أو false. هذا الأمر غير اعتيادي لأنَّ له شكلان مختلفان: # الشكل الأول test expression # الشكل الثاني [ expression ] آلية عمل الأمر test بسيطةٌ جدًا، فلو كان التعبير (expression) الذي يليه صحيحًا، فسينتهي تنفيذ الأمر test بحالة خروج تساوي الصفر؛ فيما عدا ذلك سينتهي بحالة خروج تساوي 1. من أهم مميزات الأمر test تنوع التعابير التي تستطيع كتابتها فيه؛ هذا مثالٌ بسيط: if [ -f .bash_profile ]; then echo "You have a .bash_profile. Things are fine." else echo "Yikes! You have no .bash_profile!" fi استخدمنا في المثال السابق التعبير -f .bash_profile الذي يقول: "هل الملف .bash_profile موجود؟" فإن كان موجودًا فسينتهي الأمر test بحالة خروج تساوي الصفر (أي true) وسيُنفِّذ الأمر if الأوامر التي تتبع الكلمة then؛ وإذا لم يكن الملف موجودًا فسينتهي الأمر test بحالة خروج تساوي الواحد (أي false) وسيُنفِّذ الأمر if الأوامر التي تلي الكلمة else. هذه قائمة مختصرة بالتعابير التي يمكن استعمالها في الأمر test. ولمّا كان الأمر test مُضمَّنًا في الصَدَفة (shell builtin)، فتستطيع استخدام help test لرؤية القائمة الكاملة. -d dir: الناتج هو true إذا كان dir مجلدًا. -e file: الناتج هو true إذا كان file موجودًا. -f file: الناتج هو true إذا كان file ملفًا عاديًا موجودًا. -L file: الناتج هو true إذا كان file وصلةً رمزيةً (symbolic link). -r file: الناتج هو true إذا كنت تستطيع قراءة الملف file. -w file: الناتج هو true إذا كنت تستطيع الكتابة على الملف file. -x file: الناتج هو true إذا كنت تستطيع تنفيذ الملف file. file1 -nt file2: الناتج هو true إذا كان الملف file1 أحدث (وفقًا لوقت التعديل [modification time]) من الملف file2. file1 -ot file2: الناتج هو true إذا كان الملف file1 أقدم من file2. -z string: الناتج هو true إذا كنت السلسلة النصية string فارغة. -n string: الناتج هو true إذا لم تكن السلسلة النصية string فارغة. string1 = string2: الناتج هو true إذا كانت السلسلة النصية string1 مساويةً للسلسلة النصية string2. string1 != string2: الناتج هو true إذا لم تكن السلسلة النصية string1 مساويةً للسلسلة النصية string2. قبل أن نواصل أريد أن أشرح بقية المثال السابق لأنه يبرز عددًا من الأفكار المهمة. رأينا في بداية السكربت الأمر if متبوعًا بالأمر test متبوعًا بفاصلة منقوطة وفي النهاية الكلمة then. اخترت استعمال الشكل [ expression ] للأمر test لأنَّ أغلبية الناس يرون أنَّ قراءته أسهل. لاحظ أنَّ الفراغات مطلوبة بين قوس البداية ] وبداية التعبير، وكذلك الفراغ بين نهاية التعبير وقوس الإغلاق [. تعمل الفاصلة المنقوطة كفاصل بين الأوامر، مما يسمح بوضع أكثر من أمر في نفس السطر. مثلًا: $ clear; ls سيؤدي إلى مسح الشاشة ثم تنفيذ الأمر ls. استخدمتُ الفاصلة المنقوطة في عبارة if السابقة لأنني أريد وضع الكلمة then في نفس سطر الأمر if لأنني أرى أنَّها قراءتها أسهل بهذه الطريقة. سنشاهد صديقنا القديم echo في السطر الثاني، لكنك ستلاحظ وجود محاذاة (أي فراغات قبل الأمر)، وهذا لغرض تسهيل قابلية القراءة، ومن التقاليد البرمجية أن نحاذي جميع الأوامر داخل العبارة الشرطية if (أي جميع الأسطر التي ستُنفَّذ عند تحقيق شرط معيّن). تذكَّر أنَّ الصَدَفة لا تتطلَّب فعل ذلك، لكننا نفعله لجعل قراءة الشيفرة أسهل. بعبارة أخرى، يمكننا كتابة الشيفرات الآتية وسنحصل على نفس النتيجة: # Alternate form if [ -f .bash_profile ] then echo "You have a .bash_profile. Things are fine." else echo "Yikes! You have no .bash_profile!" fi # Another alternate form if [ -f .bash_profile ] then echo "You have a .bash_profile. Things are fine." else echo "Yikes! You have no .bash_profile!" fi الأمر exit لكي نكتب سكربتات صدفة جيدة، فعلينا ضبط حالة خروج عندما ينتهي تنفيذ السكربت، ونستعمل الأمر exit لفعل ذلك، الذي يؤدي إلى إيقاف تنفيذ السكربت فوريًا وضبط حالة الخروج إلى القيمة المُمرَّرة كوسيط إليه. على سبيل المثال، الأمر الآتي: exit 0 سيؤدي إلى إيقاف تنفيذ السكربت وضبط حالة الخروج إلى 0 (أي نجاح التنفيذ)، بينما: exit 1 سيؤدي إلى إيقاف تنفيذ السكربت وضبط حالة الخروج إلى 1 (أي فشل التنفيذ). التحقق من أن المستخدم المشغل للسكربت هو الجذر آخر مرة تركنا فيها السكربت كنا نحتاج إلى تشغيله بامتيازات الجذر، وذلك لأنَّ الدالة home_space تحتاج إلى معرفة المساحة التخزينية التي تستهلكها مجلدات المنزل للمستخدمين. لكن ماذا سيحدث لو حاول مستخدمٌ عادي تشغيل السكربت؟ سيؤدي ذلك إلى إظهار الكثير من رسائل الخطأ القبيحة. لكن ماذا لو وضعنا شيئًا في السكربت يمنع تنفيذه من المستخدم العادي؟ الأمر id يخبرنا من هو المستخدم الحالي، وعند تمرير الخيار -u إليه فسيطبع قيمة عددية لمُعرِّف المستخدم (user ID) الحالي. $ id -u 501 $ su Password: # id -u 0 فلو نفَّذ المستخدم الجذر الأمر id -u فسيكون الناتج هو 0، ويمكننا أن نستثمر هذه المعلومة لكي تكون الأساس الذي سنبني عليه الاختبار الذي سنضعه في السكربت: if [ $(id -u) = "0" ]; then echo "superuser" fi تحققنا في المثال السابق أنَّ ناتج الأمر id -u مساوٍ للسلسلة النصية "0" ثم طبعنا العبارة "superuser". وعلى الرغم من أنَّ الأمر السابق يكتشف إن كان المستخدم هو المستخدم الجذر، إلا أنَّه لم يحل المشكلة بعد. إذ نريد أن يتوقف تنفيذ السكربت إن لم يكن المستخدم المُشغِّل له هو الجذر، لذلك نكتب الشيفرة الآتية: if [ $(id -u) != "0" ]; then echo "You must be the superuser to run this script" >&2 exit 1 fi نتحقق في الشيفرة السابقة أنَّ ناتج الأمر id -u لا يساوي "0"، ثم سيطبع السكربت رسالة خطأ مفهومة، ثم ينتهي تنفيذه بحالة خروج مساوية للواحد، لكي يخبر النظام أنَّه لم يتم التنفيذ بنجاح. لاحظ وجود >&2 في نهاية الأمر echo، الذي هو شكلٌ من أشكال إعادة توجيه الدخل والخرج (I/O redirection)، وسترى هذا التعبير عادةً في نهاية الأوامر التي تطبع رسائل خطأ، لأننا لو لم نُعِد توجيه مجرى الخطأ هنا، فسترسَل رسالة الخطأ إلى مجرى الخرج القياسي (standard output stream)، لكننا نريد أن تظهر رسائل الخطأ بمعزل عن مخرجات السكربت، لأننا نعيد توجيه مجرى الخرج القياسي الناتج من تنفيذ السكربت إلى ملف. علينا أن نضع الأسطر السابقة في بداية السكربت لكي نتمكن من تحديد هوية المستخدم المُشغِّل قبل أن يقع الخطأ، لكننا نريد في الوقت نفسه أنَّ يمكن المستخدمون العاديون من تشغيل السكربت، لذلك سنعدِّل الدالة home_space لكي تتأكد من امتيازات المستخدم كالآتي: function 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 بهذه الطريقة سيتمكن المستخدم العادي من تشغيل السكربت، وسيتم تجاوز الشيفرة التي قد تتسبب بخطأ بدلًا من تنفيذها وإظهار رسالة للمستخدم. ترجمة -وبتصرّف- للمقال Flow Control - Part 1 لصاحبه William Shotts.
-
- 1
-
- exit
- سطر الأوامر
- (و 10 أكثر)
-
عندما يزداد طول البرامج وتعقيدها، فستزداد صعوبة تصميمها وبرمجتها وصيانتها؛ لذا من المفيد عادةً تقسيم المهام الكبيرة إلى سلسلة من المهام الأصغر. سنُقسِّم في هذا الدرس السكربت الذي كنا نعمل عليه إلى عدد من الدوال (functions) المنفصلة. لكي نتعرف على مفهوم الدوال، فلنحاول وصف طريقة القيام بمهمة يومية: الذهاب إلى السوق وشراء الطعام. تخيل أننا سنصف العملية إلى كائنات فضائية آتية من المريخ. سيبدو الوصف العام لعملية شراء الطعام كالآتي: غادر المنزل قد السيارة إلى السوق اركن السيارة ادخل السوق اشترِ طعامًا قد السيارة إلى المنزل اركن السيارة ادخل إلى المنزل سيُغطِّي الشرح السابق الآلية العامة للذهاب إلى السوق؛ لكن تلك الكائنات الفضائية ستحتاج مزيدًا من التفاصيل، فمثلًا يمكن وصف المهمة الفرعية "اركن السيارة" كالآتي: اعثر على مكان فارغ لركن السيارة قد السيارة إلى ذاك المكان أطفئ المحرك "ارفع" المكابح اليدوية اخرج من السيارة اقفل السيارة ويمكن بالطبع تقسيم خطوة "أطفئ المحرك" إلى عدد من الخطوات مثل: أطفئ دارة الإشعال أخرج مفتاح السيارة وهكذا إلى أن تُفصِّل كل خطوة من كامل عملية الذهاب إلى السوق. عملية تعريف الخطوط الأساسية ومن ثم كتابة التفاصيل لتلك الخطوات تسمى "نمط تصميم Top-Down". يسمح هذا النمط لنا بتقسيم المهام الكبيرة والضخمة إلى مهام أبسط وأصغر. سنستخدم نمط تصميم Top-Down ليساعدنا في التخطيط لبرنامجنا الذي سنكمل تطويره وإضافة الميزات إليه. يمكننا تلخيص "الوصف العام" للمهام التي يقوم بها السكربت الآن: بداية الصفحة بداية ترويسة الصفحة كتابة العنوان إغلاق الترويسة بداية جسم الصفحة كتابة العنوان كتابة بصمة الوقت (timestamp) إغلاق الجسم إغلاق الصفحة تمت برمجة كل الخطوات السابقة، لكننا نريد إضافة المزيد. لندرج بعض المهام الإضافية بعد المهمة السابعة: كتابة بصمة الوقت كتابة معلومات عن إصدار النظام كتابة الوقت الذي مضى منذ آخر تشغيل (uptime) كتابة مساحة القرص كتابة المساحة التخزينية لمجلدات المنزل (home) إغلاق الجسم إغلاق الصفحة سيكون من حسن حظنا وجود أوامر تستطيع تنفيذ المهام الإضافية، فسنستطيع استخدام "تعويض الأوامر" (command substitution) لوضعها في السكربت كالآتي: #!/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" ##### 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_ أما للمهام التي لا توجد أوامر تستطيع فعل ما نريد تحديدًا، فيمكننا إنشاؤها باستخدام دوال الصدفة (shell functions). وكما تعلمنا في أحد الدروس السابقة، يمكن اعتبار دوال الصدفة على أنها "برامج صغيرة ضمن البرامج" وتسمح لنا باتباع مبادئ نمط التصميم top-down. علينا تعديل السكربت كالآتي لإضافة دوال الصدفة: #!/bin/bash # sysinfo_page - A script to produce an 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() { } show_uptime() { } drive_space() { } 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_ هنالك نقطتان تجدر الإشارة إليهما: أولهما أنَّه يجب تعريف دوال الصدفة قبل محاولة استخدامها؛ وثانيهما هو أنَّ جسم الدالة (أي القسم الذي يقع بين قوس البداية "}" وقوس النهاية "{") يجب أن يحتوي على أمرٍ واحدٍ على الأقل. لن يعمل السكربت السابق وسيُظهِر رسالة خطأ وذلك لأنَّ جسم الدوال فارغ. أبسط طريقة لتصحيح هذه المشكلة هي وضع عبارة "return" في جسم كل دالة، وبعدها سيُنفَّذ السكربت بنجاح. إبقاء السكربتات قابلة للتشغيل من المفيد أثناء تطويرنا للتطبيق أن نُضيف جزءًا يسيرًا من الشيفرات ثم نُجرِّب السكربت ثم نضيف المزيد ثم نجرِّب السكربت وهكذا. وبهذه الطريقة سيسهل العثور على الأخطاء في الشيفرة ومن ثم تصحيحها. بعد إضافة الدوال إلى السكربت، أصبح بإمكانك الآن مراقبة التسلسل المنطقي لتنفيذ السكربت وذلك عبر آلية يُطلَق عليها اسم stubbing أي إضافة شيفرة وهمية. يمكنك تخيل هذه الآلية كما يلي: لنفترض أننا نريد إنشاء دالة اسمها "system_info" لكننا لم نفكر في تفاصيل الشيفرة بشكل كامل. فبدلًا من إيقاف عملية تطوير السكربت إلى أن ننتهي من الدالة system_info فيمكننا إضافة الأمر echo إليها كالآتي: system_info() { # Temporary function stub echo "function system_info" } سنتمكن باستخدام هذه الآلية من تنفيذ السكربت دون خطأ حتى لو لم نكمل برمجة الدالة system_info؛ ونستطيع لاحقًا وضع الشيفرة الحقيقية بدلًا من أمر echo السابق. سبب استخدامنا لأمر echo هو أننا نحتاج إلى مؤشر لكي نعرف أنَّ السكربت قد نفَّذ الدالة المعنية. لنُطبِّق هذه الآلية على جميع الدوال في السكربت: #!/bin/bash # sysinfo_page - A script to produce an 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() { # Temporary function stub echo "function system_info" } show_uptime() { # Temporary function stub echo "function show_uptime" } drive_space() { # Temporary function stub echo "function drive_space" } home_space() { # Temporary function stub echo "function 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_ سنكمل الآن العمل على كل دالة على حدة لكي تُخرِج معلوماتٍ مفيدةً. show_uptime ستُظهِر الدالة show_uptime ناتج الأمر uptime، الذي يعرض عدِّة معلومات مثيرة للاهتمام حول النظام، بما في ذلك المدة الزمنية منذ آخر إعادة تشغيل، وعدد المستخدمين، والحِمل (load) الحالي على النظام. $ uptime 9:15pm up 2 days, 2:32, 2 users, load average: 0.00, 0.00, 0.00 لعرض ناتج الأمر uptime في صفحة HTML، فسنحتاج إلى برمجة دالة الصدفة كالآتي (وذلك بعد حذف الشيفرة الوهمية التي كانت فيها): show_uptime() { echo "<h2>System uptime</h2>" echo "<pre>" uptime echo "</pre>" } كما ترى، تُخرِج الدالة السابقة نصًا يحتوي على خليطٍ من وسوم HTML مع مخرجات الأمر uptime؛ وستصبح هذه المخرجات جزءًا من here script عندما تُجرى عملية "تعويض الأوامر" في الجزء الرئيسي من السكربت. drive_space تستخدم الدالة drive_space الأمر df لتوفير ملخص للمساحة التخزينية المستهلكة من أنظمة الملفات الموصولة (mounted file systems). $ df Filesystem 1k-blocks Used Available Use% Mounted on /dev/hda2 509992 225772 279080 45% / /dev/hda1 23324 1796 21288 8% /boot /dev/hda3 15739176 1748176 13832360 12% /home /dev/hda5 3123888 3039584 52820 99% /usr ستبدو بنية دالة dive_space شبيهةً للغاية بدالة show_uptime: drive_space() { echo "<h2>Filesystem space</h2>" echo "<pre>" df echo "</pre>" } home_space ستُظهِر دالة home_space مقدار المساحة التخزينية التي يستهلكها كل مستخدم في مجلد المنزل الخاص به. سيُعرَض الناتج كقائمة مرتبة تنازليًا وفق مقدار المساحة التخزينية المستخدمة. home_space() { echo "<h2>Home directory space by user</h2>" echo "<pre>" echo "Bytes Directory" du -s /home/* | sort -nr echo "</pre>" } لاحظ أنَّه يجب تنفيذ السكربت عبر مستخدم يملك امتيازات إدارية لكي تعمل الدالة السابقة بشكلٍ صحيح، لأنَّ الأمر du يتطلب امتيازات الجذر (root) لكي يتفحص محتويات المجلد /home. system_info لسنا جاهزين بعد لإكمال دالة system_info. لكننا سنُحسِّن من الشيفرة الوهمية التي فيها لكي تُنتِج وسوم HTML: system_info() { echo "<h2>System release info</h2>" echo "<p>Function not yet implemented</p>" } ترجمة -وبتصرّف- للمقالَين Shell Functions و Some Real Work لصاحبهما William Shotts.
-
رأينا في الدرس السابق كيف كتبنا سكربتًا يولِّد صفحة 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_ هل لاحظت كيف أنَّ العبارة "My System Information" مكررة مرتين في السكربت السابق؟ لنُحسِّنها هكذا: #!/bin/bash # sysinfo_page - A script to produce an HTML file title="My System Information" cat <<- _EOF_ <html> <head> <title> $title </title> </head> <body> <h1>$title</h1> </body> </html> _EOF_ أضفنا سطرًا إلى بداية السكربت ووضعنا $title بدلًا من العبارة "My System Information". المتغيرات ما فعلناه في الأعلى سيمهد لنا الطريق لشرح فكرة أساسية جدًا موجودة في جميع لغات البرمجة تقريبًا: المتغيرات (variables). المتغيرات هي أماكن في الذاكرة يمكن أن تُستعمَل لتخزين المعلومات، ويُشار إليها باسمٍ مُميِّزٍ لها. أنشأنا في السكربت السابق متغيرًا اسمه title ووضعنا العبارة "My System Information" في الذاكرة، ثم استخدمنا $title لإخبار الصَدَفة أننا نريد إجراء "توسعة المعاملات" (parameter expansion) ونضع محتوى المتغير بدلًا من اسمه. عندما ترى الصَدَفة كلمةً تبدأ برمز $ فستحاول معرفة إذا كانت تُشير تلك الكلمة إلى متغير، ثم ستضع القيمة المُخزَّنة فيه -أي المتغير- مكان ورود تلك الكلمة. كيفية إنشاء متغير كل ما عليك فعله لإنشاء متغير هو وضع اسم المتغير في سطرٍ مستقل متبوعًا برمز المساواة (=) دون أيّة فراغات، ثم كتابة المعلومات التي تريد إسنادها بعد رمز المساواة. أسماء المتغيرات حسنًا، أنت من يُسمي المتغيرات، لكن هنالك بعض القواعد التي عليك مراعاتها: يجب أن تبدأ أسماء المتغيرات بحرف. يجب ألّا يحتوي اسم المتغير على فراغات. استخدم الشرطات السفلية (_) بدلًا منها. لا تستطيع استخدام علامات الترقيم. كيف أثر المتغير على السكربت الذي نكتبه سهَّلت إضافة المتغير title الأمر علينا من ناحيتين: الأولى هي تقليل مقدار الكتابة الذي نحتاجه، والثانية (وهي المهمة) هي أننا جعلنا صيانة السكربت أسهل. كلما ازدادت خبرتك في كتابة سكربتات الشِل (أو أي لغة برمجة أخرى)، فستتعلم أنَّك لا تنتهي من كتابة البرنامج في خطوة واحدة، فهنالك تعديلات وتحسينات من قبِل كاتب البرنامج أو من غيره؛ وهذا هو حجر الأساس لعملية تطوير البرمجيات مفتوحة المصدر. فلنقل مثلًا أنَّك تريد تغيير العبارة "My System Information" إلى "Linuxbox System Information"، فكنت تحتاج -في النسخة القديمة من السكربت- إلى تغيير تلك العبارة في مكانين منفصلين، أما في النسخة الجديدة التي فيها المتغير title فلا حاجة إلى تغيير تلك العبارة إلا في مكانٍ وحيد. قد تظن أنَّ هذا التغيير تافه أو ليس له فائدة حقيقية، لكن ذلك لأنَّ السكربت الذي نكتبه ما يزال بسيطًا وقصيرًا؛ لكن التنظيم أساسيٌ جدًا في السكربتات الكبيرة والمعقدة. متغيرات البيئة Environment Variables هنالك بعض المتغيرات المضبوطة في جلسة الصَدَفة من قِبل ملفات البدء التي رأيناها سابقًا. استعمل الأمر printenv لرؤية جميع المتغيرات الموجودة في البيئة عندك؛ يحتوي أحد تلك المتغيرات "اسم المضيف" (hostname) لنظامك؛ ونستطيع أن نُضيف ذاك المتغير إلى السكربت كالآتي: #!/bin/bash # sysinfo_page - A script to produce an HTML file title="System Information for" cat <<- _EOF_ <html> <head> <title> $title $HOSTNAME </title> </head> <body> <h1>$title $HOSTNAME</h1> </body> </html> _EOF_ أصبح السكربت الآن يضع اسم الحاسوب الذي نعمل عليه في صفحة HTML الناتجة. لاحظ أنَّ أسماء متغيرات البيئة (وفق التقاليد البرمجية) تُكتَب بأحرفٍ كبيرة. تعويض الأوامر سنحاول الآن تحسين السكربت بوضع ناتج من أحد الأوامر فيه. كانت آخر نسخة من السكربت قادرةً على إنشاء صفحة HTML تحتوي على أسطر نصية بسيطة تتضمن اسم المضيف لجهازنا المأخوذ من متغير البيئة المسمى HOSTNAME، سنُحدِّث السكربت الآن لإضافة بصمة وقت إلى الصفحة لكي تُشير إلى آخر تحديث لها، مع ذكر اسم المستخدم الذي قام بالتحديث. #!/bin/bash # sysinfo_page - A script to produce an HTML file title="System Information for" cat <<- _EOF_ <html> <head> <title> $title $HOSTNAME </title> </head> <body> <h1>$title $HOSTNAME</h1> <p>Updated on $(date +"%x %r %Z") by $USER</p> </body> </html> _EOF_ كما لاحظت، استعملنا متغير بيئة جديد هو USER لكي نحصل على اسم المستخدم؛ واستعملنا تعبيرًا غريب المظهر: $(date +"%x %r %Z") المحارف $() تقول "يجب وضع ناتج الأمر المُحاط بالأقواس هنا". وأردنا في السكربت السابق وضع ناتج الأمر date +"%x %r %Z" الذي يطبع التاريخ والوقت الحاليين. لدى الأمر date ميزاتٌ وخياراتُ تنسيقٍ كثيرة، نستطيع إلقاء نظرة عليها كالآتي: $ date --help | less لاحظ أنَّ هنالك صيغة قديمة بديلة عن ($(command هي استخدام علامة الاقتباس الخلفية "`"، هذه الصيغة القديمة متوافقة مع صَدَفة Bourne Shell الأصلية (sh)؛ لكنني لا أنوي استخدام الشكل القديم لأنني أشرح استخدام bash الحديثة وليس sh. تدعم صَدَفة bash جميع السكربتات المكتوبة لـ sh، ولهذا تكون الصيغتان الآتيتان متكافئتين: $(command) `command` إسناد ناتج أحد الأوامر إلى متغير يمكننا أيضًا إسناد ناتج أحد الأوامر إلى متغير: right_now=$(date +"%x %r %Z") نستطيع أيضًا وضع متغير داخل متغير آخر كما يلي: right_now=$(date +"%x %r %Z") time_stamp="Updated on $right_now by $USER" الثوابت كما يوحي اسم "المتغيرات": قيمة المتغير قابلة للتبديل، وهذا يعني أنَّه من المحتمل أثناء تنفيذ السكربت أن تُعدَّل قيمة المتغير نتيجةً لعمليةٍ قمتَ بها. في المُقابل، هنالك قيم يجب ألّا تتغير بعد ضبطها، وتسمى "الثوابت" (constants). سبب ذكري لهذا الموضوع هو أنَّ مفهوم الثوابت شائعٌ في البرمجة، وتدعمها أغلبية لغات البرمجة، لكن لكي أكون صريحًا معك، لم أشاهد استعمالًا عمليًا لها. فلو كان من المفترض أن تبقى قيم المتغير ثابتةً فسيسمى المتغير بأحرفٍ كبيرة لتذكير المبرمج أنَّ قيمة المتغير ثابتة. تُعتبَر متغيرات البيئة ثوابتَ لأنها نادرًا ما تتغير؛ وتُعطى الثوابت أسماءً ذات أحرفٍ كبيرة عادةً. سأستعمل العرف الآتي في هذا السكربت: الأحرف الكبيرة للثوابت والأحرف الصغيرة للمتغيرات. يبدو السكربت الذي نعمل عليه كالآتي حاليًا: #!/bin/bash # sysinfo_page - A script to produce an HTML file title="System Information for $HOSTNAME" RIGHT_NOW=$(date +"%x %r %Z") TIME_STAMP="Updated on $RIGHT_NOW by $USER" cat <<- _EOF_ <html> <head> <title> $title </title> </head> <body> <h1>$title</h1> <p>$TIME_STAMP</p> </body> </html> _EOF_ ترجمة -وبتصرّف- للمقالَين Variables و Command Substitution And Constants لصاحبهما William Shotts.
-
جمعنا في هذا المقال 10 أدوات تساعد مستخدمي لينكس في مهامّ متنوعة مثل مراقبة الشبكة، فحص النظام وأوامر أخرى للرفع من الإنتاجية. الأداة w يُظهر أمر w المستخدمين مسجلي الدخول إلى النظام والعمليات التي ينفذونها: w أضف الخيار h- للحصول على المساعدة: w -h nmon وهي أداة تعرض معلومات عن أداء النظام، يمكن تثبيتها على أوبنتو بالأمر: sudo apt-get install nmon ثم بعد التثبيت ننفذ الأمر: nmon يمكن للأداة تحصيل معلومات عن استخدام الشبكة، المعالج والذاكرة. اضغط على حرف c لمعلومات عن استخدام المعالج: وحرف n لمعلومات عن الشبكة: تعطي الأداة بالضغط على حرف d معلومات عن استخدام القرص الصلب: ncdu وهي أداة تُستعمَل لتحليل استخدام مساحة القرص الصلب. للتثبيت على أوبنتو نفذ الأمر: sudo apt-get install ncdu وللاستخدام: ncdu / تأخذ الأداة معطى يمثّل المجلد الذي نريد معرفة مساحته على القرص الصلب. في المثال أعلاه حدّدنا المجلّد الجذر. قد يأخذ تحليل القرص بعض الوقت حسب حجمه، ثم تظهر النتيجة: استخدم الأسهم للانتقال بين قائمة المجلدات، وزر Enter لاختيار مجلد، n لترتيبها حسب الاسم و s لترتيبها حسب الحجم (تُرتّب المجلدات مبدئيا حسب الحجم). slurm تُستخدَم هذه الأداة لمراقبة تدفق البيانات عبر الشبكة حيث تظهرها في شكل منحنيات بيانية. sudo apt-get install slurm استخدم الخيار i- لمراقبة واجهة شبكة محددة: slurm -i eth1 اضغط زر l و c للانتقال بين طريقتي العرض، r لتحديث الشاشة و q للخروج. findmnt يُُستخدَم أمر findmnt للعثور على نظم الملفات المركّبة Mounted. كما يُستخدَم لتركيب أو نزع تركيب أجهزة طرفية عند الحاجة. findmnt نستخدم خيار l- للعرض على هيئة لائحة. findmnt -l عرض نظم الملفات المركّبة في ملف fstab: findmnt -s يمكن أيضا البحث عن نظم الملفات حسب النوع: findmnt -t ext4 dstat هي أداة مجمَّعة لمراقبة استخدام الذاكرة، عمليات النظام وأداء القرص الصلب. تُعدّ dstat بديلا جيدا لكل من ifstat ،iostat و dmstat. للتثبيت: sudo apt-get install dstat نفذ أمر dstat للحصول على معلومات مفصّلة عن استخدام المعالج، القرص الصلب والشبكة. يتيح الخيار c- تركيز المعلومات المعروضة على المعالج: dstat -c كما يمكن استخدام الخيار l- مع c- لمعرفة متوسّط استخدام المعالج لدقيقة، 3 دقائق أو 15 دقيقة. يوجد خيار D-الذي يمكن من متابعة أداء تجزئة قرص صلب بدلا من كامل القرص (d- لعرض أداء القرص فقط دون بقية الإحصاءات): dstat -dD sda7 saidar أداة أخرى تعمل في سطر الأوامر لمراقبة إحصاءات النظام مثل استخدام القرص الصلب، الشبكة، الذاكرة، مساحة الإبدال Swap وغيرها. للتثبيت: sudo apt-get install saidar ثم ننفذ أمر saidar للحصول على إحصاءات عن مختلف موارد النظام. يمكن استخدام الخيار c- لتلوين المخرجات. saider -c ss تأتي ss (اختصار لـSocket statistics) بديلا لأداة netstat لتجميع معلومات من فضاء النواة Kernel، تتميّز بالسرعة مقارنة مع netstat. لعرض جميع الاتصالات (نستخدم less لتسهيل تصفح المخرجات، اضغط على زر المسافة للانتقال للشاشة الموالية): ss |less يمكن استخدام الخيار A- لحصر النتائج حسب النوع: ss -A tcp كما توجد إمكانية عرض أسماء ومعرّفات العمليات pid: ss -ltp ccze تتيح هذه الأداة عرض السجلات Logs بهيئة أكثر جاذبية، للتثبيت نفذ الأمر: sudo apt-get install ccze مثال على الاستخدام: tailf /var/log/syslog | ccze تمكّن الأداة أيضا من حفظ السجلات بنفس طريقة العرض في ملف HTML: tailf /var/log/syslog | ccze -h > /path_to_file.html يعرض الأمر عند استخدام الخيار l- وحدات الأداة (أنواع السجلات التي تتعامل معها). ranwhen.py وهو سكربت python يعمل في الطرفية لعرض نشاطات النظام بيانيا، ينشئ السكربت منحنيات بيانية ملوّنة لعرض تفاصيل الأنشطة. للتثبيت على أوبنتو أضف المستودع التالي: sudo apt-add-repository ppa:fkrull/deadsnakes ثم حدّث النظام: sudo apt-get update وثبّت الإصدار 3.2 من python: sudo apt-get install python3.2 نزّل السكربت: wget -c https://github.com/p-e-w/ranwhen/archive/master.zip ثم فك ضغطه: unzip master.zip && cd ranwhen-master بإمكاننا الآن تنفيذ الأداة: python3.2 ranwhen.py ترجمة - وبتصرّف - لمقال Ten 10 Useful Utilities For Linux Users لصاحبه Rajneesh Upadhyay.
-
ما إن تقضي وقتًا أطول مع لينكس حتى تألف العمل مع سطر الأوامر command line والمعروف أيضًا بالطرفيّة Terminal، وشيئًا فشيئًا ستجد أن الأوامر التي تستخدمها تتكرر ذاتها في كلّ يوم، وأن استعمالاتك لا تخرج عن دائرة صغيرة جدًا من الأوامر والتعليمات المتاحة بالفعل. وقد اجتهد مبرمجو معظم الأوامر والأدوات المستخدمة في الطرفية باختصار طرق استدعائها والعمل من خلالها (تخيّل كم توفّر من نقرات لوحة المفاتيح بكتابة "cd" بدلًا من "change-directory"، أو "ls" بدلًا من "list")، إلا أنّ هذا ليس كل شيء بالطبع، فمعظمنا يستخدم الأوامر مع مجموعة من خياراته المفضّلة. لحسن الحظّ فإن حلًا رائعًا لا يزال بانتظارك؛ حيث تسمح لك الطرفيّة بإنشاء اختصاراتك الخاصّة وحفظ وقتك من خلال ما يسمى بالأسماء المستعارة Aliases والدوال Functions. نناقش في هذا الدرس كيفيّة إنشاء هذه الاختصارات وحفظها بشكل دائم، مع بعض الأمثلة المفيدة التي ستيسر لك عملك بالتأكيد. الإعلان عن اسم مستعار Aliasإنشاء الأسماء المستعارة في الطرفيّة أمرٌ في غاية السهولة، لدرجة أنه يمكنك تجريبه على الفور، يتمّ ذلك باستخدام الأداة alias متبوعة بالاختصار الذي ترغب به، والتي تعرّف اسمًا مستعارًا فعّالا ضمن نافذة الطرفيّة المستخدمة فقط: alias alias_name="command_to_run"انتبه إلى أن أسلوب الكتابة السابق لا يتضمن مسافات فارغة قبل وبعد إشارة المساواة (=)، وهذا ليس أمرًا اختياريًا وإلا فإن الاختصار لن يعمل. لننشئ الآن اسمًا مستعارًا كتجربة، حيث سنأخذ واحدًا من أكثر الأوامر استخدامًا على لينكس وليكن الأمر lsمع الخيار -lha أو -lhA (يهمل الثاني عرض المجلد الحالي ومجلده الأب ضمن الخرج، خلاف الخيار الأوّل)، سنختار له اسمًا مستعارًا وليكن ll: alias ll="ls -lhA"يمكننا الآن كتابة ll للحصول على قائمة بمحتويات المجلد الحالي ضمن قائمة طويلة تتضمن المجلدات المخفيّة: ll -rw-r--r-- 1 root root 3.0K Mar 20 18:03 .bash_history -rw-r--r-- 1 root root 3.1K Apr 19 2012 .bashrc drwx------ 2 root root 4.0K Oct 24 14:45 .cache drwx------ 2 root root 4.0K Mar 20 18:00 .gnupg -rw-r--r-- 1 root root 0 Oct 24 17:03 .mysql_history -rw-r--r-- 1 root root 140 Apr 19 2012 .profile drwx------ 2 root root 4.0K Oct 24 14:21 .ssh -rw------- 1 root root 3.5K Mar 20 17:24 .viminfoوفي حال رغبت بالتوقف عن استخدام الاختصار يمكنك تطبيق الأمر التالي: unalias llوهكذا تُحذف قاعدة الاختصار التي أنشأتها للتوّ. بينما يمكنك الهروب من قاعدة ما بشكل مؤقت عن طريق كتابة رمز الهروب "\" قبل الأمر، فلو قمت بإنشاء قاعدة تحيل الأمر ls إلى الأمر ls -a، وترغب الآن بتطبيق الأمر ls دون استدعاء قاعدة الاختصار، فيمكنك كتابة: \lsيمكنك استعراض جميع القواعد المنشأة في أي وقت من خلال الأمر: aliasلكن كما ذكرنا سابقًا فإن الأسماء المستعارة التي يتم إنشاؤها عن طريق الأداة alias لن تعمل سوى في نافذة الطرفيّة المستخدمة، وهذا يعني أنك لو فتحت نافذة أخرى واستدعيت قاعدة ما فلن تحصل على المطلوب. ولجعل هذه التغييرات دائمة، نحن بحاجة إلى وضعها ضمن أحد الملفات التي تقرأها الطرفية في بداية كل تشغيل لها، الخيارات الشائعة لذلك هي استخدام الملف ~/.bashrc أو ~/.bash_profile، وكل ما علينا فعله هو تحرير أحد هذه الملفات وتعريف قواعد اختصارنا هناك: nano ~/.bashrcالآن أضف الأسماء المستعارة التي كنا قد كتبناها في الطرفيّة بذات الصياغة، يمكنك إضافتها في أسفل الملف، أو في أي مكان آخر، كما يمكنك استخدام التعليقات (بالعلامة #) لتوضيح ما قمتُ بإضافته: ######### # Aliases ######### alias ll="ls -lhA"قد تلاحظ وجود بعض الأسماء المستعارة بالفعل ضمن الملف السابق، حيث تأتي العديد من التوزيعات مع بعض الاختصارات التي تجعل من استخدام الطرفية أمرًا أكثر فاعليّة وسهولة. بعد حفظ الملف تصبح التعديلات المُدخلة جاهزة للاستخدام عند فتح نافذة طرفية جديدة، أما لو رغبت باستعمال قواعد الاختصار الجديدة ضمن نافذة الطرفية الحاليّة فيمكنك كتابة الأمر التالي لإعادة قراءة الملف .bashrc: source ~/.bashrc أمثلة أخرىلنمضي الآن في تعلّم بعض الأمثلة الأخرى عن إنشاء اختصارات تسهّل تعاملك مع الطرفيّة وتجعله أكثر فاعلية، تذكّر دومًا أنه يمكنك البحث في الإنترنت عن استخدامات أخرى نافعة للاختصارات، وإلقاء نظرة على تلك التي قد تكون مُعدّة بشكل افتراضي ضمن إعدادات توزيعتك. التنقل والاستعراضيمكن بإضافة بعض الخيارات على أوامر لينكس البسيطة والشائعة الحصول على نتائج أفضل وأكثر تخصيصًا، رأينا ذلك سابقًا مع الأمر ls، لكن هناك بالتأكيد ما هو أبعد من ذلك. فمثلًا يتيح لنا الاختصار التالي استخدام الخيار -CF مع الأمر ls بشكل افتراضي، والذي يفرّق أثناء العرض بين الملفات والمجلدات، بإضافة الرمز "/" في نهاية اسم كلّ مجلد: alias ls="ls -CF"كما يمكننا الالتفاف حول بعض الأخطاء الكتابيّة الشائعة بالنسبة لنا لجعلها تعمل أيضًا: alias sl="ls"يُنشئ الأمر التالي قاعدة اختصار تُمرّر مخرجات الأمر ls إلى الأداة less لاستعراض محتويات المجلدات الكبيرة بأسلوب مريح: alias lsl="ls -lhFA | less"واحدة من الأخطاء المطبعيّة الشائعة نسيان المسافة بين الأمر cd والنقطتين ..، هذه قاعدة تخرجنا من ذلك المأزق: alias cd..="cd .."أو يمكننا اختصار الأمر بالشكل التالي: alias ..="cd .."وهذه قاعدة أخرى لإنشاء اسم مستعار يسهّل عملية البحث عن الملفات: alias fhere="find . -name "إدارة النظاميحتاج مديرو الأنظمة العاملة بلينكس إلى استخدام الكثير من الأوامر مع تفضيلاتهم الخاصة باستمرار، وهذه فرصة جديدة لتعلّم وإنشاء بعض الاختصارات. تتيح القاعدة التالية إنشاء اسم مستعار يسهّل عرض أقسام واستخدامات القرص الصلب لديك ومعلومات أخرى عنه بطريقة مرتبة باستخدام الأمر df: alias df="df -Tha --total"ويمكن تطبيق نفس القاعدة مع كل من الأمر du والأمر free: alias du="du -ach | sort -h" alias free="free -mt"يستخدم الأمر ps لعرض العمليات والبرامج التي يقوم لينكس بتشغيلها مع معلومات تفصيلية عن كل برنامج، يمكن تسهيل قراءة الخرج من خلال الاختصار التالي: alias ps="ps auxf"كما يمكن إنشاء قاعدة تتيح لنا البحث ضمن جدول الخرج عن عملية محدّدة للاكتفاء بعرضها فقط مما يوفر لنا الوقت: alias psg="ps aux | grep -v grep | grep -i -e VSZ -e"فمثلًا للحصول على معلومات العملية bash فقط يمكن كتابة الأمر التالي: psg bash USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND 1001 5227 0.0 0.0 26320 3376 pts/0 Ss 16:29 0:00 bashأمثلة إضافيّةيعمل الأمر mkdir على إنشاء مجلّد جديد، لكن عند اختيار اسم لمجلد موجود بالفعل يعيد لنا رسالة خطأ، يمكن استخدام الخيار -p مع الأمر السابق لإهمال تلك الرسالة (ودون إنشاء المجلد)، كما يمكن عن طريق قاعدة الاختصار التالية جعل هذا الخيار افتراضيًا: alias mkdir="mkdir -p"أيضًا بإضافة الخيار v إلى الأمر السابق نحصل على المزيد من التنسيق، ففي حال وجود مجلد بذات الاسم يتم تجاهل الأمر وعدم عرض رسالة خطأ، أما لو كان الاسم غير مُستخدم فيعيد الأمر السابق خرجًا على الشاشة يؤكّد عملية إنشاء المجلد بنجاح: alias mkdir="mkdir -pv"في معظم الحالات التي نستخدم بها الأمر wget لتحميل ملف ما من الويب فإننا غالبا ما نمرّر له الخيار -c لدعم استكمال التنزيل في حال حدوث خطأ بالاتصال، لجعل ذلك افتراضيًا ننشئ القاعدة التالية: alias wget="wget -c"يعتبر الأمر history واحدًا من الأدوات الفعّالة، حيث يتيح لك البحث ضمن الأوامر التي سبق واستخدمتها، ويطبع لك النتائج المطابقة على الشاشة مرفقة بأرقامها التسلسليّة (حسب التنفيذ)، حيث يمكن استدعاء الأمر مجددًا من رقمه مسبوقًا بإشارة (!): alias histg="history | grep"كما هو معروف، تتوفر بعض أدوات الطرفية بنسختين، تكون الأولى أكثر بساطة، فيما تقدّم الأخرى ميزات وخدمات أكثر، ومن خلال إنشاء الاختصارات سيكون بإمكانك تشغيل النسخة المحسّنة بنفس أمر تشغيل النسخة الأولى. فالأمر top على سبيل المثال يملك نسخة محسنة وملونة بالاسم htop (إذا لم تكن لديك ركبّها من مدير الحزم في توزيعتك أولًا)، وبإنشاء قاعدة الاختصار التالي نعمّم استخدام النسخة المحسنة في كل التطبيقات الأخرى التي تستعملها: alias top="htop"تقدّم الأداة ncdu عرضًا تحليليًا لاستخدام مساحة القرص، الملفات والمجلدات في لينكس بأسلوب تفاعليّ وخيارات متنوّعة: alias du="ncdu"يستبدل الأمر السابق الأداة du بالأداة ncdu، كما يمكن استبدال الأداة df بـ pydf المحسّنة من خلال: alias df="pydf"هل ترغب في معرفة رقم الـ IP الخاص بجهازك؟ أنشئ القاعدة التالية: alias myip="curl http://ipecho.net/plain; echo"فكّر دومًا كيف يمكنك الاستفادة من القوّة الرهيبة للأسماء المستعارة، على سبيل المثال إذا كنتَ تدير موقعًا على الإنترنت بينما يلزمك باستمرار إعادة تحجيم الصور التي ترغب برفعها إلى الموقع لتناسب مقاسًا مخصصًا، يمكنك تركيب الأداة imagemagick من مدير الحزم في توزيعتك، وإنشاء قاعدة تسهل عليك العمل: alias webify="mogrify -resize 690\> *.png"حالما تطبّق الأمر الجديد webify سيتم إعادة تحجيم جميع الصور الموجودة ضمن المجلّد النشط عندما يكون عرضها أصغر من 690px. وبذات الطريقة يمكنك تسهيل رفعها إلى الخادوم الخاص بك: alias upload="sftp username@server.com:/path/to/upload/directoryالدوالكما رأينا فإن ميزة الأسماء المستعارة توفّر أسلوبًا رائعًا في اختصار تنفيذ الأوامر وتسهيل مراكبتها، إلا أنها في النهاية محدودة القدرة، إذا لا يمكننا على سبيل المثال تطبيق سلسلة طويلة من الأوامر معًا في اختصارٍ واحد. لحسن الحظ فهناك ما يساعدنا لتلبية هذه المتطلبات، تُقدّم الدوال functions أسلوبًا بسيطًا في اختصار تنفيذ قطعة من الأوامر دفعة واحدة، وهي أسلوب يقع بين ميزة الأسماء المستعارة وبين كتابة النصوص التنفيذيّة shell scripts، وتعمل بذات طريقة الأسماء المستعارة، كما يمكنها استقبال الدخل من المستخدم لمعالجته. سنتحدث في هذه الفقرة عن الاستخدامات الأساسية لميزة كتابة الدوال، مع بعض الأمثلة التوضيحيّة، متجنبين التفاصيل الواسعة لها، والتي يمكن من خلالها برمجة نصوص تنفيذيّة متقدّمة. لتعريف دالّة لدينا أسلوبين أساسيين، يستخدم الأوّل الأمر function ويأخذ الشكل العام كالتالي: function function_name { command1 command2 } بينا يشبه الأسلوب الآخر نمط الأقواس في لغة C: function_name () { command1 command2 }يمكن ضغط مساحة الأسلوب السابق ليُكتب في سطر واحد باستخدام الفاصلة المنقوطة بين الأوامر، انتبه إلى أن الفاصلة المنقوطة يجب أن تلتصق بالأمر الذي يسبقها: function_name () { command1; command2; }لنبدأ مع مثال بسيط، عادةً عندما نقوم بإنشاء مجلد جديد ضمن الطرفية فإن الخطوة التالية مباشرة هي الدخول إليه، سنكتب دالة لذلك؛ تنشئ مجلد جديد ثم تنتقل إليه: mcd () { mkdir -p $1 cd $1 }الآن يمكن استخدام الدالة mcd بدلًا من mkdir ثم cd: mcd test pwd /home/demouser/testالدالة التالية تعرض مثالًا متقدمًا على ما يمكن كتابته وتنفيذه عن طريق الطرفية، وهي تعمل على فكّ ضغط أنواع كثيرة من تنسيقات الملفات المضغوطة: function extract { if [ -z "$1" ]; then # display usage if no parameters given echo "Usage: extract <path/file_name>.<zip|rar|bz2|gz|tar|tbz2|tgz|Z|7z|xz|ex|tar.bz2|tar.gz|tar.xz>" else if [ -f $1 ] ; then # NAME=${1%.*} # mkdir $NAME && cd $NAME case $1 in *.tar.bz2) tar xvjf ../$1 ;; *.tar.gz) tar xvzf ../$1 ;; *.tar.xz) tar xvJf ../$1 ;; *.lzma) unlzma ../$1 ;; *.bz2) bunzip2 ../$1 ;; *.rar) unrar x -ad ../$1 ;; *.gz) gunzip ../$1 ;; *.tar) tar xvf ../$1 ;; *.tbz2) tar xvjf ../$1 ;; *.tgz) tar xvzf ../$1 ;; *.zip) unzip ../$1 ;; *.Z) uncompress ../$1 ;; *.7z) 7z x ../$1 ;; *.xz) unxz ../$1 ;; *.exe) cabextract ../$1 ;; *) echo "extract: '$1' - unknown archive method" ;; esac else echo "$1 - file does not exist" fi fi }تعمل الدالة على تحديد تنسيق الملف واختيار الأمر المناسب له للتنفيذ. خاتمةنأمل أن يكون هذا الدرس قد أعطاك بعض الإلهام لكتابة قواعد الاختصار والدوال التي تناسبك، مما يسهّل عليك أداء مهامك الروتينيّة وإضافة بعض المتعة على سطر الأوامر. تذكّر أن تبقى حذرًا من إعادة تعريف بعض الأوامر الأساسية بصوّرة قد تسبب مشاكل أو أخطاء قاتلة، كن حذرًا ولا تنشئ اختصارات تؤثّر على ملفات النظام. نقطة البداية الجيدة هي من سجل الأوامر التي كنتَ قد استخدمتها بالفعل في الفترة الماضية، لترى مالذي يتكرّر باستمرار، وتعمل على اختصار العمل من خلال إنشاء أسماء مستعارة جديدة: history | awk '{CMD[$2]++;count++;}END { for (a in CMD)print CMD[a] " " CMD[a]/count*100 "% " a;}' | grep -v "./" | column -c3 -s " " -t | sort -nr | nl | head -n10يعرض السطر السابق خرجًا بالأوامر الأكثر تكرارًا في استخدامك اليوميّ ونسبها المئوية، مما يعطيك الفكرة عن احتياجاتك الحاليّة. نسعد أيضًا بمشاركتكم لنا الاختصارات والدوال التي تستخدمونها عادةً لتبادل الخبرات. ترجمة -وبتصرّف- للمقال An Introduction to Useful Bash Aliases and Functions.