מדריך: שורת הפקודה
-
הבהרות
הבהרה1: נא לסלוח על טעויות כתיב והחלפות זכר לנקבה וכדו', עברית היא לא שפת אם שלי
הבהרה2: יש הרבה שורות פקודה, נשתדל לא להתמקד בשום אחד מהם אלא לדבר על דברים שקשורים לכולם
הבהרה3: אין צורך בשום ידע מוקדם, חוץ מלדעת איפה נמצא כפתור ההפעלה של המחשב...
הבהרה4: אין שום התחייבות להמשיך את הסדרה, זה על בסיס זמן פנוי וחשק...
הבהרה5: למען הסדר הטוב, פתחתי עוד נושא לתגובות, נא להגיב שם. כאן אני מתכוון להעלות המשכים לסדרה.
הבהרה6: בל"נ לא יהיו עוד הבהרות ומיד ניגש לענין...הקדמה: שורת הפקודה מהו
לרוב האנשים המילה "תוכנה" אומרת: "חלון, ובתוכו אובייקטים גראפיים, שבאמצעות אינטראקציה איתם אפשר לעשות פעולות מסויימות". זהו התוכנה האינטראקטיבית. הוא נמצא כל הזמן (עד שתסגור אותו), כל מרכולתו פרושה לפניך, הוא יושב ומחכה לתגובה שלך, ורק נשאר לך לבחור מה אתה רוצה. אתה בוחר משהו, הוא עושה את הפעולה, ושוב חוזר ומחכה לתגובה הבא שלך. התוכנה ה"לא איטראקטיבי" או ה"פקודה", לעומת זאת, אינו יושב ומחכה לתגובה שלך (כמעט) אף פעם, מריצים אותו, הוא עושה מה שביקשת ומיד מסיים תהליך ונסגר. רוצה עוד משהו? צריך להריץ אותו שוב.
בד"כ מריצים תוכנה באמצעות תוכנה אחרת שנקרא ה-shell (מעטפת). יש shell גראפי (בווינדוס נקרא explorer.exe) ובאמצעיתו אפשר להריץ תוכנות אינטראקטיביות ע"י לחיצה על אייקון, ויש shell טקסטואלי שבו מריצים תוכנות ע"י כתיבת שמם וזהו שורת הפקודה.שורת הפקודה = סביבה מבוסס טקסט שבה מריצים תוכנות (לרוב, פקודות לא אינטראקטיביות), (CMD ב-Windows ו-DOS (ז"ל) או Powershell בווינדוס, bash, sh, וכו' בלינוקס, וכו')
למרבה האירוניה, למרות שדרך שורת הפקודה מריצים בד"כ רק תוכנות "לא אינטראקטיביות", אבל שורת הפקודה עצמה מתנהג יותר כתוכנה אינטראקטיבית. הוא מראה לך חלון עם סמן מהבהב ומחכה לקלט שלך. מגיב לפקודות, ובסיום הפקודה אינו נסגר אלה מחכה לעוד.
רכיבים של שורת פקודה
- מקום לקלט (input) - כאן מזינים את הפקודות.
- מקום לפלט (output) - כאן מקבלים תוצאות. (בד"כ זה אותו חלון של הקלט)
- PROMPT (הנחיה?) - רמז ויזואלי שהסביבה מוכן לקבל קלט. כאשר פקודה רצה, הסמן המהבהב נמצא בשורה בפנ"ע בלי PROMPT לפניה (לפעמים יש פלט של הפקודה שרצה, לפעמים לא). כאשר הפקודה מסתיימת, ושורת הפקודה מוכנה לקבל עוד פקודה, מודפס שוב שורת ה-PROMPT ואח"כ סמן מהבהב, זה סימן שאפשר להתחיל לכתוב עוד פקודה.
זה נראה משהו כזה בווינדוס:
C:\Users\yossi>_
(למה כתוב נתיב ב-PROMPT? נגיע לזה יותר מאוחר).
רכיבים של "פקודה" (תוכנה לא אינטראקטיבית)
הרכיבים: קלט, פלט, וחישוב
הפקודה מקבלת קלט עושה עם זה חישוב ומחזירה את הפלט. (לא תמיד חייבים כל הרכיבים).קלט
יש כמה דרכים להכניס קלט לפקודה
- דרך פרמטרים (נקראים גם switches, ו-arguments) = כל מה שכותבים אחרי שם הפקודה. כל זה מוזן לפקודה, הפקודה אמור להבין את זה ולפעול לפי"ז. כותבים את שם הפקודה. אח"כ כותבים את הפרמטרים. כל פקודה מחליטה לעצמה איך לתרגם את הפרמטרים שלה. (אם כי יש כמה מוסכמות מקובלות.)
דוגמא:
echo "Hello, World!"
echo
הוא שם הפקודה. פקודה זו לוקחת את הפרמטרים ופולט אותם החוצה, בלי להפעיל עליהם שום חישובים.
"Hello, World!" הוא פרמטר שהפקודה מקבלת.
הפלט:Hello, World!
אפשר להזין יותר מפרמטר אחד. וכל פרמטר יכול להכיל יותר ממילה אחת. בד"כ רווח מחלק בין פרמטרים, אם כותבים גרשיים מסביב למילים זה מחבר אותם לפרמטר אחד. הפקודה
echo
יכולה לקבל יותר מפרמטר אחת. לפי"ז הייתי יכול לכתוב:echo Hello, World!
ואז זה היה מתורגם לפקודה עם 2 פרמטרים - "Hello," ו-"World!". במקרה שיש יותר מפרמטר אחד, הפקודה
echo
פולט אותם החוצה עם רווח ביניהם, ונקבל אותו פלט.
אמנם, מה יקרה אם נכתוב:echo "Hello, World!" echo Hello, World!
הפלט יהיה:
Hello, World! Hello, World!
(
אזהרה:
הנ"ל נכון רק ב-bash, ב-CMD זה לא יעבוד, אבל העיקרון נכון גם ב-CMD רק שecho
הוא לא פקודה רגילה ב-CMD, אולי נסביר יותר בהמשך)
במקרה הראשון יש פרמטר אחד עם הרבה רווחים באמצע, במקרה השני יש 2 פרמטרים בלי שום רווחים, הרווחים מתורגמים כמחלקים בין הפרמטרים, ולא מוזנים לפקודה.עוד דרכים להזנת קלט:
- קבצים
- משתני סביבה
פלט
- טקסט מודפס בחלון שורת הפקודה
- פעולה שקורה (למשל כיבוי המחשב)
- קבצים
- קוד (מספר) שהתוכנה מחזירה - (return code)
- ....
ההמשך יבוא... (אולי כן, ואולי לא...)
-
פקודות פנימיים לעומת פקודות חיצוניים
פקודות מגיעות ב2 טעמים - פנימי וחיצוני.
פקודה חיצונית הוא תוכנה מהמחשב - לדוגמא אם נכתוב בשורת הפקודהnotepad
זה יריץ את הכתבן מהנתיבC:\Windows\notepad.exe
. אבל יש גם פקודות שממומשות ע"י ה-shell עצמה. נזכיר, ש-shell = סביבה שמתוכה מריצים פקודות. ה-shell הוא גם תוכנה וחלק מהפקודות ממומשות על ידה בלי צורך להריץ תוכנה חיצונית.
למשל, בכל ה-shellים, יש פקודהcd
לשינוי תקייה נוכחי, פקודה זו חייבת להיות פקודה פנימית כי אין דרך לתוכנה חיצונית לשנות את התקייה הנוכחית לתהליך האב שלה. אם נכתוב ב-bash או ב-CMD את הפקודה (הפנימית)help
נקבל רשימה של פקודות פנימיות. (ב-CMD, הרשימה כולל ג"כ פקודות חיצוניות, ב-bash לא).למה חשוב לדעת אם זה פנימי או חיצוני? שאלה טובה... (ב-bash, העזרה המובנית הוא רק לפקודות פנימיות, ב-CMD כמו ב-CMD המצב יותר מסובך...)
תווים מיוחדים
כמו שכבר הזכרנו בפוסט הראשון, הדרך להריץ פקודה הוא - לכתוב את שם הפקודה, ואח"כ פרמטרים. הפרמטרים מועברים לפקודה ע"י ה-shell. בד"כ הפרמטרים לא עוברים עיבוד ע"י ה-shell, אלא מועברים כמו שנכתבו. זה נכון כאשר אין תווים מיוחדים, כאשר יש תווים מיוחדים, תווים אלה יש להם משמעות מיוחדת ל-shell והם לא מועברים לפקודה אלא מתורגמים ע"י ה-shell. לכל shell יש כללים משלו מה נחשב לתו מיוחד, ואיזה פעולה כל תו יעשה. למשל ב-bash נחשב רווח כתו מיוחד, כאשר ה-shell פוגש ברווח, זה אומר לו: כאן סוף פרמטר, התו הבא שאינו רווח מתחיל פרמטר שני. משום כך לא משנה כמה רווחים תשים בין המילים, הפקודה תמיד יקבל את המילה שלפני הרווחים כפרמטר 1, והמילה שאח"כ כפרמטר 2, והרווחים נבלעים ע"י ה-shell.
ב-CMD כמו ב-CMD המצב יותר מסובך... כל מה שמגיע אחרי הפקודה מועבר לפקודה (כולל כל הרווחים). עכשיו הפקודה עצמה יכול לבחור עם לעבד את הפרמטרים בעצמו (עם הכללים שהוא ירצה לייצר לעצמו) או להעביר את המחרוזת לווינדוס לעבד אותו לפי כללים ידועים.
רוב הפקודות מעבירים את המחרוזת לעיבוד לפי הכללים הידועים. ובהם תקף הכלל הנ"ל שרווח מפסיק בין הפרמטרים, וגרשיים מחבר.
תוכנות שנכתבו ב-C (שפת תיכנות ישישה ומכובדת) יעברו עיבוד אוטומטי ע"י ה-CRT (סביבת ההרצה של C - בעיקרון של ווינדוס שכבת תאימות עבור שפת C). (יש גם אפשרות לכתוב ב-C בלי לכלול את ה-CRT, אבל זה שייך ל"תכנות אקסקלוסיבי"...) התוכנה יכולה לבחור בכל זאת להתעלם ולהשתמש במחרוזת המקורית.איך מעבירים רווח לפקודה שמשתמש ברווח כתו מיוחד? למשל אם נרצה למחוק קובץ בשם
c:\new file1.txt
, אם נכתוב כך:del c:\new file1.txt
נקבל תשובה
Could Not Find c:\new Could Not Find C:\WINDOWS\system32\file1.txt
כלומר שהקובץ new (פרמטר 1) לא נמצא, והקובץ file1.txt (פרמטר 2) לא נמצא. אנחנו צריכים לכתוב בפרמטר אחד את כל שם הקובץ, אבל שם הקובץ כולל רווח - שמחלק בין פרמטרים? בשביל זה יש עוד תו מיוחד
"
. הגרשיים מחברים כל מה שבתוכם לפרמטר אחד.del "c:\new file.txt"
ד. א. כאשר ניסיתי כמה פקודות לצורך כתיבת הפוסט, מתברר ש-notepad משתמש במחרוזת המקורית, כולל רווחים. למעט רווחים בסוף המחרוזת (שגם מועברים לתוכנה אבל נמחקים ע"י notepad).
echo
משתמש במחרוזת המקורית. כנ"לcd
. כנ"לstart
. (לכל אחד ייתכנו הבדלים עדינים בדרך שהם מתרגמים את המחרוזת שהם מקבלים).תווים מיוחדים ב-CMD
כמו שהזכרנו, ב-CMD יש תווים שהתוכנה יכולה לבחור אם הם יחשבו כתווים מיוחדים או לא. יש תווים שהם מיוחדים מיוחדים... והם לא יועברו לתוכנה בשום פנים, ואלו הם:
< > ^ | &
ו-enter. (אולי יש יותר?)
איך כותבים תווים אלו בלי שיתורגמו באופן מיוחד ע"י CMD ויועברו ישירות לפקודה? כותבים^
לפני התו:^| ^< ^> ^^ ^&
ו-^
+enter.
התו"
, גם כן מיוחד קצת... כי תו מיוחד אחר (חוץ מ-enter) שמגיע אחרי ה"
הפותח ולפני ה"
הסוגר כבר לא נחשב כתו מיוחד.
אני מאמין שיש עוד כמליון ואחד פרטים לגבי טיפול בתווים מיוחדים ב-CMD... מי שמכיר מוזמן לכתוב באשכול התגובות. -
משתני סביבה
מה זה "משתנה"?
משתנה הוא כל דבר מוגדר - בעל ערך משתנה... משתנה יש לו שם, וערך שניתן לשנות.
למשל, אני רוצה לכתוב פקודה שיקפיץ הודעה שיגיד שלום למישהו. אני יכול לכתוב פקודה שונה לכל אחד שאי פעם ארצה להגיד לו שלום:msg yossi שלום Yossi! msg yossi שלום Dovid! .... ....
(הפקודה
msg
מקבל 2 פרמטרים: שם המשתמש שיראה את ההודעה, ותוכן ההודעה. שם המשתמש במקרה זו הוא yossi והתוכן הוא "שלום פלוני!")או אני יכול לכתוב את הפקודה פעם אחת עם משתנים, שם ה"משתנה" הוא רק עוגן, וה-shell ממלא בכל פעם את הערך של המשתנה בזמן הרצה.
(משתנים ב-CMD כותבים מסובבים ב-
%
-ים. התו%
הוא תו מיוחד רק במקרה שהוא סובב משתנה שקיים במערכת. כדי לכתוב%
בלי שיתורגם כתו מיוחד כותבים^%
. (דרך אגב, טכניקה זו לכתוב תו לפני תו מיוחד כדי שלא יתורגם בצורה מיוחדת, נקרא escaping - מילוט) אין צורך (וגם לא יעזור) לעשות מילוט ל-% הראשון אלא לשני.)למשל אכתוב:
msg %username% שלום %ploni%!
עכשיו ה-shell יבדוק עם יש משתנה מוגדר בשם "USERNAME", ותמיד יש כזה כי זה משתנה שמוגדר אוטומטי ע"י המערכת, וערכו הוא שם המשתמש הפעיל - בדוגמא שלנו "yossi". ה-shell ימחוק את השם של המשתנה ובמקום זה ימלא את הערך "yossi".
עכשיו ה-shell יעבור לבדוק עם יש משתנה בשם PLONI. מכיון שאין, נצטרך להגדיר אחד כזה. ב-CMD עושים את זה כך:
set PLONI=Dovid
אם עכשיו נריץ את הפקודה - התוצאה:
משתני סביבה
משתנה שמוגדר כ"משתנה סביבה" הוא משתנה ששייך לתהליך וכל התהליכים הבנים יקבלו אותו בירושה מהאבא. ב-CMD, כל המשתנים הם משתני סביבה. אם תגדיר משתנה, ואז תריץ פקודה - המשתנה יהיה מוגדר גם בתהליך של הפקודה שרצה. ב-bash יש 2 סוגים, משתנה רגיל, ומשתנה סביבה.
אפשר לראות (וגם לערוך) משתני סביבה של תהליך בתוכנת Process Hacker
אפשר לראות משתני הסביבה של תהליך CMD ע"י הפקודהset
בלי פרמטרים.קראת? יש לך שאלה? השגה? רעיון לשיפור? בקשה להסבר על נושא ספציפי? במקום להצביע ולהמשיך הלאה, תכתוב כאן. הצבעות לא עוזרים לי, ע"י משוב שלכם אדע אם ואיך להמשיך.
ומכאן קריאה למתקדמים (ולאלה שחושבים שהם מתקדמים) נא לקרוא את הפוסטים, אולי תלמדו משהו בדרך, אבל בעיקר נא לקרוא ע"מ לקנטר... אני בטוח שיש המון שגיאות ואי דיוקים. -
(למרות שכתבתי מראש שאני לא רוצה להתמקד על מימוש מסויים של שורת פקודה, אני רואה שיש יותר מדי הבדלים דקים בין המערכות ומכיון שרוב השימוש של מבקרי הפורום הוא בווינדוס, לכן מכאן והלאה, אם לא צויין אחרת מדובר ב-CMD - שורת הפקודה של ווינדוס)
איזה פקודות ניתן להריץ משורת הפקודה?
התשובה היא: כל תוכנה (קובץ EXE) שקיימת במערכת (או בדיסק חיצוני) + פקודות מובנות (ראה למעלה הסבר על פקודות מובנות/פנימיות).
אומנם, יש תוכנות שנבנו מתחילה על דעת להשתמש בהם בסביבת שורת פקודה, ויש תוכנות שנבנו מתחילה על מנת להשתמש בהם בסביבה גרפית.
תוכנה שנבנתה מתחילה לשם שימוש בשורת הפקודה, בד"כ יקבל הרבה יותר פרמטרים מאשר הסוג הגרפי (שהרבה מהם לא מקבלים פרמטרים כלל, או שמקבלים רק פרמטר של שם קובץ). זאת משום שפרמטרים היא אחת מהדרכים העיקריות להעביר קלט אל תוך התוכנה. בנוסף, הסוג הטקסטואלי, יכלול בתוכה קוד שיורה למערכת ההפעלה להדפיס את הפלט שלה בחלון הפקודות. מכיון שכן, אין טעם להריץ אותה מחוץ לשורת הפקודה, מכיון שאז לא יהיה ניתן לקרוא את הפלט שלה.בווינדוס (בניגוד ללינוקס) קיים דגל (ביט בינארי) בתוך קבצי EXE שאומר למערכת ההפעלה "הלו, אני מיועד לשימוש בסביבה השחורה של שורת הפקודה". זה גורם לווינדוס להתייחס לתוכנה בצורה שונה. זה מתבטא בכמה דברים.
א) לחיצה כפולה על התוכנה תמיד יפתח אוטומטית חלון שחור של CMD, (מכיון שכנ"ל אין טעם להריץ אותו מבלי שיהיה לה מקום לפלוט אליו טקסט). ברוב המקרים פתיחת החלון האוטומטי לא עוזר למשתמש מכיון שהחלון נסגר אוטומטית ברגע שהתוכנה מסיים את פעולתה, ואתו נעלם כל הפלט של התוכנה. החכם עיניו בראשו, יפתח מראש חלון פקודה ויריץ את התוכנה מתוך שורת הפקודה.
ב) גם בהרצה מתוך שורת הפקודות (על ידי כתיבת שם התוכנה ולחיצת אנטר) ווינדוס מבחינה בין השתיים. בהרצת הסוג הגרפי, השליטה יחזור מיד ל-shell אחרי הרצת הפקודה. זה ניכר על ידי הדפסה חוזרת של ה-PROMPT (מה זה PROMPT? אפשר לקרוא עליו בפוסט הראשון של הסדרה). זה אומר למשתמש: "אני מוכן לקבל עוד פקודות". לעומת זאת, בסוג הטקסטואלי, בעת ריצת התוכנה, חלון הפקודות נמצא בשליטת התוכנה, זה מתבטא בזה שאי אפשר להזין עוד פקודות, מה שמצויין על ידי חיסרון שורת ה-PROMPT לפני הסמן המהבהב. זאת כדי לתת אפשרות לתוכנה להדפיס מידע לחלון.(במערכות לינוקס, אין הבחנה בין סוגי התוכנות במבנה הקובץ, כל התוכנות תופסים בברירת מחדל את חלון הפקודות כל זמן הריצה, מערכת ההפעלה לא תפתח חלון פקודות אוטומטית עבור שום תוכנה שהיא, יש דרכים להריץ תוכנות מתוך שורת הפקודות בצורה שלא יתפסו את חלון הפקודות, אבל זה נושא לשיעור אחר).
איך מריצים תוכנה XXX מתוך שורת הפקודה?
(לקבל את התשובה המתומצתת, ראה סוף הפוסט)
קודם כל, נסביר למה יש צורך לפעמים להריץ תוכנה דוקא מתוך שורת הפקודה?
אם התוכנה פולטת טקסט לשורת הפקודה, אז חייבים להריץ אותה מתוך שורת הפקודה אחרת לא נוכל לצפות בפלט. גם אם אין פלט (או שאנחנו לא מעוניינים לצפות בפלט), עדיין יש מקרים שאנחנו רוצים להעביר מידע מסויים לתוכנה על ידי פרמטרים, [במקרה כזאת ניתן להריץ את התוכנה גם מתוך תיבת ההפעלה (windows+r)].
עכשיו נסביר מה קורה כאשר מכניסים פקודה לשורת הפקודה:
כמו שכתבנו למעלה (ואוו, כבר עברה שנה!) פקודות מגיעות בשני טעמים - פקודות פנימיות ופקודות חיצוניות. הפנימיות הם אלו שה-shell (מתרגם הפקודות) בעצמו מממשת (לדוגמה
cd
), כלומר, אם נריץ את הפקודה (זוכרים עדיין איך? פשוט כותבים את שם הפקודה ולאחריה הפרמטרים ואנטר לקינוח) ה-shell שמאזין לקלט מסתכל במילה הראשונה (שם הפקודה) ומבין שהפקודה מופנית אליו, ואז הוא קורא ומעבד את שורת הפקודה ומגיב בהתאם.
פקודה חיצונית היא פקודה שלא מובנית בתוך תוכנת ה-shell, ה-shell מקבל את הקלט, בודק את שם הפקודה, ואופסס... הוא לא מזהה את הפקודה. ניקח לדוגמה את הפקודה:notepad
(כתבן). אם נריץ חיפוש על קובץ ה-EXE של תוכנת CMD, נגלה שהמרוזת "notepad" לא נמצא בתוך הקובץ CMD.EXE בשום צורה שהיא. ובכל זאת CMD יודעת איך לטפל בפקודה.
ההתנהגות של ה-shell עבור כל פקודה שהיא לא מכירה הוא לחפש את מערכת הקבצים עבור קובץ עם שם זהה לשם הפקודה, אם הוא מוצא קובץ כזאת הוא מריץ אותה עם הפרמטרים שהוזנו.אבל זה הרי ברור שאי אפשר לחפש את כל מליוני הקבצים במערכת הקבצים כדי למצוא תוכנה עם שם "notepad".
התשובה היא ש-CMD מחפש רק בכמה נתיבים מוגדרים מראש. באיזה נתיבים?
א) לפני הכל, בספריה הנוכחית. (ומה היא ה"ספריה הנוכחית"? ראה מסגרת.)
קודם, CMD יחפש קובץ עם שם זהה לשם הפקודה. אם זה לא נמצא, ינסה CMD למצוא קובץ עם שם זהה לפקודה פלוס אחת מתוך כמה סיומות מוגדרות. בד"כ רשימת הסיומות יכלול:EXE BAT CMD VBS
ועוד כמה. ניתן לשלוט על הרשימה באמצעות משתנה הסביבה:PATHEXT
.ב) במידה ולא נמצאה שום קובץ מתאים בתקייה הנוכחית, יתחיל CMD לחפש בתוך רשימה מוגדרת של נתיבים נוספים. ניתן לשלוט על רשימת הנתיבים באמצעות מתשנה הסביבה
PATH
. להדפיס את ה-PATH הנוכחי, תריצו את הפקודה:set PATH
. זה מדפיס רשימה של נתיבים שמובדלים באמצעות תו;
.הספריה הנוכחית - (Working Directory)
תהליכים במערכת הפעלה מודרנית לא רצות בחלל הריק, שורת הפקודה ומערכת ההפעלה בשיתוף פעולה מכינות להם "סביבת ריצה". הסביבה הזאת כוללת המון דברים (כגון משתני סביבה), ובתוכם "ספריה נוכחית" - שזה אומר תקיית ברירת המחדל לכל פעולה במערכת הקבצים. נגיד שהתוכנה רוצה לכתוב לתוך קובץ, אולי לוג פעילות, אולי קובץ הגדרות, או משהו אחר, לאן לכתוב את הקובץ? לפעמים יש תקייה מוגדרת מראש שאליה יכניס התוכנה את כל קבצי הדאטה שלה, אז היא תגיד למערכת ההפעלה "תצור קובץ בשבילי בנתיב
C:\XXX\XXX
", אפשרות נוספת היא שהיא יכולה להגיד למערכת ההפעלה "תיצור בשבילי בבקשה קובץ בשםXXX
" בלי נתיב, ומערכת ההפעלה תדע לייצר את הקובץ בתוך התיקייה שמוגדרת לתהליך כ"תיקייה הנוכחית".תוכנת CMD ככל תהליך אחר, גם כן רצה בתוך סביבה שכוללת בין השאר גם כן "ספריה נוכחית". אפשר לראות מהי הספריה הנוכחית בטקסט ה-PROMPT.
הספריה הנוכחית באה לידי שימוש בכל מקום שבו כותבים שם של קובץ. אם היא בתוך הספריה הנוכחית, אין צרוך לכתוב את הנתיב המלא של הקובץ, רק את השם של הקובץ עצמו, ומערכת ההפעלה תדע מעצמה לחפש אותה בספריה הנוכחית.
ניתן לשנות את הספריה הנוכחית של תהליך CMD באמצעות פקודתcd
.
בכל יצירת תהליך, מערכת ההפעלה תקבע את הספריה הנוכחית של התהליך לפי הספריה הנוכחית של תהליך האב. בהרצה מתוך CMD, הספריה הנוכחית תהיה הספריה הנוכחית של CMD.עכשיו נחזור לענות על השאלה שהצבנו בכותרת של חלק זה: איך מריצים תוכנה XXX מתוך שורת הפקודה?
התשובה, לאור הנ"ל היא:
- אם הפקודה היא מובנית/פנימית - כותבים את שם הפקודה
- אם הפקודה היא חיצונית - אם הפקודה ממומשת על ידי תוכנה שנמצא בספריה הנוכחית או על ידי תוכנה שנמצא בתוך רשימת הנתיבים שב-
PATH
- אז ניתן להריץ אותה על ידי כתיבת שם קובץ ה-EXE (עם או בלי הסיומת - בתנאי שהסיומת היא מאלו שנמצאים ברשימתPATHEXT
). - אם לא מתקיימים אף אחד מהתנאים הנ"ל, חייבים להביא ל-CMD את הנתיב המלא לקובץ, זה יכול להיות נתיב מלא שמתחיל משם הכונן (לדוגמה:
c:\windows\system32\notepad.exe
), או נתיב חלקי שמתחיל מהספריה הנוכחית (לדוגמה, נגיד שהספריה הנוכחית היאc:\users\yossi
והקובץ נמצא בהורדות, נכתובDownloads\XXXX
)
במערכות לינוקס, אי אפשר להריץ תוכנה מתוך הספריה הנוכחית בלי לציין בפירוש
./XXX
כלומר, נקודה, סלאש, ואז שם התוכנה (נקודה תמיד מציינת את הספריה הנוחכית), זה נכון גם אם הספריה הנוכחית הוא במקרה בתוך ה-PATH
. בנוסף אי אפשר להשמיט את סיומת הקובץ ובד"כ אין סיומות לקבצי תוכנה. בנוסף חייבים לתת לקובץ התוכנה הרשאות ריצה (קבצים שהותקנו באמצעות מנהל החבילות של המערכת יקבלו את ההרשאה אוטומטית, קבצים שהורדו מהאינטרנט למשל, צריך לתת להם הרשאות ריצה על ידי הפקודה:chmod +x XXXX
). -
שרשור פקודות
עד כאן דיברנו על הרצת פקודות בודדות, עכשיו נסביר קצת על שרשור פקודות בצורות שונות, אבל לפני כן מושג יסוד:
קוד יציאה
אחד מהדרכים שבהם תהליכים מתקשרים עם הסביבה הוא על ידי החזרת "קוד יציאה" בסיום ההרצה. קוד היציאה הוא ערך מספרי. יש מוסכמות שונות במערכות הפעלה שונות לגבי מה מספרים שונים מייצגים ומה הגודל המקסימלי של המספרים. אבל יש משהו אחד ששווה לכל המערכות הפופולאריות וזה שמספר 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.
-
Pipes (צינורות)
עד כאן שירשרנו פקודות בצורה שקוד היציאה של הפקודה הקודמת משפיע על הרצתם או אי הרצתם של הפקודות הבאות. לפעמים יש צורך לשרשר בצורה שהפלט של פקודה קודמת נהיה הקלט של הפקודה הבאה. לדוגמה יש לנו פקודה שפולט רשימה של שמות קבצים ועוד פקודה שמחפשת מחרוזת בתוך טקסט, אנחנו רוצים לפלוט את שמות הקבצים ולהריץ על פלט זה את פקודת החיפוש כדי לחפש אם קובץ מסויים נמצא בין הקבצים. לצורך זה משתמשים ב-pipe.
לפני שנבין לעומק איך pipe עובד, צריך להכיר כמה מושגים:קבצים
אנחנו מורגלים לחשוב על קבצים כמקומות אחסון בדיסק קשיח עבור דאטה, אבל תוכנות מסתכלות על קבצים בצורה אחרת לגמרי... בעניים של מערכת הפעלה, המושג "קובץ" מייצג אובייקט שתומך בממשק מוגדר לקריאה או כתיבה של דאטה. (תקראו שוב אם לא הבנתם).
כל מקור שממנו אפשר לקרוא דאטה או כל מיכל שיכול לקבל דאטה יכול לתמוך בממשק המוגדר של "קובץ" ואז זה נראה לעיניים של תוכנה כמו קובץ אמיתי. זה יכול לכלול בין השאר: חיבורי רשת, pipes (שנסביר אותם בהמשך), קבצים אמיתיים, מקלדת ועכבר (אפשר "לקרוא" מתוכם זרם של דאטה - דהיינו המקשים שהמשתמש לוחץ או תנועות העכבר, הם לא תומכים בכתיבה) ועוד
קלט ופלט
לכל פקודה שמערכת ההפעלה מריצה מחוברים "קבצים" של קלט ושל פלט. "קבצים" אלו נראות לפקודה כמו קובץ רגיל, אבל הם לא חייבים להיות קבצים אמיתיים וכנ"ל.
בברירת מחדל ה-shell פותח עבור כל תוכנה שלוש "קבצים".- הקלט (
stdin
או standard input), זה קובץ או כל דבר אחר שמדמה את הממשק של קובץ. זה פתוח לקריאה בלבד והפקודה קוראת מתוכה את הקלט שלה.
כאשר מריצים קלט מתוך טרמינל, הקלט מחובר לטרמינל, כלומר הטרמינל מדמה ממשק של קובץ כאשר פעולת קריאה על ה"קובץ" מביא את הקלט שהמתשמש רושם בטרמינל.
מה קורה כאשר פקודה מבקשת לקרוא מתוך הטרמינל ואין עדיין קלט להזין לו? הפקודה נעצרת עד שיש למערכת ההפעלה קלט להזין לו או עד ל-timeout שניתן להגדיר (ליתר דיוק ה-thread שביקש את הקלט נעצר).
- הפלט הרגיל (
stdout
או standard output), זה קובץ או כל דבר אחר שמדמה ממשק של קובץ. זה פתוח לכתיבה בלבד והוא הפלט ברירת המחדל עבור פלט רגיל של תוכנה.
בברירת מחדל זה הטרמינל שמדמה ממשק של קובץ כאשר "כתיבה" ל"קובץ" מופיע בטרמינל. - פלט השגיאות (
stderr
או standard error), זה קובץ או כל דבר אחר שמדמה ממשק של קובץ. זה פתוח לכתיבה בלבד והוא הפלט ברירת המחדל עבור לוגי שגיאות של תוכנה.
למה יש שתי קבצים לפלט? כי לפעמים אנו רוצים לנתב את הפלט הרגיל למקום אחד ושגיאות למקום שונה
הנ"ל הם קבצי ברירת המחדל, כל תוכנה יכולה לפתוח עוד קבצים גם כן. אבל קבצים אלו תמיד קיימים כי ה-shell פותח אותם עבור תוכנה.
התיאור הנ"ל על קלט ופלט מדוייק לגבי מערכות הפעלה ממשפחת UNIX, (לינוקס, מאק, BSD וכו'). בווינדוס המצב קצת שונה, למרות זאת חלק גדול מהדברים עדיין תקפים והשימוש ב-pipes דומה
PIPE
על פי הנ"ל נבוא להסביר מה זה pipe.
Pipe הינה "קובץ" ווירטואלי (כלומר שאין קובץ מקביל בדיסק הקשיח, ובד"כ אין לו שם או נתיב במערכת הקבצים), שמדמה צינור, כל מה "ששופכים" (= פעולת כתיבה) בצד אחד יוצא (= הוא זמין לפעולות קריאה) כמות שהוא בצד השני. צד אחד של ה-pipe תמיד פתוח רק לכתיבה והצד השני רק לקריאה.
דבר זה מאפשר שירשור פקודות בצורה שהפלט של פקודה א' נהיה הקלט של פקודה ב' וכן הלאה.זה מנגנון עוצמתי במיוחד שמאפשר בניית פקודות מורכבות מאוד.
דוגמה
ניקח כדוגמה את המקרה שהזכרנו בתחילת דברנו, חיפוש אם קובץ מסויים קיים בתיקייה.
לצורך זה נשתמש בשתי פקודות, הראשון פולטת רשימה של קבצים שנמצאים בתקייה, השנייה מחפשת אם מחרוזת מסויימת קיימת בתוך הקלט של הפקודה.
לצורך הביצוע נייצר pipeline (= מחרוזת של פקודות שמחוברות על ידי pipe) שנראה כך:Bash:
ls folder1 | grep filename
CMD:
dir folder1 | findstr filename
ה-pipeline שלנו מורכבת משתי פקודות:
ls
אוdir
ו-grep
אוfindstr
הראשון פולט רשימה של כל הקבצים שנמצאים בתקייה שמזינים בפרמטר של הפקודה (folder1
) והשני מחפש בקלט של עצמו מחרוזת (filename
) שהגדרנו לו בפרמטר הראשון.
הפקודות מחוברות באמצעות תו|
שמסמל pipe.כאשר ה-shell מריץ את הפקודות קורה התהליך הבא:
- יצירת pipe (קובץ ווירטואלי כנ"ל)
- הרצת שתי הפקודות במקביל כאשר הפלט של הראשון מחובר לצד הכניסה/כתיבה של ה-pipe (במקום ברירת המחדל שהוא חלון הטרמינל), והקלט של השני מוגדר להיות צד הקריאה/יציאה של ה-pipe (במקום ברירת המחדל דהיינו חלון הטרמינל).
הפקודה השנייה תדווח לנו אם המילה שביקשנו נמצאה בתוך רשימת הקבצים שהפקודה הראשונה הוציאה.
בפוסט הבא נדבר קצת בעז"ה על ניתוב קלט ופלט.
- הקלט (
-
טוב, הגיע הזמן לעוד פוסט...
והפעם (כמו שהבטחנו) נדבר על "ניתוב קלט ופלט"
כדאי לחזור לפוסט הקודם ולקרוא שוב על המושגים של "קובץ" ו"קלט ופלט" בהקשר זה.
ובקיצור:- "קובץ" בהקשר של ה-shell הוא כל דבר שמאפשר כתיבה לתוכו ו/או קריאה מתוכו. זה כולל חלון הטרמינל, חיבורי רשת, קובצים רגילים (כמובן) ועוד.
- מערכת ההפעלה מגישה ממשק אחיד לתהליכים עבור תקשורת עם "קבצים". לתהליך לא איכפת מה האובייקט שעומד מאחורי המצג הזה של "קובץ", אם זה חיבור רשת או חלון טרמינל או כל דבר אחר.
- לכל תהליך שה-shell מריץ, קיימים בברירת מחדל 3 קבצים פתוחים, הקלט, הפלט, ועוד פלט עבור שגיאות.
נקודה נוספת שכדאי להבין הוא שכאשר אנחנו מדברים על "3 קבצים" שפתוחים בברירת מחדל עבור כל תהליך, התהליך לא מקבל "קובץ" אלא "file handle" - ידית עבור קובץ, ה"ידית" הוא מספר שמייצג את הקובץ, וניתן להשתמש בו מול מערכת ההפעלה עבור פעולה עם הקובץ. לשלוש הקבצים האלו יש מספרים ידועים מראש. 0 (קלט), 1 (פלט), 2 (פלט שגיאות).
ניתוב קלט/פלט
בברירת מחדל, 3 הקבצים הנ"ל, או יותר נכון 3 ה"ידיות" הנ"ל כולם מייצגות את אותו קובץ שהוא ה"קובץ" שמייצג את חלון הטרמינל.
ולכן, בברירת מחדל, כל תהליך קוראת קלט מתוך חלון הטרמינל וכותבת פלט שוב לחלון הטרמינל.
המושג של "ניתוב פלט" הוא לבקש מאת ה-shell לשייך את אחד מ"ידיות" הפלט (1 או 2, או שניהם) לקובץ אחר.
יש כמה "תווים מיוחדים" שמשמשים לצורך ניתוב קלט ופלט' והם:
>
,<
,|
,<<
.
על|
כבר למדנו בפוסט הקודם. הוא התו שמייצר "צינור" ומחבר את הפלט של הפקודה הקודמת לקלט של הפקודה הבאה.ניתוב פלט בסיסי
ניתוב פלט נעשה על ידי התו
>
ואחריה שם של קובץ. (שימו לב שבתוך טקסט ימין לשמאל, גם הכיוון של הגליף הפוך...)
כדי לנתב את הפלט של פקודתls
לקובץ בשםout.txt
כותבים כך:ls > out.txt
התוצאה של פקודה זו הוא שה-shell פותחת את הקובץ out.txt לכתיבה, ומשייכת אותו ל"ידית" מס' 1. ואז היא מריצה את הפקודה
ls
שכותבת את הפלט לקובץ הנ"ל.
התחביר הנ"ל הוא קיצור של תחביר יותר ארוך:ls 1> out.txt
בתחביר הארוך אנחנו מציינים בפירוש את המספר של ה"ידית" שנחנו רוצים לנתב לקובץ out.txt. אם משמיטים את המספר, הכוונה למספר 1.
אם נרצה שגם פלט השגיאות ינותב לקובץ נכתוב ככה:
ls 1>out.txt 2>out.txt
אם הנתיב של קובץ הפלט הוא ארוך זה יוצא קצת ארוך, אז יש קיצור. אפשר ל"שכפל" ידיות. זה נראה ככה:
ls > /A/very/long/and/complicated/path/etc/etc 2>&1
הסימון:
2>&1
בסוף אומר, תנתב את 2 לאותו קובץ ש-1 מייצג.ויש דרך עוד יותר קצרה (זה עובד רק בבאש ולא ב-CMD):
ls &> /A/very/long/and/complicated/path/etc/etc
הכוונה של
$>
הוא "תנתב את 1 ו-2 לקובץ זה".ניתוב של פלט לקובץ בצורה הנ"ל, ידרוס את התוכן הקודם של הקובץ.
מה נעשה אם לא נרצה לדרוס את התוכן הקודם אלא להוסיף לו?
במקום
>
נכתוב>>
. זה מצרף את הפלט של פקודה זו לתוכן הקודם של הקובץ.ניתוב קלט
ניתוב קלט עובד בדיוק כמו ניתוב פלט רק הסימון הוא
<
במקום>
.
(שימו לב שבקטע בכיוון ימין לשמאל, הגליפים הפוכים...)להדגים את זה ניקח את הפקודה:
findstr
(זה ב-CMD, בבאש ישgrep
שדומה לו). פקודה זו קוראת את הקלט שלה ומחפשת שורות שכוללות מחרוזת מסויימת. אם יש שורות כאלה, היא כותבת אותם לפלט שלה.
שימוש לדוגמה, הפקודה (או יותר נכון: ה-pipeline -- רצף פקודות שמועברות בצינור):dir | findstr abc
dir
פולטת רשימה של קבצים בתיקייה הנוכחית. הרשימה מוזנת לקלט של פקודתfindstr
שמחפשת בין הקלט שורות שכוללות את המחרוזת abc, ומדפיסה שורות אלו לפלט.אם נרצה להשתמש בפקודת
findstr
כדי לחפש מחרוזת בתוך קובץ בשם file.txt, איך נעשה את זה?אחת מהדרכים היא על ידי ניתוב קלט:
findstr abc < file.txt
זה גורם ל-shell להריץ את הפקודה במצב ש"ידית" מס' 0 (דהיינו ה"ידית" שמייצגת את הקלט) מצביע על קובץ file.txt.
אגב, הבאתי את זה רק להדגים ניתוב קלט, אומנם יש דרך אחרת לחפש בתוך קובץ. וזה על ידי הפרמטר:
f/
לדוגמה:findstr /f:file.txt abc
.
יש דרך אחרת שאנשים רבים משתשים בה אבל הוא אריכות ללא צורך:type file.txt | findstr abc
כי זה מריץ פעולתtype
ללא כל צורך.
כנ"ל בלינוקס רואים הרבה:cat file.txt | command xyz
כאשר אפשר לכתוב במקום זה:command xyz < file.txt
.
זה נקרא UUOC (ר"ת Useless use of cat).
חוץ מזה שהוא אריכות ללא צורך והשרצת תהליך מיותרת, יש עוד הבדל עדין, עיין בכתבה בוויקיפידיה. -
רציתי להמשיך עם כמה השלמות בענין ניתוב קלט/פלט
חשבתי להכניס את הכל בפוסט אחד אבל החלק הראשון כבר ארך יותר מדי... אז בינתיים נעלה אותו.
חלק זה הוא מידע תיאורטי שלא חייבים להבין כדי להשתמש בשורת הפקודההשלמה בנושא File handles (המכונים גם File descriptors)
רקע
מטעמים מרובים זה לא פרקטי במערכות מדרניים לתת לכל תהליך לגשת ישירות לדיסק הקשיח ולעשות שם מה שהוא רוצה, ולכן אחת מהאחריות של מערכת ההפעלה היא להיות אמצעי בין התהליכים לבין קבצים, וכל גישה לקובץ נעשה דרך הגישור של מערכת ההפעלה.
בכל מערכות ההפעלה הנפוצות, פתיחה של קובץ גורם למערכת ההפעלה להקצות עבור התהליך "ידית" לקובץ (שהוא למעשה סה"כ מספר) כאשר הידית מייצגת את הקובץ ומועברת כפרמטר בכל פעולה שהתהליך רוצה לעשות עם הקובץ.
זה הרעיון של file handles.מימוש בווינדוס ולינוקס
הזכרנו שלכל תהליך שה-shell מריץ קיימות בברירת מחדל 3 ידיות לקבצים. מספרי הידיות הם 0,1 ו-2 והם מייצגות את הקבצים של הקלט/פלט/ושגיאות.
במערכות מבוססות לינוקס מספרים אלו באמת מייצגות את הידית של מערכת ההפעלה. אפשר לראות את זה על ידי הפקודה:lsof -a -p $$ -d0,1,2
זה מראה את הידיות 0,1,2 של ה-shell עצמו.
והתוצאה אמורה להיות משהו כמו זה:COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME bash 16104 yossizahn 0u CHR 136,2 0t0 5 /dev/pts/2 bash 16104 yossizahn 1u CHR 136,2 0t0 5 /dev/pts/2 bash 16104 yossizahn 2u CHR 136,2 0t0 5 /dev/pts/2
הנתיב
/dev/pts/2
מכיל את הקובץ שמייצג את חלון הטרמינל (ע"ע PTY)הסבר הפקודה כאן; אגב, אתר מגניב, לא?
המשתנה$$
מייצגת את ה-PID של ה-shell עצמואם נבצע ניתוב פלט על ידי פקודה כזו:
exec 2> ~/error.log
נקבל טבלת ידיות כזה:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME bash 3460 yossizahn 0u CHR 136,2 0t0 5 /dev/pts/2 bash 3460 yossizahn 1u CHR 136,2 0t0 5 /dev/pts/2 bash 3460 yossizahn 2w REG 8,0 0 519201 /home/yossizahn/error.log
והנה הידית עם מזהה (FD = File Descriptor) 2 באמת פונה לקובץ error.log.
הפקודה
exec
עם ניתוב גורם לנתב את הפלט של ה-shell עצמו. עייןhelp exec
.
פקודתhelp
נותנת עזרה על פקודות "מובנות" או "פנימיות".
בונוס: תלמדו את הייעוד של פקודתexec
ותסבירו למה היא חייבת להיות פקודה מובנית/פנימית ולא פקודה חיצוניתבווינדוס כמו בווינדוס הדברים לא כל כך פשוטים.
א. לא כל תהליך מקבלת את הידיות האלו. רק אלה שמסומנים כאלה שמיועדים עבור שימוש בשורת הפקודה.
ב. מספרי הידיות שמערכת ההפעלה מקצה עבורם הם לא 0,1,2 אלא מספרים אחרים.ניתן לראות את הידיות של תהליך בכלי הנפלא process hacker.
ככה נראה רשימת הידיות של תהליך CMD שהרצתי:
[סיננתי את הרשימה להראות רק ידיות מסוג File]
אפשר לראות שאין שם ידיות עם המספר 0,1,2. אז איפה הם?
התשובה היא שלשם תאימות עם מנגנון זה שמקובל בשורות פקודה של מערכות הפעלה, יש מטהדאטה נוסף שמוצמד לתהליך (ה-PEB) שכולל בתוכו את המידע שממפה ידיות ה-native-ים לידיות 0,1,2.
לא מצאתי בינתיים דרך פשוטה להסתכל במיפוי הזה.
אבל יש דרך לא פשוטה...
בא ננסה ביחד!
החלק הבא למתקדמים בלבד...- נפתח את תוכנת windbg ונבחר מתוך התפריט attach to process.
- ברשימת התהליכים נבחר את התהליך שנרצה לקבל מידע עליו.
[אפשר לסנן את הרשימה לפי שם התהליך] - עכשיו נריץ את הפקודה הבאה בחלון command:
dt _peb @$peb
פקודת
dt
מציג דאטה בצורה יפה (dump בלע"ז), הפרמטר_peb
אומר להציג את זה כמבנה מסוג_peb
. הפרמטר@$peb
מתורגם לכתובת של מבנה ה-PEB.-
נקבל dump של מבנה ה-PEB. מתוך זה נבחר את התת אובייקט:
ProcessParameters
.
למזלינו windbg מספיק חכם לדעת איך לתרגם את האובייקט הזה, והוא מציג אותו כקישור שבלחיצה עליו מורצת אוטומטית הפקודה שתעשה dump עליו:
-
בפלט של הפקודה, סמוך לתחילת הרשימה נראה את המיפוי של הקלט,פלט,ופלט שגיאות:
כל שורה הוא סוג הפלט/קלט עם ערך של הידית שמשוייך אליו.
עכשיו אפשר לחזור ל-process hacker ולקבל את הנתיב של הקובץ לפי המזהה.
(נראה לי שבדיבוג ב-user mode אין דרך פשוטה לקבל את הנתיב של הקובץ מ-windbg, (רק בדיבוג קרנל אפשר) אבל יש דרך מסובכת מאוד, עיין כאן)
טוב, נראה לי שקצת נסחפתי... בפוסט הבא נחזור שוב לנושאי שורת הפקודה
- נפתח את תוכנת windbg ונבחר מתוך התפריט attach to process.