מבוא לצנורות והפניית פלט וקלט

יובל
היסטוריית גירסאות
גירסה 1.0 05-04-2007 כתריאל טראום
הומר לפורמאט וויקי

זכויות יוצרים ורשיון

כל הזכויות שמורות © 2007, יובל, הרשות ניתנת להעתיק, לשנות ולהפיץ מדריך זה תחת התנאים של רשיון ה-GFDL

Linux הוא סימן מסחרי רשום של Linus Torvalds.

הסרת אחריות

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

הקדמה

מה הוא צינור (pipe)? צינורות אלה לא קשורים לתיקון סתימות ושרברבות, אלא לצינורות במחשבים - צינורות המקשרים בין הליך אחד לאחר

קלט ופלט - לכל תוכנה יש אמצעי קלט ופלט, אחרת למה התוכנות האלה גוזלות לנו זמן עיבוד?! אמצעי הקלט הסטנדרטי של תוכנה נקרא, stdin (Standart Input), והקלט ממנו בא בדרך כלל מהמקלדת, זה קורה כאשר המחשב מחכה שתקלידו משהו ותלחצו return) Enter).

כמו כן יש אמצעי פלט סטרנדרטי לתוכנה הנקרא stdout (Standrt Output),ויש אמצעי שגיאה סטנדרטי strerr (Standart Error), שהפלט מהם מגיע בדרך כלל אל המסך, ואתם רואים אותו בצורה של האותיות על הקונסול שלכם.

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

צנורות

לאורך כל המדריך נעבוד עם ה console. כדאי שהוא יהיה פתוח (אם אתה ב KDE, הרץ את konsole, ואם אתה ב gnome הרץ את gnome-terminal).

דוגמא

נניח ואתה רוצה לדעתם אם תהליך בשם “apache” רץ עכשיו. כדי לדעת את התשובה, אפשר לבקש מהמחשב את “כל התהליכים במערכת בשמם יש את המילה apache”.

איך נעשה זאת? פשוט כך:

$ ps -ax|grep apache

עוד רגע נכנס לעומק הדוגמא.

הסבר

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

נניח ורציתם לראות, אם שרת האפאצי שלכם (או כל תוכנה אחרת) פעילה כרגע?
נחלק את שאלה זו לשתי שאלות: (1) איך לראות את כל התהליכים שרצים כרגע?, (2) איך לסנן כך שרק apache יוצג. התשובה לשאלה הראשונה היא הכלי “ps”, שאם תפעיל כך:

$ ps -ax

אתה תקבל פלט של כל התהליכים הרצים במחשב כרגע.

אבל הפלט מכיל הרבה מאוד תהליכים - ויכול להיות, שאם apache היה כתוב שם, פיספת אותו, כי הפלט רץ מהר מידי,חלון הקונסול קטן מידי, ולא הספקת לראות.

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

כדי לבדוק זאת רשמו:

$ grep apache (Enter)

הפקדודה האחרונה הפעילה את grep ואמרה לסנן את כל השורות בלי המילה apache. המסך של ה console יעצור ויחכה לקלט. ה אתם תשימו לב שהמחשב מחכה. למה הוא מחכה ? הוא מחכה לקלט. תחילו לרשום שורות קלט. שימו לב שרק אם תרשמו שורה עם המילה hello, אז grep תוציא אותה למסך. שימו לב - אם לא נותנים עוד ארגומנט קובץ ל grep (ועוד הרבה תוכניות שפועלות כך), היא מחכה לקבל קלט מה stdin שלה. והמחשב מחכה שתזינו לו אותו. לחצו על control + D (או control +C אם זה לא עובד) זה יחזיר אותכם למעטפת (shell).

אבל, ps ו grep הן שתי תוכניות שונות, איך תוכלו לחבר את grep ל ps כך ש grep תסנן את הפלט שלה? - כאן נכנסים צנורות לעניין - על אף שהמתכנת של grep בכלל לא חשב (כנראה) על ps כשהוא עשה את grep, תוכלו לחבר את הפלט של ps עם הקלט של grep - חיבור זה נקרא צינור.

צינור הוא אמצעי, שניתן לנו על ידי הליבה של המערכת, שנועד לתקשורת בין תהלכים. במדריכון זה, נשתמש בו, כדי להפנות את הפלט מתוכנה אחת שאנו מפעילים, (ה stdout שלה), לתוך קלט של תוכנה אחרת (ה stdin שלה). זה לא מסובך כמו שזה נשמע… ותוך זמן קצר אתם תלמדו להיות שרברבים מיומנים!

כעת אם נקיש את הפקודה הבאה:

$ ps -ax | grep apache 

התוצאה - רק השורות מהפלט של ps המכילות את המילה apache יוצגו.

מה קרה כאן? בעזרת התו | אמרנו למעטפת ליצור צינור, שיעביר את הפלט של ps להיות הקלט של grep, ו grep עשתה את עבודתה וסננה מהקלט שלה, ופלטה רק את השורות המכילות את הביטוי apache. הסימן | הוא האומר למעטפת ליצור צינור בין 2 תוכניות.
זה עובד גם בצורות אחרות, כמו גם עם התוכניות head(שמציגה את ה 10 שורות הראשונות שבקלט שלה) ו tail (שמציגה את ה 10 שורות האחרונות שבקלט שלה), less (שמאפשרת ניווט נוח במה שהוכנס לה כקלט), וכל תוכנית שעובדת עם הקלט שלה, נסו לדוגמא:

$ ps -ax | less

ותיהיה לכם את הרשימת כל התוכנות מוצגת על המסך ותוכלו לחפש כרצונכם.

דוגמא עם head ו tail:

$ps -ax| tail -20 |head 

מה יודפס כאן?
כאן, הפלט של ps, יועבר ע”י צינור לקלט של tail, והפלט של tail , יועבק ע” צינור להיות הקלט של head.
tail פלטה את ה 20 שורות האחרונות של הקלט שלה - מרשימת התהליכים. ו head הציגה את ה 10 שורות, הראשונות, מתוך ה 20 האחרונות.

דוגמע נוספת: עם sort - תוכנה הפולטת את השורות הקלט שלה בסדר אלפא-ביתי, ו cat תוכנה שפולטת תוכנו של קובץ ל stdout שלה. ניתן למיין את קובץ הססמאות לדוגמא, כך:

$ cat /etc/passwd |sort

הפלט שתראו על המסך, יהיה בסדר אלפאבתי.

דוגמא יותר שימושית: נניח ואתה עובד על מערכת מובססת RPM (כמו RedHat או Mandrake), ואתה רוצה לגלות גרסא מסיומת של תוכנה שבא בצורת rpm, לצורך העניין נניח שתוכנה זו היא KDE.
מה תעשה? - במערכות אלו ישנה הפקודה rpm שמנהלת בעצם פעולות עם חבילות rpm. הפקודה “rpm -qa” תבצע שאליתה ותציג את כל החבילות המותקנות למסך. אבל אתה רק רוצה לראות את החבילות של KDE, מה תעשה?
לכן, אתם תעשו כך:

$ rpm -qa |grep kdebase

מה קרה - כל הפלט של “rpm -qa” הועבר עם צינור לקלט של “grep kdebase” ופקודה זו תסננן את הפלט שלה ותציג רק את השורות שיש בהן kdebase, שזו חבלית הבסיס של kde, ואז אתה תראה משהו בסגנון:

kdebase-3.0.0-12

ותדע שהגרסא היא 3.0.0

עוד על תמרון פלט וקלט - הפניות

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

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

$ ls ~/* > database_file

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

$ ls ~/* >> database_file

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

# find / -perm +6000 -ls > ~/suid.master

בדוגמא זו, אנו מוצאים את כל קבצי ה suid במערכת ושומרים את המיקום שלהם בקובץ suid.master תחת תיקיית הבית.

מה אם תרצו שרק הפלט מ stderr יוכנס לקובץ, כך שתוכלו לעקוב אחרי שגיאות של תוכנה מסוימת?
זה מאוד דומה עם הבדל קטן, במקום שנרשום > נרשום2> ,אז בדומה לדוגמא הקודמת, במקום שה stdout יופנה לקובץ, ה stderr יופנה לקובץ. דוגמא:

$ ls /root 2> error_file

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

ומה אם מרצה שהפלט מ stderr, ומ stdout ילכו לאותו מקום? כך שיהיו בקובץ אחד, ברצף. לדוגמא:

$ find / >db_file 2>&1

כאן, הסימן2>&1 , אמר למעטפת להעביר את מה שמגיע ל stderr (שהוא 2), לאן ש stdout הולך (שהוא 1),ואז יהיה רצץ אחיד של פלט ל stdout, וגם מה שמגיע ל stderr ילך לשם.

קבלת קלט מקובץ - אם נאמר, יש לנו קובץ, ובו נתונים מסוימים, שאותם נרצה להכניס כקלט לתוכנה, יש שני דרכים לבצע זאת: עם צינורות - לדוגמא, קבלת פירוט על קבצים הרשומים בקובץ מסוים, בעזרת ls:

$ cat db_file|ls -l

כאן, cat מוציאה תוכן הקובץ ל stdout שלה, שמועבר ל stdin, של ls, שהיא בתורה, מביאה פרטים אודות הקובץ.

דרך נוספת לעשות זאת היא כך:

$ ls < db_file -l

כאן השתמשנו בסימן < כדי להגיד למעטפת שתוציא את תוכן הקובץ db_file, ל stdin של ls.

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

$ find / 2>/dev/null

כאן הרצנו חיפוש על כל הקבצים במערכת, מכיוון שעשינו זאת בתור משתמש רגיל, יש מקומות שלהם אין לנו גישה, ואז find תוציא הודעת שגיאה. אם איננו רוצים לראות את הודעת השגיאה הזאת על המסך, אלא רק את הקבצים שנמצאו, נפנה את stderr של find ל /dev/null, וכך נפטר ממנו.

לסיום - החלק הקצת טכני (אי אפשר בלעדיו :-)

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

המספרים 2,1 שראיתם בשימוש במהחל החלק על הפניות, דוגמת “2>&1”או ב “2>” הם בעצם מספרים שמייצגים מתארי קבצים (file descriptor), הם משמשים ביונקיס כחלק הממשק גישה לקבצים. המספר המייצג את stdin הוא 0, stdout מיוצג ע”י 1, ו stderr מיוצג ע”י 2 (באופן דומה, מספרים אלו מייצגים את מתארי הקבצים של אותם רצפי פלט/קלט ב C), אם לא שמתם לב עד עכשיו, כל דבר ביוניקס הוא קובץ :)

המעטפת נותנת לך ממשק לצינור, כדי ל”קשור” את הפלט (stdout) של תהליך אחד לקלט(stdin) של תהליך שני, זהו אמצעי חזק שמאפשר לך לבצע משימות אשר כלי אחד ביוניקס אינו מסוגל לבצע לבד.
זו בעצם חלק מהפילוסופיה של יוניקס - לכל כלי יש מטרה אחת, ומחברים אותם, כדי לפתור בעיות מורכבות יותר.
צינורות מהווים חלק ממנגנון של תקשרות בין תהליכים (IPC= Inter-Proccess Communication) שכולל בתוכו עוד מספר דרכים לתקשורת בין תהליכים שלא יפורטו כאן.

קונבנציות

אם אתה לא מבין מה זה הסימן $ כל פעם שאני רושם פקודה, הכוונה היא למעטפת (shell) , הסימן $ אומר שיש להקליט את הפקודה במעטפת, והסימן #, אומר מעטפת עם הרשאות root.

מידע נוסף

ברשת ניתן למצוא מדריכים וכתבים בנושא, לעוד מידע, פשוט חפש IPC ב google האהוד על כולנו.

מדריכים/מבוא_לצנורות_והפניית_פלט_וקלט.txt · שונה לאחרונה ב: 2008/06/19 18:34 (עריכה חיצונית)
chimeric.de = chi`s home Creative Commons License Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0