מדריך: שורת הפקודה - תגובות
-
@yossiz תמשיך מחכים לזה בכיליון עינים
-
@yossiz תמשיך מחכים לזה בכיליון עינים
@כוספים-למשיח ביקשת - קיבלת
(עכשיו תבקש שהמשיח יבוא במהרה...)
חבר'ה!!! אם משהו לא ברור או אם רוצים הרחבה בפרט מסויים, תשאלו!, (יותר משהעגל וכו'...).
-
שרשור פקודות
עד כאן דיברנו על הרצת פקודות בודדות, עכשיו נסביר קצת על שרשור פקודות בצורות שונות, אבל לפני כן מושג יסוד:
קוד יציאה
אחד מהדרכים שבהם תהליכים מתקשרים עם הסביבה הוא על ידי החזרת "קוד יציאה" בסיום ההרצה. קוד היציאה הוא ערך מספרי. יש מוסכמות שונות במערכות הפעלה שונות לגבי מה מספרים שונים מייצגים ומה הגודל המקסימלי של המספרים. אבל יש משהו אחד ששווה לכל המערכות הפופולאריות וזה שמספר 0 מייצג הצלחה ומספר אחר מייצג כשלון. למה? פשוט כי יש דרך אחד שבו ניתן להצליח ויש מליון דרכים שבהם ניתן להיכשל.
ב-CMD ניתן לקבל את קוד היציאה של הפקודה האחרונה במשתנה
%errorlevel%
. בבאש ניתן לקבלו במשתנה$?
.שרשור בסיסי
ניתן להשתמש בקוד היציאה של תהליך כדי לשרשר תהליכים בצורות שונות.
- הרץ את הפקודה השנייה רק אם הראשונה הצליחה
command1 && command2
- הרץ את הפקודה השנייה רק אם הראשונה לא הצליחה
command1 || command2
קוד היציאה של השרשור הוא קוד היציאה של הפקודה האחרונה בשרשור, ייתכן שההתנהגות של ביטויים לוגיים ב-JS (למי שמכיר) הושפע מה-shell
- הרץ את הפקודה הראשונה ואח"כ את השנייה בכל מקרה
- CMD
command1 & command2
- bash
command1; command2
If
עוד דרך להשתמש בקוד היציאה כדי להשפיע על הפקודות הבאות הוא השימוש בביטוי "if" (=אם).
דוגמאות ב-CMD:
- אם קוד היציאה של
command1
שווה (EQU
) 0 (כלומר הצליחה) הרץcommand2
אחרת הרץcommand3
:
command1 IF %ERRORLEVEL% EQU 0 (command2) ELSE (command3)
- אם קוד היציאה של
command1
הוא בין 10 ל-20 הרץcommand2
:
command1 IF %ERRORLEVEL% GTR 10 ( IF %ERRORLEVEL% LEQ 20 ( command2 ) )
התחביר של CMD הוא פרימיטיבי קשה ומסורבל לעומת bash או powershell. יש אתר מצויין שמתעד אותו: https://ss64.com/nt ניתן ללמוד משם הכל. אבל אין צורך להכיר את כל הפינות של השפה, מספיק להכיר מלמעלה את היכולות ואז לבדוק במקרה הצורך באתר הנ"ל. אני השתמשתי בו עבור הדוגמאות הנ"ל.
דוגמאות ב-bash:
- אם קוד היציאה של
command1
שווה 0 (כלומר הצליחה) הרץcommand2
אחרת הרץcommand3
:
if command1; then command2; else command3; fi
- אם קוד היציאה של
command1
הוא בין 10 ל-20 הרץcommand2
:
command1 if [[ $? -gt 10 && $? -le 20 ]]; then command2; else command3; fi # או if [ $? -gt 10 -a $? -le 20 ]; then command2; else command3; fi # או if [ $? -gt 10 ] && [ $? -le 20 ]; then command2; else command3; fi # או if (( $? > 10 && $? <= 20 )); then command2; else command3; fi
ב-CMD הביטוי
if
בוחן את התוצאה של ביטוי בוליאני (ביטוי שתוצאתה הינו true או false), ב-bash ביטויif
תמיד בוחן קוד יציאה של פקודה. יש לצורך זה כמה פקודות "מיוחדות" כמו]
, [[ ... ]]
, (( ... ))
ו-test
. פקודות אלו מקבלות ביטוי בוליאני ומחזירים קוד יציאה של 0 במידה והתוצאה היא true וקוד יציאה של 1 במידה והתוצאה false.למי שמכיר שפות תכנות: שימו לב, ביטוי
if
ב-bash עובד בדיוק הפוך מבכל שפות התכנות. קוד יציאה של 0 נחשב כהצלחת מבחן ה-if וקוד לא אפסי נחשב ככשלון.בפוסט הבא בעז"ה נרחיב על pipes.
-
@yossiz אמר במדריך: שורת הפקודה:
ייתכן שההתנהגות של ביטויים לוגיים ב-JS למי שמכיר הושפע מה-shell
אתה בטוח? אני חושב שגם בC זה יעבוד ככה, זה כורח המציאות, הרי הביטוי הימני יבוצע בהתאם לאופרטור עם התוצאה של השמאלי, זה הרעיון של short circuit.
@dovid לא הייתי מספיק ברור.
לא התכוונתי להתנהגות ה-short circuiting אלא לזה שהתוצאה של ביטוי לוגי הוא לא ערך בוליאני אלא הערך של הביטוי האחרון שהורץ.(בטבלה הזאת בוויקיפידיה אפשר לראות ש-JS ו-shell הם השפות הכי נפוצות שמתנהגים כך [יש גם את perl lua python ו-ruby. זה ברור לי ש-perl הושפע רבות מתחביר shell] )
ערכתי בפנים
-
@yossiz מיוחד מאד המדריך של הפייפס, אני זוכר שפעם הסתבכתי מאד עם הקטע של הפלט השונה של השגיאות, אני מקווה שאתה הולך להרחיב על זה עוד (על הקטע של > שזה הזרם הרגיל, ו >> שזה הזרם של השגיאות, נראה לי).
בכל מקרה תודה רבה על המדריך המושקע הזה, זה באמת מאד חשוב ולא כ"כ ידוע.
-
@yossiz מיוחד מאד המדריך של הפייפס, אני זוכר שפעם הסתבכתי מאד עם הקטע של הפלט השונה של השגיאות, אני מקווה שאתה הולך להרחיב על זה עוד (על הקטע של > שזה הזרם הרגיל, ו >> שזה הזרם של השגיאות, נראה לי).
בכל מקרה תודה רבה על המדריך המושקע הזה, זה באמת מאד חשוב ולא כ"כ ידוע.
-
@yossiz
אם אתה עוסק בקלט ובפלט, האם אתה תגיע מתי שהוא לאיך עובד הפלט של הGUI
או שזה לא קשור בשום דרך לשורת הפקודה, אז זה כבר מדריך נפרד? -
@nigun אמר במדריך: שורת הפקודה - תגובות:
איך עובד הפלט של הGUI
לא הבנתי למה אתה מתכוון. אתה מדבר על GUI של תוכנה מסויימת או בכללות? איזה פלט?
-
@yossiz
כל תוכנה
דהיינו אם תוכנת CLI מוציאה את הstdout ואת הstdout לטרמינל.
מה קורה בתוכנות עם ממשק גרפי?
או שבעצם הטרמינל הוא גם תוכנה עם ממשק גרפי שמציג את הפלט של הפקודות בצורה גרפית?@nigun אמר במדריך: שורת הפקודה - תגובות:
מה קורה בתוכנות עם ממשק גרפי?
אני מניח שאתה מדבר על לינוקס.
(בווינדוס המושג הזה של stdout ו-stderr לא קיים בצורה מובנית. בשפת C, C++ שהמושג קיים הם עושים שכבת תאימות - ב-CRT - ש(בין השאר) מספק את הזרמים האלו לתוכנה, אגב זה קיים בהרבה דברים שהמושגים של unix ושפת C מאוד תואמים אחד את השני, כי אלה שהמציאו את מערכת יוניקס הם אותם שהמציאו את שפת C).
בלינוקס לכל תוכנה (כולל תוכנות גרפיות) קיימים שלוש file handles שפתוחים מיד בעת הרצת התוכנה.
אם תהליך האבא לא מגדיר את הקבצים האלו אז הבן יורש את אותם handle-ים של האבא.בד"כ תוכנת הטרמינל מריץ את ה-shell כאשר ה-handles פונים לקובץ PTY שמקביל לקלט ופלט של הטרמינל. ואז רואים את ה-prompt של הטרמינל בחלון הטרמינל. אם תריץ תוכנה מתוך shell שרץ בטרמינל תראה את הפלט שלו בטרמינל (אם הוא לא עושה fork כדי להתנתק מהטרמינל)
אם אתה מריץ תוכנה מתוך תפריט התחלה גרפית בלינוקס, אז הוא יירש את ה-stdout מהאבא, פעם (כאשר הייתי משתמש בלינוקס...) היה קובץ שנקרא משהו כמו xsession_errors (אני לא זוכר בדיוק את השם) שקיבל את ה-stderr של תוכנות שהורצו בתוך סביבה גרפית.
עריכה: הקובץ נקרא.xsession-errors
וה-stdout של ה-Xserver מחובר אליו, וממילא גם של כל הבנים והנכדים וכל המשפחה העניפה... עיין (https://stackoverflow.com/a/17019341) כהיום שעברו ל-wayland ייתכן שדברים השתנו.
לשירותים, (כמו של systemd) אפשר להגדיר בתצורת השירות לאן יפנה ה-stdout ו-stderr.
יש מושג של ניתוב הפלט ל-/dev/null
שזה חור שחור שמדמה קובץ.ובקיצור יש המון פרטים וקשה לכתוב את הכל על רגל אחת...
-
@nigun אם אתה באמת רוצה לדעת לאן מנותבים שלוש הזרמים הסטנדרטיים של תהליך בלינוקס, תוכל לבדוק ב-
lsof
או יותר קל ב-htop
(מקש L כאשר אתה עומד על תהליך) את הקבצים הפתוחים של התוכנה. המזהים של הזרמים הסטנדרטיים הם תמיד:שם מזהה stdin
0 stdout
1 stderr
2 -
@nigun אמר במדריך: שורת הפקודה - תגובות:
מה קורה בתוכנות עם ממשק גרפי?
אני מניח שאתה מדבר על לינוקס.
(בווינדוס המושג הזה של stdout ו-stderr לא קיים בצורה מובנית. בשפת C, C++ שהמושג קיים הם עושים שכבת תאימות - ב-CRT - ש(בין השאר) מספק את הזרמים האלו לתוכנה, אגב זה קיים בהרבה דברים שהמושגים של unix ושפת C מאוד תואמים אחד את השני, כי אלה שהמציאו את מערכת יוניקס הם אותם שהמציאו את שפת C).
בלינוקס לכל תוכנה (כולל תוכנות גרפיות) קיימים שלוש file handles שפתוחים מיד בעת הרצת התוכנה.
אם תהליך האבא לא מגדיר את הקבצים האלו אז הבן יורש את אותם handle-ים של האבא.בד"כ תוכנת הטרמינל מריץ את ה-shell כאשר ה-handles פונים לקובץ PTY שמקביל לקלט ופלט של הטרמינל. ואז רואים את ה-prompt של הטרמינל בחלון הטרמינל. אם תריץ תוכנה מתוך shell שרץ בטרמינל תראה את הפלט שלו בטרמינל (אם הוא לא עושה fork כדי להתנתק מהטרמינל)
אם אתה מריץ תוכנה מתוך תפריט התחלה גרפית בלינוקס, אז הוא יירש את ה-stdout מהאבא, פעם (כאשר הייתי משתמש בלינוקס...) היה קובץ שנקרא משהו כמו xsession_errors (אני לא זוכר בדיוק את השם) שקיבל את ה-stderr של תוכנות שהורצו בתוך סביבה גרפית.
עריכה: הקובץ נקרא.xsession-errors
וה-stdout של ה-Xserver מחובר אליו, וממילא גם של כל הבנים והנכדים וכל המשפחה העניפה... עיין (https://stackoverflow.com/a/17019341) כהיום שעברו ל-wayland ייתכן שדברים השתנו.
לשירותים, (כמו של systemd) אפשר להגדיר בתצורת השירות לאן יפנה ה-stdout ו-stderr.
יש מושג של ניתוב הפלט ל-/dev/null
שזה חור שחור שמדמה קובץ.ובקיצור יש המון פרטים וקשה לכתוב את הכל על רגל אחת...
-
@yossiz
כשאני מריץ תוכנה גרפית בטרמינל
אז הוא פותח לי חלון בצד עם הממשק הגרפי
ואת הלוגים (כנראה stderr) הוא מדפיס בטרמינל.
איך הוא יודע שהפלט מיועד לממשק הגרפי?הסברתי את זה, אבל כנראה לא מספיק ברור... (לוקח משאבים להסביר ברור...)
@yossiz אמר במדריך: שורת הפקודה - תגובות:
בד"כ תוכנת הטרמינל מריץ את ה-shell כאשר ה-handles פונים לקובץ PTY שמקביל לקלט ופלט של הטרמינל. ואז רואים את ה-prompt של הטרמינל בחלון הטרמינל. אם תריץ תוכנה מתוך shell שרץ בטרמינל תראה את הפלט שלו בטרמינל
כל טרמינל מייצר קובץ (וירטואלי, משהו שמדמה קובץ). ואז הוא מריץ את ה-shell כאשר הזרמים הסטנדרטיים שלו כולם מנותבים ל"קובץ" הזה. (בתמונה שהעליתי בפוסט הקודם שם הקובץ הוא
/dev/ttyS0
).
הטרמינל קורא מתוך הקובץ הזה את הפלט של תוכנות וכותב לתוכה את הקלט שמשתמש מזין לתוך חלון הטרמינל. (אני מפשט קצת, בפועל יש שני קבצים... עיין בכתבה בויקיפידיה או תגגל את הנושא של pty).
כאשר ה-shell מוליד תהליך בן, תהליך הבן יורש בברירת מחדל את ה-handle-ים לזרמים הסטנדרטיים מהאבא.
כאשר תוכנה כותב פלט הוא כותב ל-handle עם מזהה 1 או 2 (תלוי אם זה stderr או stdout) וזה מנותב לקובץ שה-handle הזה מייצג. שבברירת מחדל יהיה הקובץ שמננו הטרמינל קורא את הפלט של תוכנות.מובן, או שעדיין לא ברור?
-
הסברתי את זה, אבל כנראה לא מספיק ברור... (לוקח משאבים להסביר ברור...)
@yossiz אמר במדריך: שורת הפקודה - תגובות:
בד"כ תוכנת הטרמינל מריץ את ה-shell כאשר ה-handles פונים לקובץ PTY שמקביל לקלט ופלט של הטרמינל. ואז רואים את ה-prompt של הטרמינל בחלון הטרמינל. אם תריץ תוכנה מתוך shell שרץ בטרמינל תראה את הפלט שלו בטרמינל
כל טרמינל מייצר קובץ (וירטואלי, משהו שמדמה קובץ). ואז הוא מריץ את ה-shell כאשר הזרמים הסטנדרטיים שלו כולם מנותבים ל"קובץ" הזה. (בתמונה שהעליתי בפוסט הקודם שם הקובץ הוא
/dev/ttyS0
).
הטרמינל קורא מתוך הקובץ הזה את הפלט של תוכנות וכותב לתוכה את הקלט שמשתמש מזין לתוך חלון הטרמינל. (אני מפשט קצת, בפועל יש שני קבצים... עיין בכתבה בויקיפידיה או תגגל את הנושא של pty).
כאשר ה-shell מוליד תהליך בן, תהליך הבן יורש בברירת מחדל את ה-handle-ים לזרמים הסטנדרטיים מהאבא.
כאשר תוכנה כותב פלט הוא כותב ל-handle עם מזהה 1 או 2 (תלוי אם זה stderr או stdout) וזה מנותב לקובץ שה-handle הזה מייצג. שבברירת מחדל יהיה הקובץ שמננו הטרמינל קורא את הפלט של תוכנות.מובן, או שעדיין לא ברור?
@yossiz
תודה על הסבלנות
בעיקר היה חסר לי הקטע של "ברירת מחדל"
דהיינו שזה מנותב לhandle של האב אא"כ צוין אחרת (ע"י התוכנה כנראה).אז כשאני נכנס למכונה דרך SSH אז כל הקלט הוא מהSSH וכנ"ל הפלט
ואם אני מפעיל תוכנת SCREEN אז הקלט מופנה למקום כל שהוא בתוכנה.
וכנ"ל אפשר לשלוח את הפלט לUDP או לאיפה שאני ירצה.עריכה: האם היעד יכול להיות ישירות למסך או שחייב לעבור דרך מקום אחר?
כי אם יש לי כמה טרמינאלים פתוחים (בw3) ואני כותב באחד מהםecho hello >/dev/pts/6
הפלט מופיע במסך המבוקש, אבל זה לא כותב ישירות למסך אלא יש כאן כמה שגרירים בדרך.נראה לי שהבנתי את הכיוון, תודה רבה.
נ.ב. אני רואה שיש לי עוד הרבה לקרוא למשל מה זה בעצם ה$DISPLAY ומה ההבדל בין סוגי הפלט (כמו שרואים בתמונה הזאת )
-
@yossiz
תודה על הסבלנות
בעיקר היה חסר לי הקטע של "ברירת מחדל"
דהיינו שזה מנותב לhandle של האב אא"כ צוין אחרת (ע"י התוכנה כנראה).אז כשאני נכנס למכונה דרך SSH אז כל הקלט הוא מהSSH וכנ"ל הפלט
ואם אני מפעיל תוכנת SCREEN אז הקלט מופנה למקום כל שהוא בתוכנה.
וכנ"ל אפשר לשלוח את הפלט לUDP או לאיפה שאני ירצה.עריכה: האם היעד יכול להיות ישירות למסך או שחייב לעבור דרך מקום אחר?
כי אם יש לי כמה טרמינאלים פתוחים (בw3) ואני כותב באחד מהםecho hello >/dev/pts/6
הפלט מופיע במסך המבוקש, אבל זה לא כותב ישירות למסך אלא יש כאן כמה שגרירים בדרך.נראה לי שהבנתי את הכיוון, תודה רבה.
נ.ב. אני רואה שיש לי עוד הרבה לקרוא למשל מה זה בעצם ה$DISPLAY ומה ההבדל בין סוגי הפלט (כמו שרואים בתמונה הזאת )
@nigun אמר במדריך: שורת הפקודה - תגובות:
אני רואה שיש לי עוד הרבה לקרוא למשל מה זה בעצם ה$DISPLAY ומה ההבדל בין סוגי הפלט (כמו שרואים בתמונה הזאת )
אתה מערב עכשיו נושאים אחרים. זה כבר לא קשור לנושא המקורי.
$DISPLAY
ל-Xserver. בתמונה רואים כל הקבצים הפתוחים. יש כל מיני קבצים במערכת לינוקס שרובם לא מקבילים לקבצים אמיתיים. כל חיבור רשת או תקשורת בין תהליכי מופיע כקובץ. -
הסברתי את זה, אבל כנראה לא מספיק ברור... (לוקח משאבים להסביר ברור...)
@yossiz אמר במדריך: שורת הפקודה - תגובות:
בד"כ תוכנת הטרמינל מריץ את ה-shell כאשר ה-handles פונים לקובץ PTY שמקביל לקלט ופלט של הטרמינל. ואז רואים את ה-prompt של הטרמינל בחלון הטרמינל. אם תריץ תוכנה מתוך shell שרץ בטרמינל תראה את הפלט שלו בטרמינל
כל טרמינל מייצר קובץ (וירטואלי, משהו שמדמה קובץ). ואז הוא מריץ את ה-shell כאשר הזרמים הסטנדרטיים שלו כולם מנותבים ל"קובץ" הזה. (בתמונה שהעליתי בפוסט הקודם שם הקובץ הוא
/dev/ttyS0
).
הטרמינל קורא מתוך הקובץ הזה את הפלט של תוכנות וכותב לתוכה את הקלט שמשתמש מזין לתוך חלון הטרמינל. (אני מפשט קצת, בפועל יש שני קבצים... עיין בכתבה בויקיפידיה או תגגל את הנושא של pty).
כאשר ה-shell מוליד תהליך בן, תהליך הבן יורש בברירת מחדל את ה-handle-ים לזרמים הסטנדרטיים מהאבא.
כאשר תוכנה כותב פלט הוא כותב ל-handle עם מזהה 1 או 2 (תלוי אם זה stderr או stdout) וזה מנותב לקובץ שה-handle הזה מייצג. שבברירת מחדל יהיה הקובץ שמננו הטרמינל קורא את הפלט של תוכנות.מובן, או שעדיין לא ברור?
-
-
@yossiz
בדיוק אתמול ניסתי להבין איך בונים טרמינל בדפדפן (כמו בcode-server וכדו')
איכשהו נפלתי עלDISPLAY
והסתבכתי עם זה כהוגן.
עכשיו אני מבין שזה פשוט עוד PTY שמנתב את הhandles לHTTP
וככה זה נראה בקוד בסיסי (כאן זה יוצר עוד טרמינל "שקוף", ואם בודקים עםtty
רואים שזה קורא מקובץ PTY אחר, לכאורה כל מה שצריך לשנות זה את הניתוב לWEB ואז אפשר לנהל את השרת מהדפדפן) -
@yossiz
בדיוק אתמול ניסתי להבין איך בונים טרמינל בדפדפן (כמו בcode-server וכדו')
איכשהו נפלתי עלDISPLAY
והסתבכתי עם זה כהוגן.
עכשיו אני מבין שזה פשוט עוד PTY שמנתב את הhandles לHTTP
וככה זה נראה בקוד בסיסי (כאן זה יוצר עוד טרמינל "שקוף", ואם בודקים עםtty
רואים שזה קורא מקובץ PTY אחר, לכאורה כל מה שצריך לשנות זה את הניתוב לWEB ואז אפשר לנהל את השרת מהדפדפן)@nigun אמר במדריך: שורת הפקודה - תגובות:
איכשהו נפלתי על DISPLAY והסתבכתי עם זה כהוגן.
עכשיו אני מבין שזה פשוט עוד PTY שמנתב את הhandles לHTTPלגבי DISPLAY אתה טועה, זה כלל לא קשור לסיפור. זה משתנה שאומר לתוכנות גרפיות עם איזה xserver לתקשר.
לכאורה כל מה שצריך לשנות זה את הניתוב לWEB ואז אפשר לנהל את השרת מהדפדפן
בזה נראה לי שקיבלת תמונה נכונה.
-
@nigun אמר במדריך: שורת הפקודה - תגובות:
איכשהו נפלתי על DISPLAY והסתבכתי עם זה כהוגן.
עכשיו אני מבין שזה פשוט עוד PTY שמנתב את הhandles לHTTPלגבי DISPLAY אתה טועה, זה כלל לא קשור לסיפור. זה משתנה שאומר לתוכנות גרפיות עם איזה xserver לתקשר.
לכאורה כל מה שצריך לשנות זה את הניתוב לWEB ואז אפשר לנהל את השרת מהדפדפן
בזה נראה לי שקיבלת תמונה נכונה.