לוגים, על 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