שאלה מה זה 'להגדיר' לעשות, ומדוע זה עלול להיחשב מסוכן?


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

מה זה 'להגדיר' לעשות, ומדוע זה עלול להיחשב מסוכן?


142
2018-05-19 16:39




הנה נושא קשור: stackoverflow.com/questions/64786/error-handling-in-bash/... - Stefan Lasiewski


תשובות:


set -e גורם פגז לצאת אם כל subcommand או צינור מחזיר מעמד לא אפס.

התשובה שהמראיין בוודאי חיפש היא:

זה יהיה מסוכן להשתמש "set -e" בעת יצירת scripts init.d:

מ http://www.debian.org/doc/debian-policy/ch-opersys.html 9.3.2 -

היזהר בשימוש set -e scripts init.d. כתיבת scripts init.d הנכון דורש לקבל סטטוסים שונים יציאת השגיאה כאשר הדמונים כבר פועל או כבר עצר בלי הפסק script init.d, וספריות פונקציונליות init.d משותף לא בטוח להתקשר עם set -e למעשה. עבור scripts init.d, זה לעתים קרובות יותר קל להשתמש set -e ובמקום לבדוק את התוצאה של כל פקודה בנפרד.

זוהי שאלה תקינה מנקודת מבט של המראיין, משום שהיא מודדת מועמדים העובדים על רמת השרתים של סקריפטים ואוטומציה


148
2017-08-09 21:01



נחמד למצוא. תודה. - egorgry
נקודה טובה. זה היה לעצור את תהליך האתחול על משהו שעשוי להיות שגיאה טכנית, אבל לא צריך לגרום את כל סקריפט לעצור - Matt
למרות שאני מסכים stackoverflow.com/questions/78497/..., אני חושב סגנון זה מוצא התאמה טובה עם bash עבור בדיקות init קצר ו רישום או תיקון הסביבה קופים אחרים לפני execing את עומס העבודה היעד. אנו משתמשים באותה מדיניות עבור קובץ ה- docker שלנו תמונה script. - joshperry


מ bash(1)You

          -e      Exit immediately if a pipeline (which may consist  of  a
                  single  simple command),  a subshell command enclosed in
                  parentheses, or one of the commands executed as part  of
                  a  command  list  enclosed  by braces (see SHELL GRAMMAR
                  above) exits with a non-zero status.  The shell does not
                  exit  if  the  command that fails is part of the command
                  list immediately following a  while  or  until  keyword,
                  part  of  the  test  following  the  if or elif reserved
                  words, part of any command executed in a && or  ││  list
                  except  the  command  following  the final && or ││, any
                  command in a pipeline but the last, or if the  command’s
                  return  value  is being inverted with !.  A trap on ERR,
                  if set, is executed before the shell exits.  This option
                  applies to the shell environment and each subshell envi-
                  ronment separately (see  COMMAND  EXECUTION  ENVIRONMENT
                  above), and may cause subshells to exit before executing
                  all the commands in the subshell.

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


33
2018-05-19 16:43



מסכה אמיתי / בעיות אחרות, כן, אני מניח שאני יכול לראות את זה ... אני נאבקת לבוא עם דוגמה של זה להיות מסוכן, כמו גם ... - cpbills
יש את דף השער set! אני תמיד מגיע builtin(1). תודה. - Jared Beck
איך אני יודע את התיעוד עבור set הוא befound ב man 1 bash?? ואיך יוכל מישהו למצוא את -e אופציה עבור set מילת מפתח בדף ידני גדול כל כך? אתה פשוט לא /-e חפש כאן - Blauhirn
@Blauhirn באמצעות help set - Blauhirn


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

some code
set -e     # same as set -o errexit
more code  # exit on non-zero status
set +e     # same as set +o errexit
more code  # no exit on non-zero status

כמו כן ראוי לציין את זה מן סעיף האיש באש על trap אשר מתאר גם כיצד set -e פונקציות בנסיבות מסוימות.

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

אז יש כמה תנאים שבהם מעמד לא אפס לא יגרום ליציאה.

אני חושב שהסכנה היא לא להבין מתי set -e נכנס לשחק וכאשר זה לא להסתמך על זה בצורה לא נכונה תחת הנחה לא נכונה כלשהי.

ראה גם בשאפא / 105 למה לא מוגדר -E (או להגדיר- errexit, או מלכודת ERR) לעשות מה שציפיתי?


19
2018-05-19 22:39



בעוד סטייה מן השאלה קצת, התשובה הזאת היא בדיוק מה שאני מחפש: מכבה אותו רק חלק קטן של תסריט! - Stephan Bijzitter


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

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

השתתפתי ב -40 ראיונות עבודה ב -2 השנים האחרונות, והמרואיינים לפעמים שואלים שאלות שגויות, או שיש להם תשובות שגויות.

או אולי זו שאלה טריקית, שתהיה צולעת, אבל לא לגמרי בלתי צפויה.

או אולי זה הסבר טוב: http://www.mail-archive.com/debian-bugs-dist@lists.debian.org/msg473314.html


13
2018-05-19 17:03



+1 אני באותה סירה, והרבה "ראיונות" טכניים אני כבר להתמודד עם היה לפחות misguided מעט. - cpbills
וואו. טוב למצוא את רשימת debian. +1 עבור בורות שאלות ראיון. אני זוכר להתווכח תשובה netback פעם אחת מאז הייתי 100% בטוח שאני צודק. הם אמרו לא. הלכתי הביתה וגוגלדתי אותו, צדקתי. - egorgry


set -e אומר bash, בתסריט, כדי לצאת כאשר משהו מחזיר ערך החזר אפס.

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


9
2018-05-19 16:46



זה מעניין. לא חשבתי על הרשאות שנפתחו בתסריט שמת לפני הזמן, אבל יכולתי לראות שזה נחשב מסוכן. החלק המהנה של חידון זה הוא שאתה לא יכול להשתמש בכל חומרי עזר כגון אדם או גוגל ואם אתה לא יכול לענות באופן מלא לא לענות על זה בכלל. - egorgry
זה פשוט טיפשי, הייתי לשקול מחדש את המעסיק ... צוחק (סוג של). זה טוב יש בסיס חזק של ידע, אבל מחצית של עבודה IT הוא לדעת / היכן / כדי למצוא את המידע ... אני מקווה שהם היו חכמים מספיק כדי לקחת את זה בחשבון כאשר הבקשות המועמדים. על הערה צדדית, אני רואה / לא / להשתמש עבור set -e, למעשה, לי זה מדבר על עצלות להתעלם בדיקת שגיאות סקריפטים שלך ... אז לזכור את זה, עם המעסיק הזה, גם ... אם הם משתמשים בו הרבה, איך נראים הסקריפטים שלהם, כי אתה יהיה בהכרח צריך לשמור ... - cpbills
נקודה מעולה @ cpbills. אני גם לא רואה שום שימוש עבור להגדיר-e ב סקריפט וזה כנראה למה זה stumped אותי כל כך הרבה. אני רוצה לפרסם את כל השאלות מאז כמה באמת טובים וחלקם באמת wacky אקראי כמו זה. - egorgry
ראיתי את זה הרבה cron עבודות המערכת ... - Andrew


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

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

לגרג וולדג' יש הרבה מה לומר על הסכנות של set -eYou

בקישור השני, ישנן דוגמאות שונות של התנהגות לא אינטואיטיבית ובלתי צפויה של set -e.

כמה דוגמאות להתנהגות לא אינטואיטיבית של set -e (חלק לקוחים מתוך הקישור wiki לעיל):

  • בחר
    x = 0
    תן x + +
    הד "x הוא $ x"
    האמור לעיל יגרום סקריפט פגז ליציאה בטרם עת, כי let x++ מחזירה 0, אשר מטופל על ידי let מילת מפתח כערך falsy והפכה לקוד יציאה לא מזויף. set -e מבחין זה, ו בשקט מסתיים את התסריט.
  • בחר
    [-d / opt / foo] && echo "אזהרה: foo כבר מותקן. > & 2
    echo "מתקין foo ..."
    

    האמור לעיל עובד כצפוי, הדפסת אזהרה אם /opt/foo כבר קיים.

    בחר
    check_previous_install () {
        [-d / opt / foo] && echo "אזהרה: foo כבר מותקן. > & 2
    }
    
    check_previous_install
    echo "מתקין foo ..."
    

    האמור לעיל, למרות ההבדל היחיד הוא כי שורה אחת כבר refactored לתפקד, יסתיים אם /opt/foo לא קיים. הסיבה לכך היא העובדה כי זה עבד במקור הוא יוצא מן הכלל מיוחד set -eשל התנהגות. מתי a && b מחזיר nonzero, הוא התעלם על ידי set -e. עם זאת, עכשיו זה פונקציה, קוד היציאה של הפונקציה הוא שווה את קוד היציאה של הפקודה, ואת הפונקציה לחזור nonzero יהיה בשקט לסיים את התסריט.

  • בחר
    IFS = $ '\ n' read -d '' -r-config_vars <config
    

    האמור לעיל יקרא את המערך config_vars מהתיק config. כמו המחבר עלול מתכוון, זה מסתיים עם שגיאה אם config חסר. כמו המחבר אולי לא מתכוון, זה מסתיים בשקט אם config אינו מסתיים בקו חדש. אם set -e לא היו בשימוש כאן config_vars יכיל את כל השורות של הקובץ אם זה הסתיים או לא.

    משתמשים של טקסט הנשגב (ועורכי טקסט אחרים אשר לטפל Newlines בצורה לא נכונה), היזהר.

  • בחר
    
    should_audit_user () {
        קבוצות קבוצה מקומית = "$ (קבוצות" $ 1 ")"
        עבור קבוצה בקבוצות $; לעשות
            אם ["$ group" = Audit]; ואז לחזור 0; Fi
        בוצע
        Return/
    }
    
    אם המשתמש צריך "$_ לאחר מכן
        לוגר 'בלה'
    Fi
    

    המחבר כאן סביר לצפות כי אם מסיבה כלשהי המשתמש $user לא קיים, אז groups הפקודה תיכשל והסקריפט יסתיים במקום לתת למשתמש לבצע משימה מסוימת ללא ביקורת. עם זאת, במקרה זה את set -e לא ייכנס לתוקף. אם $user לא ניתן למצוא מסיבה כלשהי, במקום לסיים את התסריט, את should_audit_user הפונקציה פשוט להחזיר נתונים שגויים כאילו set -e לא היה בתוקף.

    זה חל על כל פונקציה המופעלת ממצב התנאי של if הצהרה, לא משנה כמה עמוק מקונן, לא משנה היכן הוא מוגדר, לא משנה גם אם אתה מפעיל set -e בתוכה שוב. שימוש if בכל שלב משבית לחלוטין את ההשפעה של set -e עד לחסימת הבלוק במצב מלא. אם המחבר אינו מודע זה pitfall, או לא יודע את כל מחסנית השיחה בכל המצבים האפשריים שבהם פונקציה ניתן לקרוא, אז הם יכתבו קוד באגי ואת תחושת שווא של ביטחון המסופק על ידי set -e יהיה לפחות להאשים באופן חלקי.

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

כמה חסרונות נוספים של set -eYou

  • זה מעודד קוד מרושל. שגיאה מטפלים נשכחים לחלוטין על, בתקווה כי מה נכשל יהיה לדווח על השגיאה בצורה כלשהי הגיוני. עם זאת, עם דוגמאות כמו let x++ לעיל, זה לא המקרה. אם התסריט מת באופן בלתי צפוי, הוא בדרך כלל בדממה, מה שמקשה על איתור באגים. אם התסריט אינו מתים ואתה מצפה אותו (ראה נקודת כדור קודמת), אז יש לך באג עדין יותר חתרני על הידיים.
  • זה מוביל אנשים לתחושה מזויפת של ביטחון. ראה שוב את if- נקודת קליע מותנית.
  • המקומות שבהם פגז מסתיים אינם עקביים בין פגזים או גרסאות פגז. זה אפשרי בטעות לכתוב סקריפט אשר מתנהג אחרת על גרסה ישנה יותר של bash בשל ההתנהגות של set -e לאחר שהיה tweaked בין גירסאות אלה.

set -e היא בעיה במחלוקת, וכמה אנשים מודעים לסוגיות המקיפות אותו ממליצים נגד זה, בעוד כמה אחרים פשוט ממליצים לטפל בזמן שהוא פעיל כדי לדעת את המלכודות. יש הרבה פגז scripting Newbies אשר ממליצים set -eעל כל סקריפטים כמו לתפוס את כל התנאים שגיאה, אבל בחיים האמיתיים זה לא עובד ככה.

set -e אינו תחליף לחינוך.


6
2018-04-27 23:06





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


2
2018-05-19 18:07



לגמרי מסכים עם תשובה זו. זה לא מטבע הדברים מסוכן, אבל זו הזדמנות לקבל יציאה מוקדמת בלתי צפויה. - pboin
מה זה הזכיר לי הוא C + + פרופ 'שלי כי תמיד היה משיכת נקודות מן המטלות שלי עבור לא נתקל נקודת כניסה אחת / נקודת יציאה אחת בתוכנית. חשבתי שזה עניין 'עיקרון' גרידא, אבל זה להגדיר את העסק בהחלט demos איך ולמה דברים יכולים לחלוטין להסתחרר מכלל שליטה. בסופו של דבר תוכניות הן על שליטה דטרמיניזם, ועם סיום מוקדם אתה מוותר על שניהם. - Marcin


כדוגמה מוחשית יותר לתגובתו של מרצ'ין, אשר נשכה אותי אישית, דמיינתי שהיתה rm foo/bar.txt במקום כלשהו בתסריט שלך. בדרך כלל לא עניין גדול אם foo/bar.txt לא קיים בפועל. עם זאת set -e נוכחים עכשיו את התסריט שלך יסתיים מוקדם שם! אופס.


0
2018-06-22 19:00