לוגים, הקדמה 2 exec
רמת קושי: #advanced
פקודת
רגע מה???, למה שמישהו ירצה לעזאזל להריץ פקודת באש על פקודת exec במקום להריץ ישירות על באש את הפקודה הרצויה?
פקודת
מה שבעצם קורה הוא שexec לא פותח תהליך חדש אלא מתלבש על התהליך הקיים ויוצא כשהוא מסיים (בקשר לזה עוד בהערה).
פקודת
הרצת
הרצת
כפי שניתן לראות לאחר שהרצנו
נ.ב. שימוש בexec עם פרמטר יוצר בעצם את הרצף הבא
מאחר ו
#exec
#redirection
@bash_tips
רמת קושי: #advanced
פקודת
exec
כמו שהיא נשמעת היא פקודת באש שמריצה פקודות באש מתוך באשbash >> command
bash >> exec >> command
רגע מה???, למה שמישהו ירצה לעזאזל להריץ פקודת באש על פקודת exec במקום להריץ ישירות על באש את הפקודה הרצויה?
פקודת
exec
יודעת לנהל את הפלט של הסקריפט ממש כמו שנריץ בטרמינל עצמו, במילים אחרות אפשר לומר שזה כמו הרצה של באש מתוך הסקריפט.מה שבעצם קורה הוא שexec לא פותח תהליך חדש אלא מתלבש על התהליך הקיים ויוצא כשהוא מסיים (בקשר לזה עוד בהערה).
פקודת
exec
עובדת בשני צורות אחת עם פרמטר והשניה בלי פרמטר,הרצת
exec
עם פרמטר (פקודה) תגרום לכך שרק הפקודה שהועברה כפרמטר תרוץ תחת exec
.$ exec ls > myfile.log
הרצת
exec
בלי פרמטר תגרום לכך שכל מה שיכתב לאחר מכן ירוץ תחת exec
, אם אנו חוזרים לאנלוגיה ממקודם אז זה כמו לפתוח באש חדש מתוך באש, כל מה שנריץ ירוץ בעצם בתוך המעטפת החדשה שיצרנו.$ ls
1.txt 2.txt 3.txt
$ exec > myfile.log
$ ls
$ cat myfile.log
$ 1.txt 2.txt 3.txt
כפי שניתן לראות לאחר שהרצנו
exec
פקודת ls
כבר לא מחזירה פלט לטרמינל אלא ישירות לקובץ.נ.ב. שימוש בexec עם פרמטר יוצר בעצם את הרצף הבא
bash >> exec >> ls >> exit
מאחר ו
exec
משתלט בעצם על התהליך שכבר רץ הלא הוא באש ולא יוצר תהליך חדש משל עצמו אז כשהוא מסיים לרוץ הוא מחזיר קוד יציאה וסוגר את התהליך עליו הוא השתלט, זוהי בעצם הסיבה למה טרמינלים עפים וחיבורי ssh נסגרים.#exec
#redirection
@bash_tips
לוגים, על exec וניתוב פלט
רמת קושי: #advanced
באש היא שפת סקריפט שתפקידה בגדול זה להפוך תהליכים לאוטומטים, אבל לא משנה כמה נתאמץ להגן על הקוד שלנו עדין נרצה שיהיה לנו לוג שיציג את מה שעבר על הסקריפט ואם אפשר אז להכניס ללוג כמה שיותר פלט רלוונטי ופחות פלט שהוא קשקוש מוחלט.
המשימה: יצירת לוג אינפורמטיבי
פתרון 1
הפתרון הראשון שמיד יעלה לנו לראש הוא ליצור איזה פונקציה שעושה echo לכל מה שנעביר לה לתוך קובץ, משהו שנראה כך
אוקי נראה אחלה, איפה הבעיה?
הבעיה היא שכרגע המצב הוא שרק מתי שנקרא לפונקציית הלוגר היא תכתוב נתונים לקובץ הלוג, מה שאומר שכמעט לכל פקודה שאריץ אצטרך לאסוף את הפלט שלה.
וזה עוד לא החלק הבאמת בעייתי, מה קורה אם לדוגמה פקודה מסויימת נכשלת ומחזירה שגיאה? בגלל שלא קראנו לפונקציית הלוגר הפלט לא יכתב ללוג וזה ממש חבל כי זה בדיוק הפלט שהיינו רוצים שיופיע.
אם כך נשנה מעט את המשימה שלנו
המשימה: יצירת לוג אינפורמטיבי אוטומטי
פתרון 2
אז מה שאנו מחפשים בעצם היא יכולת גלובלית יותר לתפוס את כל הפלט של הסקריפט, איך נעשה את זה? הדרך הפשוטה היא פשוט לאסוף את הפלט בזמן שאנו קוראים לסקריפט
מצד שני אם היינו יכולים לקרוא לסקריפט בצורה כמו זאת מהסקריפט עצמו זה היה יכול להיות נהדר.
פתרון 3
שימוש פקודת exec אותה ראינו בפוסט הקודם, אם נחשוב על הבעיה הקודמת שהיתה לנו בפתרון 2 נוכל לראות איך שימוש בכלי "חיצוני" כחלק מהסקריפט יכול לעזור לנו.
מה שלא ממש צויין בטיפ הקודם הוא שפקודת exec תוכל גם לנתב את הפלט עבורנו, וכל עוד לא נעביר לה פרמטר exec ינתב את הפלט של הסקריפט כולו.
אתגר בקצה
אחלה אם כן יש לנו פתרון נהדר, היכן עוד נוכל לשפר אותו?
כמו שאנו מכירים כל לוג אמור להכיל עוד פרטים מעבר לפלט, שעה ותאריך לדוגמה, או כל דבר אחר שנרצה שהלוג יכיל, מן הסתם נרצה שלפני שהפלט יכתב לקובץ הלוג שהוא יעבור תהליך כלשהו כדי שהלוג יהיה קריא ומועיל וכו'
איך נוכל לגרום לפלט להיות בפורמט של לוג?
מוזמנים לשלוח רעיונות
#process_substitution
#logging
#exec
#tee
@bash_tips
רמת קושי: #advanced
באש היא שפת סקריפט שתפקידה בגדול זה להפוך תהליכים לאוטומטים, אבל לא משנה כמה נתאמץ להגן על הקוד שלנו עדין נרצה שיהיה לנו לוג שיציג את מה שעבר על הסקריפט ואם אפשר אז להכניס ללוג כמה שיותר פלט רלוונטי ופחות פלט שהוא קשקוש מוחלט.
המשימה: יצירת לוג אינפורמטיבי
פתרון 1
הפתרון הראשון שמיד יעלה לנו לראש הוא ליצור איזה פונקציה שעושה echo לכל מה שנעביר לה לתוך קובץ, משהו שנראה כך
logger() {
echo "${@}" | tee myscript.log
}
מה שיש לנו פה זאת פונקצייה פשוטה בשם logger שמדפיסה כל מה שהיא מקבלת לקובץ myscript.logאוקי נראה אחלה, איפה הבעיה?
הבעיה היא שכרגע המצב הוא שרק מתי שנקרא לפונקציית הלוגר היא תכתוב נתונים לקובץ הלוג, מה שאומר שכמעט לכל פקודה שאריץ אצטרך לאסוף את הפלט שלה.
וזה עוד לא החלק הבאמת בעייתי, מה קורה אם לדוגמה פקודה מסויימת נכשלת ומחזירה שגיאה? בגלל שלא קראנו לפונקציית הלוגר הפלט לא יכתב ללוג וזה ממש חבל כי זה בדיוק הפלט שהיינו רוצים שיופיע.
אם כך נשנה מעט את המשימה שלנו
המשימה: יצירת לוג אינפורמטיבי אוטומטי
פתרון 2
אז מה שאנו מחפשים בעצם היא יכולת גלובלית יותר לתפוס את כל הפלט של הסקריפט, איך נעשה את זה? הדרך הפשוטה היא פשוט לאסוף את הפלט בזמן שאנו קוראים לסקריפט
$ myscript.sh 2>&1 | tee myscript.log
זה כמובן יעבוד אבל פחות נרצה לכתוב סקריפט שתלוי בצורת ההרצה שלו, מה גם שנקבל ממש את כל הפלט שהסקריפט מוציא ולא נוכל לסנן רק את הפלט הרלוונטי.מצד שני אם היינו יכולים לקרוא לסקריפט בצורה כמו זאת מהסקריפט עצמו זה היה יכול להיות נהדר.
פתרון 3
שימוש פקודת exec אותה ראינו בפוסט הקודם, אם נחשוב על הבעיה הקודמת שהיתה לנו בפתרון 2 נוכל לראות איך שימוש בכלי "חיצוני" כחלק מהסקריפט יכול לעזור לנו.
מה שלא ממש צויין בטיפ הקודם הוא שפקודת exec תוכל גם לנתב את הפלט עבורנו, וכל עוד לא נעביר לה פרמטר exec ינתב את הפלט של הסקריפט כולו.
exec &> >(tee myscript.log)
מה שיש לנו כאן זוהי בעצם הכרזה בסקריפט שכל פלט שמגיע מהפקודות לאחר הכרזה זו (stderr & stdout) יופנה אל פקודת tee על ידי שימוש ב process_substitution שהיא בתורה תכתוב את התוכן גם לקובץ וגם למסך, וכמו בעבר בכדי להימנע מכלים שיש להם מידע שאינו רלוונטי ללוגים תמיד נוכל להשתיק פלט על ידי הפניה שלו אל /dev/null
אתגר בקצה
אחלה אם כן יש לנו פתרון נהדר, היכן עוד נוכל לשפר אותו?
כמו שאנו מכירים כל לוג אמור להכיל עוד פרטים מעבר לפלט, שעה ותאריך לדוגמה, או כל דבר אחר שנרצה שהלוג יכיל, מן הסתם נרצה שלפני שהפלט יכתב לקובץ הלוג שהוא יעבור תהליך כלשהו כדי שהלוג יהיה קריא ומועיל וכו'
איך נוכל לגרום לפלט להיות בפורמט של לוג?
מוזמנים לשלוח רעיונות
#process_substitution
#logging
#exec
#tee
@bash_tips