Még nagyobb hiánya volt az 1.0-ás verziónak, hogy nem volt lehetőség PowerShell cmdletek távoli futtatására. Persze bizonyos WMI metódusok rendelkeztek távoli futtatás lehetőségével, amelyeket PowerShellből meghívva persze olyan érzésünk lehetett, hogy táv-futtatunk, de ez nem volt az igazi. Most már viszont bármit futtathatunk távolról is! Nem teszteltem le az összes cmdletet, de a BITS fájlátvitellel kapcsolatos cmdleteket biztos nem lehet távolról futtatni.
A háttérben ennek és a később előkerülő távoli futtatás infrastruktúráját a WinRM szolgáltatás biztosítja. Ez Vista operációs rendszertől fölfelé érhető el alaphelyzetben, de a Management Framework részeként (amelyben a PowerShell 2.0 is benne van) Windows XP-re és Windows Server 2003-ra is telepíthető. Ez a szolgáltatás telepítés után magától nem fut, legegyszerűbben az Enable-PSRemoting paranccsal lehet bekapcsolni:
[14] PS C:\> Enable-PSRemoting
WinRM Quick Configuration
Running command "Set-WSManQuickConfig" to enable this machine for remote
management through WinRM service.
This includes:
1. Starting or restarting (if already started) the WinRM service
2. Setting the WinRM service type to auto start
3. Creating a listener to accept requests on any IP address
4. Enabling firewall exception for WS-Management traffic (for http
only).
Do you want to continue?
[Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help
(default is "Y"):y
WinRM already is set up to receive requests on this machine.
WinRM already is set up for remote management on this machine.
Confirm
Are you sure you want to perform this action?
Performing operation "Set-PSSessionConfiguration" on Target "Name:
microsoft.powershell SDDL:
O:NSG:BAD:P(A;;GA;;;BA)S:P(AU;FA;GA;;;WD)(AU;SA;GXGW;;;WD). This will
allow selected users to remotely run Windows PowerShell commands on this
computer".
[Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help
(default is "Y"):y
Confirm
Are you sure you want to perform this action?
Performing operation "Set-PSSessionConfiguration" on Target "Name:
Microsoft.PowerShell32 SDDL: O:NSG:BAD:P(A;;GA;;;BA)S:P. This will allow
selected users to remotely run Windows PowerShell commands on this
computer".
[Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help
(default is "Y"):y
Confirm
Are you sure you want to perform this action?
Performing operation "Set-PSSessionConfiguration" on Target "Name:
microsoft.ServerManager SDDL:
O:NSG:BAD:P(A;;GA;;;BA)S:P(AU;FA;GA;;;WD)(AU;SA;GXGW;;;WD). This will
allow selected users to remotely run Windows PowerShell commands on this
computer".
[Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help
(default is "Y"):y
Ez egy összetett folyamatot indít el. Egyrészt a winrm quickconfig parancs PowerShelles megfelelőjét, a Set-WSMandQuickCOnfig -ot futtatja, másrészt a távoli csatlakozás pontjait állítja be. Ez egy 64 bites gépen tartalmazza az alaphelyzet szerinti Microsoft.Powershell csatlakozási pontot (PSSessionConfiguration-t) és a Microsoft.Powershell32 csatlakozási pontokat. Ezekről majd részletesebben a gyakorlati részben, a 2.23 Távoli futtatási környezet testre szabása fejezetben lesz szó.
A WinRM szolgáltatás http protokollba ágyazott kommunikációt folytat, így akár tűzfalon keresztül is képes két gép ezzel egymással kommunikálni. A kommunikáció eleve titkosított, így nem feltétlenül szükséges SSL titkosítás használata, de arra is van lehetőség. Ha sikeresen beindítottuk a WinRM szolgáltatást, akkor létrehozhatjuk a távoli futtatáshoz szükséges munkameneteket.
Visszatérve a távoli futtatás engedélyezésére, látható volt, hogy sok jóváhagyás után tudtunk csak eljutni a funkció bekapcsolásáig. Ha ezeket a jóváhagyásokat ki akarjuk hagyni, akkor használjuk a ‑force kapcsolót:
[15] PS C:\> Enable-PSRemoting -force
A távoli futtatással kapcsolatos cmdletek főneve a PSSession:
PS C:\> Get-Command -noun pssession
CommandType Name Definition
----------- ---- ----------
Cmdlet Enter-PSSession Enter-PSSession [-Computer...
Cmdlet Exit-PSSession Exit-PSSession [-Verbose] ...
Cmdlet Export-PSSession Export-PSSession [-Session...
Cmdlet Get-PSSession Get-PSSession [[-ComputerN...
Cmdlet Import-PSSession Import-PSSession [-Session...
Cmdlet New-PSSession New-PSSession [[-ComputerN...
Cmdlet Remove-PSSession Remove-PSSession [-Session...
Nyissunk is gyorsan egy ilyen PSSession-t a New-PSSession cmdlet segítségével, rögtön két gépre:
[16] PS C:\> New-PSSession -ComputerName dc, member
Id Name ComputerName State ConfigurationName Availab
ility
-- ---- ------------ ----- ----------------- -------
1 Session1 member Opened Microsoft.PowerShell ...able
2 Session2 dc Opened Microsoft.PowerShell ...able
Ha egy picit részletesebb listanézetre váltunk, akkor még több információt kapunk:
[17] PS C:\> Get-PSSession 1 | fl
ComputerName : member
ConfigurationName : Microsoft.PowerShell
InstanceId : 3c8eafa1-1efe-4f7f-ae2d-f1bab9f749f9
Id : 1
Name : Session1
Availability : Available
ApplicationPrivateData : {PSVersionTable}
Runspace : System.Management.Automation.RemoteRunspace
State : Opened
Megjegyzés
Egy géphez egy időben akár több PSSession-t is nyithatunk. Vigyázzunk, ezt csak akkor alkalmazzuk, ha tényleg erre van szükség. Például sok gépnek akarjuk újraindítani ugyanazt a szolgáltatást, akkor nem sok értelme van ezt kétszer megcsinálni egy adott gépen.
Bírjuk munkára ezt a fajta munkamenetet is, kíváncsi vagyok az összes bevont gépen futó, „g” betűvel kezdődő szolgáltatásra:
[23] PS C:\> Invoke-Command -Session (Get-PSSession) -ScriptBlock {get-ser
vice g*}
Status Name DisplayName PSComp
uterNa
me
------ ---- ----------- ------
Running gpsvc Group Policy Client member
Running gpsvc Group Policy Client dc
Itt nem kell külön lekérni a futtatás eredményét, hiszen itt most nem „job”-ként hajtattam végre a scriptet, azaz az eredményt rögtön megkaptam. A kimenet elvileg akár lehetne „vegyes” is, azaz a különböző gépekről érkező információk keveredhetnének is, ilyenkor szükség lehet a kimenet PSComputerName szerinti rendezésére is.
Ha mégis háttérben szeretném futtatni ezeket, akkor van lehetőség erre is, a korábban már említett –AsJob kapcsoló használatával:
[33] PS C:\> Invoke-Command -Session (Get-PSSession) -ScriptBlock {get-ser
vice g*} -AsJob
WARNING: column "Command" does not fit into the display and was removed.
Id Name State HasMoreData Location
-- ---- ----- ----------- --------
23 Job23 Running True member,dc
[34] PS C:\> Receive-Job 23
Status Name DisplayName PSComp
uterNa
me
------ ---- ----------- ------
Running gpsvc Group Policy Client member
Running gpsvc Group Policy Client dc
Az első lépésben tehát most nem magát a szolgáltatások listáját kaptam meg, hanem az elindított munkamenet-objektumot. Itt láthatjuk, hogy a Location tulajdonság tartalmazza a számítógépneveket, ahol a munkamenet fut. A Receive-Job-bal kérdezhetjük le a futtatott szkript kimenetét.
Még érdekesebb, hogy interakcióba is léphetünk ilyen PSSession objektumokkal az Enter-PSSession cmdlet segítségével, azaz úgy dolgozhatunk, mintha tényleg azon a gépen nyitottunk volna meg egy PowerShell ablakot:
[35] PS C:\> Get-PSSession
Id Name ComputerName State ConfigurationName Availab
ility
-- ---- ------------ ----- ----------------- -------
1 Session1 member Opened Microsoft.PowerShell ...able
2 Session2 dc Opened Microsoft.PowerShell ...able
[36] PS C:\> Enter-PSSession 1
[member]: PS C:\Users\TEMP\Documents> cd c:\
[member]: PS C:\> $env:computername
MEMBER
A fenti példában az 1-es PSSession-höz csatlakoztam, minek következtében a prompt is megváltozott jelezvén, hogy amit ezután látok és gépelek az nem a saját gépemen, hanem a távoli gépen érvényes. Kilépni ebből az Exit-PSSession cmdlettel lehet:
[member]: PS C:\> Exit-PSSession
[37] PS C:\>
A létrehozott PSSession objektumokat a Remove-PSSession cmdlettel tudjuk megszüntetni, például az összes megszüntetése a következő kifejezéssel lehetséges:
[38] PS C:\> Get-PSSession | Remove-PSSession
Ha a PSSession objektumokra nincs szükségünk tartósan, mert csak egy szkript futtatásának erejéig akarjuk használni, akkor az invoke-command dinamikusan is képes ilyeneket létrehozni, futtatni bennük a szkriptet és megszüntetni. Ilyenkor a ComputerName paramétert kell megadni:
[39] PS C:\> Invoke-Command -ComputerName dc, member -ScriptBlock {$env:co
mputername}
MEMBER
DC
A futtatás után nem is marad semmilyen PSSession objektum, amit meg kellene szüntetni.
A paraméterátadás ugyanolyan módon történik, mint ahogy a háttérfolyamatok során láttuk, itt is az ‑inputobject paraméteren keresztül lehet átadni a változókat:
[40] PS C:\> $a = " gép"; Invoke-Command -Session (get-pssession) -ScriptB
lock {$env:computername + $input} -InputObject $a
MEMBER gép
DC gép
Megjegyzés
Vigyázat! A PSSession-nek átadott objektumok némi csonkításon mennek keresztül. Az alábbi példában egy mappaobjektumot adok át a PSSesson-nek, és a munkamenetből nézve kérek egy get-member-t erre az objektumra:
[44] PS C:\> $a = get-item C:\munka
[45] PS C:\> Invoke-Command -Session (Get-PSSession) -ScriptBlock {$input
| gm} -inputobject $a
TypeName: Deserialized.System.IO.DirectoryInfo
WARNING: column "PSComputerName" does not fit into the display and was re
moved.
Name MemberType Definition
---- ---------- ----------
ToString Method string ToString(), string ToString(stri...
BaseName NoteProperty System.String BaseName=munka
Mode NoteProperty System.String Mode=d----
PSChildName NoteProperty System.String PSChildName=munka
PSDrive NoteProperty Deserialized.System.Management.Automati...
PSIsContainer NoteProperty System.Boolean PSIsContainer=True
PSParentPath NoteProperty System.String PSParentPath=Microsoft.Po...
…
Látható, hogy a System.IO.DirectoryInfo objektumomból „Deserialized” változat lett, azaz elvesztette az objektum az összes metódusát és csak a tulajdonságai élnek tovább. A háttérben pont az játszódik le, mint amit korábban láttunk az objektumok XML adatblokkokká történő konvertálása során, hiszen a hálózaton keresztül itt is pont XML adatok formájában utazgatnak az objektumok.