מדריך שורת הפקודה - Pipes

חלק שישי בסדרת מדריך שורת הפקודה

Authors
  • Name
    YossiZ
    Published on
    Twitter

Pipes (צינורות)

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

לפני שנבין לעומק איך pipe עובד, עלינו להכיר כמה מושגים:

קבצים

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

כל מקור שממנו אפשר לקרוא דאטה או כל מיכל שיכול לקבל דאטה יכול לתמוך בממשק המוגדר של "קובץ" ואז זה נראה לעיניים של תוכנה כמו קובץ אמיתי. זה יכול לכלול בין השאר: חיבורי רשת, pipes (שנסביר אותם בהמשך), קבצים אמיתיים, מקלדת ועכבר (אפשר "לקרוא" מתוכם זרם של דאטה - שזה המקשים שהמשתמש לוחץ או תנועות העכבר, הם לא תומכים בכתיבה) ועוד

קלט ופלט

לכל פקודה שמערכת ההפעלה מריצה מחוברים "קבצים" של קלט ושל פלט. "קבצים" אלו נראות לפקודה כמו קובץ רגיל, אבל הם לא חייבים להיות קבצים אמיתיים וכנ"ל.
בברירת מחדל ה-shell פותח עבור כל תוכנה שלוש "קבצים".

  1. הקלט (stdin או standard input), זה קובץ או כל דבר אחר שמדמה את הממשק של קובץ. זה פתוח לקריאה בלבד והפקודה קוראת מתוכה את הקלט שלה.
    כאשר מריצים קלט מתוך טרמינל, הקלט מחובר לטרמינל, כלומר הטרמינל מדמה ממשק של קובץ כאשר פעולת קריאה על ה"קובץ" מביא את הקלט שהמתשמש רושם בטרמינל.

    ℹ מה קורה כאשר פקודה מבקשת לקרוא מתוך הטרמינל ואין עדיין קלט להזין לה? הפקודה נעצרת עד שיש למערכת ההפעלה קלט להזין לה או עד ל-timeout שניתן להגדיר (ליתר דיוק ה-thread שביקש את הקלט נעצר.

  2. הפלט הרגיל (stdout או standard output), זה קובץ או כל דבר אחר שמדמה ממשק של קובץ. זה פתוח לכתיבה בלבד והוא הפלט ברירת המחדל עבור פלט רגיל של תוכנה.
    בברירת מחדל זה הטרמינל שמדמה ממשק של קובץ כאשר "כתיבה" ל"קובץ" מופיע בטרמינל.

  3. פלט השגיאות (stderr או standard error), זה קובץ או כל דבר אחר שמדמה ממשק של קובץ. זה פתוח לכתיבה בלבד והוא הפלט ברירת המחדל עבור לוגי שגיאות של תוכנה.

    ℹ מדוע ישנם שני קבצים לפלט? כי לפעמים אנו רוצים לנתב את הפלט הרגיל למקום אחד ושגיאות למקום שונה

הנ"ל הם קבצי ברירת המחדל, כל תוכנה יכולה לפתוח עוד קבצים גם כן. אבל קבצים אלו תמיד קיימים כי ה-shell פותח אותם עבור תוכנה.

⚠ התיאור הנ"ל על קלט ופלט מדוייק לגבי מערכות הפעלה ממשפחת UNIX, (לינוקס, מאק, BSD וכו'). בווינדוס המצב קצת שונה, למרות זאת חלק גדול מהדברים עדיין תקפים והשימוש ב-pipes דומה

PIPE

על פי הנ"ל נתחיל להסביר מה זה pipe.

Pipe הינו "קובץ" ווירטואלי (כלומר שאין קובץ מקביל בדיסק הקשיח, ובד"כ אין לו שם או נתיב במערכת הקבצים), שמדמה צינור, כל מה "ששופכים" (= פעולת כתיבה) בצד אחד יוצא (= הוא זמין לפעולות קריאה) כמות שהוא בצד השני. צד אחד של ה-pipe תמיד פתוח רק לכתיבה והצד השני רק לקריאה.
דבר זה מאפשר שירשור פקודות בצורה שהפלט של פקודה א' נהיה הקלט של פקודה ב' וכן הלאה.

זהו מנגנון עוצמתי במיוחד שמאפשר בניית פקודות מורכבות מאוד.

דוגמה

ניקח כדוגמה את המקרה שהזכרנו בתחילת דברנו, חיפוש אם קובץ מסויים קיים בתיקייה.
לצורך זה נשתמש בשתי פקודות, הראשונה פולטת רשימה של קבצים שנמצאים בתיקייה, השניה מחפשת אם מחרוזת מסויימת קיימת בתוך הקלט של הפקודה.
לצורך הביצוע נייצר pipeline (= מחרוזת של פקודות שמחוברות על ידי pipe) שנראה כך:

Bash:

ls folder1 | grep filename

CMD:

dir folder1 | findstr filename

ה-pipeline שלנו מורכב משתי פקודות: ls או dir ו-grep או findstr
הראשונה פולטת רשימה של כל הקבצים שנמצאים בתיקייה שמזינים בפרמטר של הפקודה (folder1) והשניה מחפשת בקלט של עצמה מחרוזת (filename) שהגדרנו לו בפרמטר הראשון.
הפקודות מחוברות באמצעות תו | שמסמל pipe.

כאשר ה-shell מריץ את הפקודות קורה התהליך הבא:

  • יצירת pipe (קובץ ווירטואלי כנ"ל)
  • הרצת שתי הפקודות במקביל כאשר הפלט של הראשון מחובר לצד הכניסה/כתיבה של ה-pipe (במקום ברירת המחדל שהוא חלון הטרמינל), והקלט של השני מוגדר להיות צד הקריאה/יציאה של ה-pipe (במקום ברירת המחדל שזה חלון הטרמינל).

הפקודה השניה תדווח לנו אם המילה שביקשנו נמצאה בתוך רשימת הקבצים שהפקודה הראשונה הוציאה.

בפוסט הבא נדבר קצת בעז"ה על ניתוב קלט ופלט.