تعلم البرمجة المتعددة الموضوعات في السيناريوهات باستخدام GNU Parallel

إذا كنت متعبًا من تشغيل نصوص Bash الخاصة بك لفترة طويلة، فهذا البرنامج التعليمي مناسب لك. غالبًا ما يمكنك تشغيل نصوص Bash بشكل متوازٍ، مما يمكن أن يسرع النتيجة بشكل كبير. كيف؟ باستخدام أداة GNU Parallel، المعروفة أيضًا باسم Parallel، مع بعض الأمثلة المفيدة لـ GNU Parallel!

تقوم Parallel بتشغيل نصوص Bash بشكل متوازٍ باستخدام مفهوم يُسمى التعداد المتعدد. تسمح هذه الأداة لك بتشغيل مهام مختلفة لكل وحدة معالجة مركزية بدلاً من واحد فقط، مما يقلل من وقت تشغيل النص.

في هذا البرنامج التعليمي، ستتعلم كيفية تشغيل نصوص Bash بتعدد المواضيع مع العديد من الأمثلة الممتازة لـ GNU Parallel!

المتطلبات المسبقة

سيكون هذا البرنامج التعليمي مليئًا بالعروض التوضيحية العملية. إذا كنت تنوي متابعة الدروس، تأكد من أن لديك ما يلي:

  • A Linux computer. Any distribution will work. The tutorial uses Ubuntu 20.04 running on Windows Subsystem for Linux (WSL).
  • تسجيل الدخول بمستخدم لديه امتيازات sudo.

تثبيت GNU Parallel

لبدء تسريع نصوص Bash بتعدد المواضيع، يجب عليك أولاً تثبيت Parallel. لذا دعنا نبدأ بتنزيله وتثبيته.

1. افتح محطة Bash.

2. قم بتشغيل wget لتنزيل حزمة Parallel. يقوم الأمر أدناه بتنزيل أحدث إصدار (parallel-latest) إلى الدليل الحالي.

wget https://ftp.gnu.org/gnu/parallel/parallel-latest.tar.bz2

إذا كنت تفضل استخدام إصدار أقدم من GNU Parallel، يمكنك العثور على جميع الحزم في الموقع الرسمي للتنزيل.

3. الآن، قم بتنفيذ الأمر tar أدناه لفك ضغط الحزمة التي قمت بتنزيلها للتو.

في الأمر أدناه، يستخدم العلامة x لاستخراج الأرشيف، والعلامة j لتحديد أنها تستهدف أرشيفًا بامتداد .bz2، والعلامة f لقبول ملف كإدخال لأمر tar. sudo tar -xjf parallel-latest.tar.bz2

sudo tar -xjf parallel-latest.tar.bz2

يجب أن تحصل الآن على دليل يسمى parallel- مع شهر ويوم وسنة أحدث إصدار.

4. انتقل إلى مجلد الأرشيف الخاص بالحزمة باستخدام cd. في هذا البرنامج التعليمي، يُطلق على مجلد الأرشيف الخاص بالحزمة اسم parallel-20210422، كما هو موضح أدناه.

Navigating to the Parallel archive folder

5. بعد ذلك، قم ببناء وتثبيت البرنامج التنفيذي لـ GNU Parallel بتشغيل الأوامر التالية:

./configure
 make
 make install

الآن، تحقق من أن Parallel قد تم تثبيته بشكل صحيح من خلال التحقق من الإصدار الذي تم تثبيته.

parallel --version
Checking the GNU Parallel version

عند تشغيل Parallel للمرة الأولى، قد ترى أيضًا بضعة سطور مخيفة تعرض نصًا مثل perl: warning:. تشير هذه الرسائل التحذيرية إلى أن Parallel لا يمكنه اكتشاف إعدادات محليتك ولغتك الحالية. ولكن لا داعي للقلق بشأن هذه التحذيرات في الوقت الحالي. ستتعلم كيفية إصلاح هذه التحذيرات لاحقًا.

تكوين GNU Parallel

بمجرد تثبيت Parallel ، يمكنك استخدامه على الفور! ولكن أولاً ، من المهم تكوين بعض الإعدادات الطفيفة قبل البدء.

أثناء وجودك في نافذة الطرفية Bash ، قم بالموافقة على ترخيص البحث الأكاديمي لـ GNU Parallel بتحديد المعامل “citation” تليه “will cite”.

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

parallel --citation
will cite

قم بتغيير اللغة بضبط المتغيرات المحيطة بالبيئة عن طريق تشغيل الأوامر التالية. ضبط المتغيرات المحيطة باللغة واللغة بهذا الشكل ليس امرًا إلزاميًا. ولكن يتحقق GNU Parallel من وجودها في كل مرة يتم فيها تشغيله.

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

يفترض هذا البرنامج التعليمي أنك تتحدث الإنجليزية. اللغات الأخرى مدعومة أيضًا.

export LC_ALL=C man
export LANGUAGE=en_US
export LANG=en_US.UTF-8
Setting locale and language for GNU Parallel

تشغيل أوامر الشل على الطاير

لنبدأ الآن باستخدام GNU Parallel! للبدء، ستتعلم الصيغة الأساسية. بمجرد أن تصبح مرتاحًا مع الصيغة، ستقوم بعدها بتطبيق بعض الأمثلة العملية لـ GNU Parallel.

لنبدأ بمثال بسيط جدًا حيث سنقوم بطباعة الأرقام من 1 إلى 5.

1. في نافذة تيرمينال باش الخاصة بك، قم بتشغيل الأوامر التالية. مثير للإعجاب، أليس كذلك؟ باش يستخدم الأمر echo لإرسال الأرقام من 1 إلى 5 إلى تيرمينال. إذا كنت تضع كل هذه الأوامر في نص برمجي باش، فإن باش سينفذ كل واحدة منها تتابعيًا، في انتظار الانتهاء من الأمر السابق.

في هذا المثال، تقوم بتنفيذ خمسة أوامر لا تستغرق وقتًا طويلاً. ولكن تخيل لو كانت هذه الأوامر نصوص برمجية باش تقوم بشيء مفيد ولكنها تستغرق وقتًا طويلاً للتنفيذ؟

 echo 1
 echo 2
 echo 3
 echo 4
 echo 5

الآن، قم بتشغيل كل واحدة من تلك الأوامر في نفس الوقت باستخدام Parallel كما هو مبين أدناه. في هذا المثال، يقوم Parallel بتنفيذ الأمر echo المحدد بواسطة :::، ويمرر لهذا الأمر الوسيطات 1، 2، 3، 4، 5. الثلاثة نقاط تخبر Parallel أنك تقدم الإدخال عبر سطر الأوامر بدلاً من الأنبوب (المزيد فيما بعد).

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

# من سطر الأوامر
 parallel echo ::: 1 2 3 4 5

تتبع جميع أوامر Parallel الصيغة parallel [Options] <Command to multi-thread>.

3. لتوضيح استلام متوازي للإدخال من خلال أنبوب باش، قم بإنشاء ملف يسمى count_file.txt كما هو موضح أدناه. يُمثل كل رقم الArgument الذي ستمرره إلى أمر الـ echo.

 1
 2
 3
 4
 5

4. الآن، قم بتشغيل أمر cat لقراءة تلك الملف وتمرير الإخراج إلى Parallel، كما هو موضح أدناه. في هذا المثال، يُمثل {} كل Argument (1-5) الذي سيتم تمريره إلى Parallel.

# من خلال أنبوب cat count_file.txt | parallel echo {}
GNU Parallel Example #1

المقارنة بين باش و GNU Parallel

في الوقت الحالي، قد يبدو استخدام Parallel مجرد وسيلة معقدة لتشغيل أوامر باش. ولكن الفائدة الحقيقية لك هي توفير الوقت. تذكر، باش سيعمل على نواة واحدة فقط بينما سيعمل GNU Parallel على العديد منها في نفس الوقت.

1. لتوضيح الفرق بين أوامر باش التسلسلية مقابل Parallel، قم بإنشاء نص باش يسمى test.sh بالشيفرة التالية. قم بإنشاء هذا النص في نفس الدليل الذي أنشأت فيه count_file.txt في وقت سابق.

النص باش أدناه يقرأ ملف count_file.txt، ينام لمدة 1، 2، 3، 4، و 5 ثوان، يقوم بطباعة طول النوم على الطرفية، وينهي التنفيذ.

#!/bin/bash
 nums=$(cat count_file.txt) # قراءة count_file.txt
 for num in $nums           # بالنسبة لكل سطر في الملف، قم ببدء حلقة
 do
     sleep $num             # اقرأ السطر وانتظر لمدة الثواني المحددة
     echo $num              # اطبع السطر
 done

2. الآن، قم بتشغيل السكريبت باستخدام time لقياس مدى الوقت الذي يستغرقه السكريبت للاكتمال. سيستغرق 15 ثانية.

time ./test.sh

3. الآن، استخدم time مرة أخرى لأداء نفس المهمة ولكن باستخدام Parallel هذه المرة.

الأمر أدناه يؤدي نفس المهمة ولكن هذه المرة، بدلاً من الانتظار حتى اكتمال الحلقة الأولى قبل بدء الأخرى، ستعمل واحدة على كل نواة للمعالج وتبدأ العديد منها في نفس الوقت.

time cat count_file.txt | parallel "sleep {}; echo {}"
The prompt on the right side of the terminal confirms the time each command took to complete

تعرف على Dry Run!

حان الوقت الآن للدخول في بعض أمثلة GNU Parallel في العالم الحقيقي أكثر. ولكن قبل أن تفعل ذلك، يجب أن تعرف أولاً عن العلم –dryrun. يأتي هذا العلم بمتعة عندما تريد أن ترى ما سيحدث دون أن يفعل Parallel ذلك فعلاً.

يمكن أن تكون علامة --dryrun هي الفحص النهائي للتأكد قبل تشغيل أمر لا يتصرف كما توقعت. للأسف ، إذا قمت بإدخال أمر يمكن أن يؤذي النظام الخاص بك ، فالشيء الوحيد الذي سيساعدك فيه GNU Parallel هو تسريع الأمر الضار!

parallel --dryrun "rm rf {}"

مثال على GNU Parallel #1: تنزيل الملفات من الويب

لهذه المهمة ، ستقوم بتنزيل قائمة من الملفات من عناوين URL مختلفة على الويب. على سبيل المثال ، يمكن أن تمثل هذه العناوين عناوين صفحات الويب التي ترغب في حفظها ، أو الصور ، أو حتى قائمة الملفات من خادم FTP.

لهذا المثال ، ستقوم بتنزيل قائمة من حزم الأرشيف (وملفات SIG) من خادم FTP لـ GNU parallel.

1. قم بإنشاء ملف يسمى download_items.txt ، احصل على بعض روابط التنزيل من الموقع الرسمي للتنزيل وأضفها إلى الملف مفصولة بسطر جديد.

 https://ftp.gnu.org/gnu/parallel/parallel-20120122.tar.bz2
 https://ftp.gnu.org/gnu/parallel/parallel-20120122.tar.bz2.sig
 https://ftp.gnu.org/gnu/parallel/parallel-20120222.tar.bz2
 https://ftp.gnu.org/gnu/parallel/parallel-20120222.tar.bz2.sig

يمكنك توفير بعض الوقت من خلال استخدام مكتبة Beautiful Soup لـ Python لاستخراج جميع الروابط من صفحة التنزيل.

2. قراءة جميع عناوين URL من ملف download_items.txt وتمريرها إلى Parallel ، الذي سيقوم بتنفيذ أمر wget وتمرير كل عنوان URL.

cat download_items.txt | parallel wget {}

لا تنس أن {} في أمر موازي هو عنصر نائب لسلسلة الإدخال!

3. ربما تحتاج إلى التحكم في عدد الخيوط التي يستخدمها GNU Parallel في وقت واحد. إذا كان الأمر كذلك، أضف المعلمة --jobs أو -j إلى الأمر. تحدد معلمة --jobs عدد الخيوط التي يمكن أن تعمل بشكل متزامن إلى العدد الذي تحدده.

على سبيل المثال، لتحديد قدرة Parallel على تنزيل خمس عناوين URL في وقت واحد، سيكون شكل الأمر كما يلي:

#!/bin/bash
 cat download_items.txt | parallel --jobs 5 wget {}

يمكن تعديل معلمة --jobs في الأمر أعلاه لتنزيل أي عدد من الملفات، طالما أن الكمبيوتر الذي تعمل عليه لديه هذا العدد من وحدات المعالجة المركزية لمعالجتها.

4. لتوضيح تأثير معلمة --jobs، قم الآن بتعديل عدد المهام وتشغيل أمر time لقياس مدى استغراق كل تشغيل.

 time cat download_items.txt | parallel --jobs 5 wget {}
 time cat download_items.txt | parallel --jobs 10 wget {}

مثال GNU Parallel #2: فك ضغط حزم الأرشيف

الآن بعد أن قمت بتنزيل جميع هذه الملفات من الأمثلة السابقة، يجب عليك الآن فك الأرشيف.

أثناء وجودك في نفس الدليل الذي تحتوي فيه حزم الأرشيف، قم بتشغيل الأمر التالي باستخدام Parallel. لاحظ استخدام الرموز المستعارة (*). نظرًا لأن هذا الدليل يحتوي على حزم الأرشيف و ملفات SIG، يجب عليك إخبار Parallel بمعالجة ملفات .tar.bz2 فقط.

sudo parallel tar -xjf ::: *.tar.bz2

مكافأة! إذا كنت تستخدم GNU Parallel تفاعليًا (ليس في نص)، أضف علم --bar ليظهر لك Parallel شريط تقدم أثناء تشغيل المهمة.

Showing the output from the --bar flag

مثال GNU Parallel #3: إزالة الملفات

إذا قمت باتباع الأمثلتين الأوليين، يجب أن تكون لديك الآن العديد من المجلدات في دليل العمل تستهلك المساحة. لنقم الآن بإزالة جميع تلك الملفات بشكل متزامن!

لإزالة جميع المجلدات التي تبدأ بـ “parallel-” باستخدام Parallel، قم بسرد جميع المجلدات باستخدام ls -d وقم بتوجيه كل من مسارات تلك المجلدات إلى Parallel، مستدعيًا rm -rf على كل مجلد، كما هو موضح أدناه.

تذكر علامة --dryrun!

ls -d parallel-*/ | parallel "rm -rf {}"

الاستنتاج

الآن يمكنك أتمتة المهام باستخدام Bash وتوفير الكثير من الوقت لنفسك. ما تختار فعله بهذا الوقت يتوقف عليك. سواء كان حفظ الوقت يعني مغادرة العمل قليلاً في وقت مبكر أو قراءة مقال آخر في مدونة ATA، فهو وقت متاح لك في يومك.

الآن فكر في جميع السكربتات ذات الفترة الزمنية الطويلة في بيئتك. أيها يمكنك تسريعه باستخدام Parallel؟

Source:
https://adamtheautomator.com/how-to-speed-up-bash-scripts-with-multithreading-and-gnu-parallel/