מקצוענים בתחום הטכנולוגיה לעיתים קרובות אינם עובדים רק על המחשב המקומי שלנו. באמצעות הפקודה Invoke-Command של PowerShell, אנו לא צריכים לעשות זאת! פקודה זו מאפשרת לנו לכתוב קוד בצורה שוטפת כאילו אנו עובדים על המחשב המקומי שלנו.
על ידי שימוש בתכונת Remoting של PowerShell, פקודת Invoke-Command
היא פקודת PowerShell נפוצה המאפשרת למשתמש לבצע קוד בתוך PSSession. ה- PSSession יכול להיות אחד שנוצר מראש באמצעות פקודת New-PSSession
, או שהוא יכול ליצור ולהפריד במהירות גם מושב זמני.
קשור: Remoting של PowerShell: מדריך המתקדם
חשבו על Invoke-Command כמו על ה־psexec של PowerShell. אף על פי שהם מיושמים בדרכים שונות, המושג הוא אותו הדבר. לקחו קוד או פקודה והריצו אותו "מקומית" על המחשב המרוחק.
כדי ש- Invoke-Command
יעבוד, עליכם לוודא שה־PowerShell Remoting מופעל וזמין על המחשב המרוחק. כברירת מחדל, כל מכונת Windows Server 2012 R2 או מאוחר יותר מצוידות בו ובחריגי הגנה מתאימים. אם יש לכם מכונות Server 2008 עדיין, קיימות דרכים מרובות להגדיר Remoting אך דרך פשוטה היא על ידי הרצת winrm quickconfig
או Enable-PSRemoting
על המחשב המרוחק.
כדי להדגים איך Invoke-Command עובד עם "פקודה רגעית" שאינה דורשת יצירת PSSession חדש, נניח שיש לך מחשב מרוחק מצורף לדומיין של Windows Server 2012 R2 או מאוחר יותר. הדברים מתערערים קצת כשעובדים עם מחשבים בקבוצת עבודה. אני אפתח את חלון הפקודה של PowerShell שלי, אכתוב Invoke-Command ואז אני אלחץ Enter.
I’m immediately asked to provide a scriptblock. The scriptblock is the code that we’re going to run on the remote computer.
כדי שנוכל להוכיח שהקוד בתוך ה-scriptblock מתבצע על המחשב המרוחק, בוא נריץ פשוט את הפקודה hostname. פקודה זו תחזיר את שם המחשב עליו היא מופעלת. ריצת הפקודה hostname על המחשב המקומי שלי מחזירה את שמו.
בוא נעביר עכשיו scriptblock עם אותו הקוד בתוך scriptblock ל-Invoke-Command. אך לפני שנעשה זאת, אנחנו שוכחים פרמטר חובה: ComputerName. אנחנו חייבים לספר ל-Invoke-Command איזה מחשב מרוחק להריץ פקודה זו עליו.
שים לב שפלט הפקודה hostname כעת הוא שם המחשב המרוחק WEBSRV1. הרצת קוד פשוט בתוך scriptblock והעברה למחשב מרוחק יחיד היא האפליקציה הקלה ביותר של Invoke-Command אך היא יכולה לעשות הרבה יותר.
מעבר משתנים מקומיים ל-scriptblocks מרוחקים
אתה לא תמצא הפניה אחת בלבד ל-Invoke-Command בתוך סקריפט. הסקריפט שלך כנראה יהיה מלא בעשרות שורות, יהיו לו משתנים שמוגדרים במקומות שונים, ופונקציות שמוגדרות במודולים וכו '. אפילו אם תכסה קוד מסוים במספר סוגריים מסולסלים, אתה למעשה משנה את הטווח של כל הקוד הזה שרץ בו. לסוף סוף, אתה שולח את הקוד הזה למחשב מרוחק. למחשב המרוחק אין מושג על כל הקוד המקומי במכונה שלך חוץ ממה שנמצא בבלוק הסקריפט.
לדוגמה, אולי יש לך פונקציה עם שם מחשב ופרמטר של נתיב קובץ. תפקידה של פונקציה זו הוא להפעיל מתקין תוכנה מסוים במחשב המרוחק. אתה יכול למסור את שם המחשב ואת נתיב הקובץ "המקומי" למתקין שכבר נמצא במחשב המרוחק.
הפונקציה למטה נראית סבירה, נכון? ננסה להריץ אותה.
הרץ נכשל עם הודעת שגיאה מעורפלת עקב שימוש שלי באופרטור ampersand. הקוד לא היה שגוי, אבל נכשל כי $InstallerFilePath
היה ריק למרות שמסרת ערך עם פרמטר הפונקציה. אנו יכולים לבדוק זאת על ידי החלפת ה-ampersand עם Write-Host
.
שורת הפונקציה החדשה: Invoke-Command -ComputerName $ComputerName -ScriptBlock { Write-Host "נתיב המתקין הוא: $InstallerFilePath" }
שים לב שערך ה־$InstallerFilePath
הוא של ריק. המשתנה לא התרחב כי לא הועבר למכונה המרוחקת. כדי להעביר משתנים מקומיים ל־scriptblock הרחוק, יש לנו שתי אפשרויות; אפשר להקדים את שם המשתנה בתוך $using:
בתוך ה־scriptblock או להשתמש בפרמטר ArgumentList
של Invoke-Command
. בואו נסתכל על שניהם.
הפרמטר ArgumentList
דרך אחת להעביר משתנים מקומיים ל־scriptblock רחוק היא להשתמש בפרמטר ArgumentList
של Invoke-Command
. פרמטר זה מאפשר לך להעביר משתנים מקומיים לפרמטר ולהחליף הפניות למשתנים מקומיים ב־scriptblock עם מצייני מקום.
העברת המשתנים המקומיים לפרמטר ArgumentList
קלה.
החלק שמביא לקושי אצל חלק מהאנשים הוא איך למבנה את המשתנים בתוך ה־scriptblock. במקום להשתמש ב־{ & $InstallerPath }
, עלינו לשנות אותו כך שיהיה או { & $args[0] }
או {param($foo) & $foo }
. שתי הדרכים עובדות באותו אופן אך איזו מהן כדאי להשתמש?
הפרמטר ArgumentList
הוא אוסף אובייקטים. אוספי אובייקטים מאפשרים לך להעביר ערכים אחדים או יותר בכל פעם. במקרה זה, אני מעביר רק אחד.
כאשר בוצע, cmdlet ה-Invoke-Command לוקח את האוסף הזה ואז מכניס אותו לתוך ה- scriptblock, שבעצם משנה אותו למערך הנקרא `$args`. זכור ש- `$args -eq ArgumentList`. בנקודה זו, תתייחס לכל איבר באוסף בדיוק כמו שתעשה עם מערך. במקרה שלנו, הייתה לנו רק רכיב אחד באוסף (`$InstallerFilePath`), ש "תורגם" ל- `$args[0]`, כלומר האינדקס הראשון באוסף זה. אם יש לך יותר, תתייחס אליהם עם `$args[1]`, `$args[2]` וכו'
בנוסף, אם תרצה להקצות שמות משתנים טובים יותר למשתני scriptblock, תוכל גם להוסיף פרמטרים לתוך ה- scriptblock בדיוק כמו בפונקציה. לאחר הכתיבה, תתייחס לפרמטר הזה ב- scriptblock כמו שמוצג למטה.
במקרה זה, האיברים באוסף `ArgumentList` "ממופים" לפרמטרים שהוגדרו לפי הסדר. שמות הפרמטרים לא חשובים; הסדר הוא החשוב. `Invoke-Command` יקח את האיבר הראשון באוסף `ArgumentList`, יחפש את הפרמטר הראשון וימפה את הערכים, יעשה אותו דבר עבור השני, השלישי וכן הלאה.
ה-$Using Construct
המבנה $using
הוא דרך פופולרית נוספת להעברת משתנים מקומיים לתוך בלוק קוד רחוק. מבנה זה מאפשר לך להשתמש מחדש במשתנים המקומיים הקיימים פשוט על ידי הוספת קידומת של $using:
לשם המשתנה. אין צורך לדאוג לאוסף $args
או להוסיף בלוק פרמטרים.
המבנה $using
בפוֹוּרֶשֶׁל הכוח של PowerShell הוא הרבה פשוט יותר, אך אם תתחיל ללמוד Pester, תגלה ש־ArgumentList
יהיה החבר שלך.
Invoke-Command ו־New-PSSession
מבחינה טכנית, הפוסט הזה הוא רק על Invoke-Command אך כדי להדגיש את תועלתו, אנו צריכים להגיע בקצרה אל פקודת New-PSSession
גם. זכור שכבר קדמתי ש־Invoke-Command
יכול להשתמש בפקודות "אד-הוק" או להשתמש בהפעלת הסשן הקיים.
במהלך הפוסט הזה, אנו פשוט מריצים פקודות "אד-הוק" על מחשבים מרוחקים. אנו מקימים סשן חדש, מריצים קוד ומתפרקים אותו. זה תקין למצבים חד פעמיים אך לא כל כך לעת שבה אתה מבצע עשרות פקודות על אותו מחשב. במקרה זה, עדיף להשתמש מחדש בסשן PSSession קיים על ידי יצירתו מראש באמצעות New-PSSession
.
לפני הרצת כל פקודות, תצטרך ליצור PSSession עם New-PSSession
. נוכל לעשות זאת פשוט על ידי הרצת $session = New-PSSession -ComputerName WEBSRV1
. זה יוצר סשן רחוק בשרת וגם הפניה אל הסשן הזה במכשיר המקומי שלי. בנקודה זו, אני יכול להחליף את ההפניות של ComputerName
עם Session
ולהפנות את Session
למשתנה שמור שלי, $session
.
כאשר מורץ, תשימו לב שהביצועים מהירים יותר מכיוון שהסשן כבר נבנה. לאחר השלמת הפעולות, חשוב להסיר את הסשן הפתוח עם Remove-PSSession
.
סיכום
Cmdlet של PowerShell Invoke-Command הוא אחד מה-Cmdlets הכי נפוצים והכי עוצמתיים שקיימים. זהו אחד מהם שאני אישית משתמש בו הכי הרבה. קלות השימוש שלו ויכולתו להריץ כל קוד על מחשבים רחוקים היא עוצמה נפלאה וזו פקודה שאני ממליץ ללמוד מעל לתחתית!