למדו סקריפטים בש ברבים עם 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, תוכל להשתמש בו מיד! אך קודם כל, חשוב להגדיר כמה הגדרות קטנות לפני התחלת השימוש.

עדיין נמצאים בטרמינל שלך, ואישור ל-GNU Parallel רשות למחקר אקדמאי, ובכך אתה מוביל ל-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. בטרמינל שלך ב-Bash, הרץ את הפקודות הבאות. מרגש, נכון? Bash משתמשת ב- פקודת ה-echo כדי לשלוח את המספרים 1-5 לטרמינל. אם הייתה מכניס כל אחת מהפקודות האלו לתסריט, Bash היה מבצעת כל אחת מהן בסדר, מחכה שהקודמת תסיים.

בדוגמה זו, אתה מפעיל חמישה פקודות שלא לוקחות זמן רב. אך, תדמיין אם הפקודות הללו היו תסריטי Bash שעושים משהו שימושי אך לוקחות זמן רב להרוץ?

 echo 1
 echo 2
 echo 3
 echo 4
 echo 5

עכשיו, הפעל כל אחת מהפקודות הללו בו זמנית באמצעות Parallel כמו שמוצג למטה. בדוגמה זו, Parallel מפעילה את פקודת ה-echo ומסמנת אותה באמצעות התו :::, מעבירה לפקודה את הארגומנטים, 1, 2, 3, 4, 5. שלושה נקודותיים מספרות ל-Parallel שאתה מספק קלט דרך שורת הפקודה ולא דרך הצינור (יותר מאוחר).

בדוגמה למטה, העברת פקודה יחידה ל-Parallel ללא אפשרויות. כאן, כמו בכל דוגמה של Parallel, Parallel התחילה תהליך חדש עבור כל פקודה באמצעות ליבת CPU שונה.

# משור הפקודה
 parallel echo ::: 1 2 3 4 5

כל הפקודות של Parallel עוקבות אחר התחביר parallel [אפשרויות] <פקודה לרב-תהליך>.

3. כדי להדגים קבלת קלט מקו אחר באמצעות צינור Bash, יש ליצור קובץ בשם count_file.txt כמו שמתואר למטה. כל מספר מייצג את הארגומנט שתעביר לפקודת echo.

 1
 2
 3
 4
 5

4. כעת, יש להפעיל את הפקודה cat כדי לקרוא את הקובץ הזה ולהעביר את הפלט ל-Parallel, כפי שמתואר למטה. בדוגמה זו, התג {} מייצג כל ארגומנט (1-5) שיעבר ל-Parallel.

# מתוך הצינור cat count_file.txt | parallel echo {}
GNU Parallel Example #1

השוואה בין Bash ו-Parallel

כרגע, שימוש ב-Parallel ייראה כמו דרך מורכבת להריץ פקודות Bash. אך היתרון האמיתי בשבילך הוא חיסכון בזמן. זכור, Bash ירוץ על ליבה אחת בלבד תוך ש-Parallel של GNU ירוץ על מספר ליבות בו זמנית.

1. כדי להדגים את ההבדל בין פקודות Bash סידוריות לבין Parallel, יש ליצור סקריפט Bash בשם test.sh עם הקוד הבא. יש ליצור את הסקריפט באותו ספרייה שבה נוצר הקובץ count_file.txt מקודם.

הסקריפט ב-Bash למטה קורא לקובץ 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 כדי לעשות זאת.

הפקודה למטה מבצעת את אותה המשימה, אך הפעם, במקום לחכות שהלולאה הראשונה תסיים לפני שתתחיל הבאה, היא תרוץ על כל ליבת מעבד CPU אחת, ותתחיל כמה שניתן יותר באותו הזמן.

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 של פייתון לחילוץ כל הקישורים מ־דף ההורדה.

2. קרא את כל הכתובות URL מתוך קובץ download_items.txt והעבר אותן ל־Parallel, שיקרא את wget ויעביר כל קישור.

cat download_items.txt | parallel wget {}

אל תשכח ש־{} בפקודת parallel הוא מקום מוחלף למחרוזת הקלט!

3. אולי יש צורך לשלוט על מספר החוטים ש-GNU Parallel משתמשת בו בו זמנית. אם כן, הוסף את הפרמטר --jobs או -j לפקודה. פרמטר --jobs מגביל את מספר החוטים שיכולים לרוץ בו זמנית למספר שתציין.

לדוגמה, כדי להגביל את Parallel להוריד חמישה כתובות URL בו זמנית, הפקודה תיראה כך:

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

הפרמטר --jobs בפקודה הנ\"ל יכול להתאים להוריד כל מספר של קבצים, כל עוד המחשב שאתה מפעיל עליו יש לו מספר CPUs שכזה לעיבודם.

4. כדי להדגיש את ההשפעה של פרמטר --jobs, כעת כוון את מספר העבודות והפעל את פקודת time למדידת כמה זמן לוקח כל הפעלה.

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

דוגמה נוספת של GNU Parallel: פתיחת קבצי ארכיונים

כעת שיש לך את כל קבצי הארכיון האלו שהורדו מדוגמה הקודמת, עכשיו עליך לפתוח אותם.

בעודך באותו ספרייה כמו חבילות הארכיון, הפעל את פקודת Parallel הבאה. שים לב לשימוש בתו כוכב (*). מכיוון שהספרייה הזו מכילה גם חבילות ארכיון וגם קבצי ה-SIG, עליך לספק ל-Parallel לעבד רק קבצים בפורמט .tar.bz2.

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

בונוס! אם אתה משתמש ב-GNU Parallel באופן אינטראקטיבי (לא בתוך סקריפט), הוסף את הדגל --bar כדי לראות סרגל התקדמות בזמן הרצת המשימה.

Showing the output from the --bar flag

דוגמה נוספת של GNU Parallel: מחיקת קבצים

אם עקבת אחרי הדוגמאות הראשונות, עליך כעת להיות עם הרבה תיקיות בספריית העבודה שלך שמקבלות מקום. אז בוא נסיר את כל הקבצים הללו באופן פרולי!

להסיר את כל התיקיות שמתחילות עם 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/