Chapitre 8 - Communication à distance PowerShell
PowerShell propose de nombreuses façons différentes d’exécuter des commandes sur des ordinateurs distants. Dans le dernier chapitre, vous avez vu comment interroger à distance WMI à l’aide des applets de commande CIM. PowerShell comprend également plusieurs applets de commande avec un paramètre ComputerName intégré.
Comme indiqué dans l’exemple suivant, Get-Command
peut être utilisée avec le paramètre ParameterName pour déterminer les commandes qui ont un paramètre ComputerName.
Get-Command -ParameterName ComputerName
CommandType Name Version Source
----------- ---- ------- ------
Cmdlet Add-Computer 3.1.0.0 Microsoft.PowerShell.Management
Cmdlet Clear-EventLog 3.1.0.0 Microsoft.PowerShell.Management
Cmdlet Connect-PSSession 3.0.0.0 Microsoft.PowerShell.Core
Cmdlet Enter-PSSession 3.0.0.0 Microsoft.PowerShell.Core
Cmdlet Get-EventLog 3.1.0.0 Microsoft.PowerShell.Management
Cmdlet Get-HotFix 3.1.0.0 Microsoft.PowerShell.Management
Cmdlet Get-Process 3.1.0.0 Microsoft.PowerShell.Management
Cmdlet Get-PSSession 3.0.0.0 Microsoft.PowerShell.Core
Cmdlet Get-Service 3.1.0.0 Microsoft.PowerShell.Management
Cmdlet Get-WmiObject 3.1.0.0 Microsoft.PowerShell.Management
Cmdlet Invoke-Command 3.0.0.0 Microsoft.PowerShell.Core
Cmdlet Invoke-WmiMethod 3.1.0.0 Microsoft.PowerShell.Management
Cmdlet Limit-EventLog 3.1.0.0 Microsoft.PowerShell.Management
Cmdlet New-EventLog 3.1.0.0 Microsoft.PowerShell.Management
Cmdlet New-PSSession 3.0.0.0 Microsoft.PowerShell.Core
Cmdlet Receive-Job 3.0.0.0 Microsoft.PowerShell.Core
Cmdlet Receive-PSSession 3.0.0.0 Microsoft.PowerShell.Core
Cmdlet Register-WmiEvent 3.1.0.0 Microsoft.PowerShell.Management
Cmdlet Remove-Computer 3.1.0.0 Microsoft.PowerShell.Management
Cmdlet Remove-EventLog 3.1.0.0 Microsoft.PowerShell.Management
Cmdlet Remove-PSSession 3.0.0.0 Microsoft.PowerShell.Core
Cmdlet Remove-WmiObject 3.1.0.0 Microsoft.PowerShell.Management
Cmdlet Rename-Computer 3.1.0.0 Microsoft.PowerShell.Management
Cmdlet Restart-Computer 3.1.0.0 Microsoft.PowerShell.Management
Cmdlet Send-MailMessage 3.1.0.0 Microsoft.PowerShell.Utility
Cmdlet Set-Service 3.1.0.0 Microsoft.PowerShell.Management
Cmdlet Set-WmiInstance 3.1.0.0 Microsoft.PowerShell.Management
Cmdlet Show-EventLog 3.1.0.0 Microsoft.PowerShell.Management
Cmdlet Stop-Computer 3.1.0.0 Microsoft.PowerShell.Management
Cmdlet Test-Connection 3.1.0.0 Microsoft.PowerShell.Management
Cmdlet Write-EventLog 3.1.0.0 Microsoft.PowerShell.Management
Les commandes comme Get-Process
et Get-Hotfix
ont un paramètre ComputerName. L’exécution de commandes sur des ordinateurs distants n’est pas une solution à long terme retenue par Microsoft. Même si vous trouvez une commande ayant un paramètre ComputerName, il est probable que vous deviez spécifier d’autres informations d’identification et qu’il n’y ait pas de paramètre Credential. Si vous avez décidé d’exécuter PowerShell à partir d’un compte avec élévation de privilèges, un pare-feu entre vous et l’ordinateur distant peut bloquer la demande.
Pour utiliser les commandes de communication à distance PowerShell présentées dans ce chapitre, la communication à distance PowerShell doit être activée sur l’ordinateur distant. Utilisez l’applet de commande Enable-PSRemoting
pour activer la communication à distance PowerShell.
Enable-PSRemoting
WinRM has been updated to receive requests.
WinRM service type changed successfully.
WinRM service started.
WinRM has been updated for remote management.
WinRM firewall exception enabled.
Communication à distance un-à-un
Si vous voulez que votre session à distance soit interactive, la communication à distance un-à-un est ce que vous voulez.
Ce type de communication à distance est fourni par le biais de l’applet de commande Enter-PSSession
.
Dans le dernier chapitre, j’ai stocké mes informations d’identification d’administrateur de domaine dans une variable nommée $Cred
. Si vous ne l’avez pas déjà fait, continuez en stockant vos informations d’identification d’administrateur de domaine dans la variable $Cred
.
Cela vous permet d’entrer les informations d’identification une seule fois et de les utiliser pour chaque commande tant que votre session PowerShell actuelle est active.
$Cred = Get-Credential
Créez une session de communication à distance PowerShell un-à-un sur le contrôleur de domaine nommé dc01.
Enter-PSSession -ComputerName dc01 -Credential $Cred
[dc01]: PS C:\Users\Administrator\Documents>
Notez que, dans l’exemple précédent, l’invite PowerShell est précédée de [dc01]
. Cela signifie que vous êtes dans une session PowerShell interactive sur l’ordinateur distant nommé dc01. Toutes les commandes que vous exécutez s’exécutent sur dc01, et non sur votre ordinateur local. De plus, n’oubliez pas que vous avez uniquement accès aux commandes PowerShell qui existent sur l’ordinateur distant, et pas à celles de votre ordinateur local. En d’autres termes, si vous avez installé des modules supplémentaires sur votre ordinateur, ces derniers ne sont pas accessibles sur l’ordinateur distant.
Quand vous êtes connecté à un ordinateur distant par le biais d’une session de communication à distance PowerShell interactive un-à-un, vous vous trouvez en fait sur l’ordinateur distant. Les objets sont des objets normaux tout comme ceux que vous utilisez dans l’ensemble de cette documentation.
[dc01]: Get-Process | Get-Member
TypeName: System.Diagnostics.Process
Name MemberType Definition
---- ---------- ----------
Handles AliasProperty Handles = Handlecount
Name AliasProperty Name = ProcessName
NPM AliasProperty NPM = NonpagedSystemMemorySize64
PM AliasProperty PM = PagedMemorySize64
SI AliasProperty SI = SessionId
VM AliasProperty VM = VirtualMemorySize64
WS AliasProperty WS = WorkingSet64
Disposed Event System.EventHandler Disposed(System.Object, ...
ErrorDataReceived Event System.Diagnostics.DataReceivedEventHandler ...
Exited Event System.EventHandler Exited(System.Object, Sy...
OutputDataReceived Event System.Diagnostics.DataReceivedEventHandler ...
BeginErrorReadLine Method void BeginErrorReadLine()
BeginOutputReadLine Method void BeginOutputReadLine()
CancelErrorRead Method void CancelErrorRead()
CancelOutputRead Method void CancelOutputRead()
Close Method void Close()
CloseMainWindow Method bool CloseMainWindow()
CreateObjRef Method System.Runtime.Remoting.ObjRef CreateObjRef(...
Dispose Method void Dispose(), void IDisposable.Dispose()
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetLifetimeService Method System.Object GetLifetimeService()
GetType Method type GetType()
InitializeLifetimeService Method System.Object InitializeLifetimeService()
Kill Method void Kill()
Refresh Method void Refresh()
Start Method bool Start()
ToString Method string ToString()
WaitForExit Method bool WaitForExit(int milliseconds), void Wai...
WaitForInputIdle Method bool WaitForInputIdle(int milliseconds), boo...
__NounName NoteProperty string __NounName=Process
BasePriority Property int BasePriority {get;}
Container Property System.ComponentModel.IContainer Container {...
EnableRaisingEvents Property bool EnableRaisingEvents {get;set;}
ExitCode Property int ExitCode {get;}
ExitTime Property datetime ExitTime {get;}
Handle Property System.IntPtr Handle {get;}
HandleCount Property int HandleCount {get;}
HasExited Property bool HasExited {get;}
Id Property int Id {get;}
MachineName Property string MachineName {get;}
MainModule Property System.Diagnostics.ProcessModule MainModule ...
MainWindowHandle Property System.IntPtr MainWindowHandle {get;}
MainWindowTitle Property string MainWindowTitle {get;}
MaxWorkingSet Property System.IntPtr MaxWorkingSet {get;set;}
MinWorkingSet Property System.IntPtr MinWorkingSet {get;set;}
Modules Property System.Diagnostics.ProcessModuleCollection M...
NonpagedSystemMemorySize Property int NonpagedSystemMemorySize {get;}
NonpagedSystemMemorySize64 Property long NonpagedSystemMemorySize64 {get;}
PagedMemorySize Property int PagedMemorySize {get;}
PagedMemorySize64 Property long PagedMemorySize64 {get;}
PagedSystemMemorySize Property int PagedSystemMemorySize {get;}
PagedSystemMemorySize64 Property long PagedSystemMemorySize64 {get;}
PeakPagedMemorySize Property int PeakPagedMemorySize {get;}
PeakPagedMemorySize64 Property long PeakPagedMemorySize64 {get;}
PeakVirtualMemorySize Property int PeakVirtualMemorySize {get;}
PeakVirtualMemorySize64 Property long PeakVirtualMemorySize64 {get;}
PeakWorkingSet Property int PeakWorkingSet {get;}
PeakWorkingSet64 Property long PeakWorkingSet64 {get;}
PriorityBoostEnabled Property bool PriorityBoostEnabled {get;set;}
PriorityClass Property System.Diagnostics.ProcessPriorityClass Prio...
PrivateMemorySize Property int PrivateMemorySize {get;}
PrivateMemorySize64 Property long PrivateMemorySize64 {get;}
PrivilegedProcessorTime Property timespan PrivilegedProcessorTime {get;}
ProcessName Property string ProcessName {get;}
ProcessorAffinity Property System.IntPtr ProcessorAffinity {get;set;}
Responding Property bool Responding {get;}
SafeHandle Property Microsoft.Win32.SafeHandles.SafeProcessHandl...
SessionId Property int SessionId {get;}
Site Property System.ComponentModel.ISite Site {get;set;}
StandardError Property System.IO.StreamReader StandardError {get;}
StandardInput Property System.IO.StreamWriter StandardInput {get;}
StandardOutput Property System.IO.StreamReader StandardOutput {get;}
StartInfo Property System.Diagnostics.ProcessStartInfo StartInf...
StartTime Property datetime StartTime {get;}
SynchronizingObject Property System.ComponentModel.ISynchronizeInvoke Syn...
Threads Property System.Diagnostics.ProcessThreadCollection T...
TotalProcessorTime Property timespan TotalProcessorTime {get;}
UserProcessorTime Property timespan UserProcessorTime {get;}
VirtualMemorySize Property int VirtualMemorySize {get;}
VirtualMemorySize64 Property long VirtualMemorySize64 {get;}
WorkingSet Property int WorkingSet {get;}
WorkingSet64 Property long WorkingSet64 {get;}
PSConfiguration PropertySet PSConfiguration {Name, Id, PriorityClass, Fi...
PSResources PropertySet PSResources {Name, Id, Handlecount, WorkingS...
Company ScriptProperty System.Object Company {get=$this.Mainmodule....
CPU ScriptProperty System.Object CPU {get=$this.TotalProcessorT...
Description ScriptProperty System.Object Description {get=$this.Mainmod...
FileVersion ScriptProperty System.Object FileVersion {get=$this.Mainmod...
Path ScriptProperty System.Object Path {get=$this.Mainmodule.Fil...
Product ScriptProperty System.Object Product {get=$this.Mainmodule....
ProductVersion ScriptProperty System.Object ProductVersion {get=$this.Main...
[dc01]:
Quand vous avez terminé d’utiliser l’ordinateur distant, quittez la session de communication à distance un-à-un à l’aide de l’applet de commande Exit-PSSession
.
[dc01]: Exit-PSSession
Communication à distance un-à-plusieurs
Vous pouvez parfois être amené à effectuer une tâche de manière interactive sur un ordinateur distant. Mais la communication à distance est beaucoup plus puissante quand une tâche est exécutée simultanément sur plusieurs ordinateurs distants. Utilisez l’applet de commande Invoke-Command
pour exécuter une commande sur un ou plusieurs ordinateurs distants en même temps.
Invoke-Command -ComputerName dc01, sql02, web01 {Get-Service -Name W32time} -Credential $Cred
Status Name DisplayName PSComputerName
------ ---- ----------- --------------
Running W32time Windows Time web01
Start... W32time Windows Time dc01
Running W32time Windows Time sql02
Dans l’exemple précédent, trois serveurs ont été interrogés pour obtenir l’état du service de temps Windows. L’applet de commande Get-Service
a été placée dans le bloc de script de Invoke-Command
. Get-Service
s’exécute en fait sur l’ordinateur distant et les résultats sont retournés à votre ordinateur local sous la forme d’objets désérialisés.
La redirection de la commande précédente vers Get-Member
indique que les résultats sont en effet des objets désérialisés.
Invoke-Command -ComputerName dc01, sql02, web01 {Get-Service -Name W32time} -Credential $Cred | Get-Member
TypeName: Deserialized.System.ServiceProcess.ServiceController
Name MemberType Definition
---- ---------- ----------
GetType Method type GetType()
ToString Method string ToString(), string ToString(string format, Sys...
Name NoteProperty string Name=W32time
PSComputerName NoteProperty string PSComputerName=sql02
PSShowComputerName NoteProperty bool PSShowComputerName=True
RequiredServices NoteProperty Deserialized.System.ServiceProcess.ServiceController[...
RunspaceId NoteProperty guid RunspaceId=570313c4-ac84-4109-bf67-c6b33236af0a
CanPauseAndContinue Property System.Boolean {get;set;}
CanShutdown Property System.Boolean {get;set;}
CanStop Property System.Boolean {get;set;}
Container Property {get;set;}
DependentServices Property Deserialized.System.ServiceProcess.ServiceController[...
DisplayName Property System.String {get;set;}
MachineName Property System.String {get;set;}
ServiceHandle Property System.String {get;set;}
ServiceName Property System.String {get;set;}
ServicesDependedOn Property Deserialized.System.ServiceProcess.ServiceController[...
ServiceType Property System.String {get;set;}
Site Property {get;set;}
StartType Property System.String {get;set;}
Status Property System.String {get;set;}
Notez que la majorité des méthodes sont manquantes sur les objets désérialisés. Cela signifie qu’il ne s’agit pas d’objets actifs ; ils sont inertes. Vous ne pouvez pas démarrer ou arrêter un service à l’aide d’un objet désérialisé, car il s’agit d’une capture instantanée de l’état de cet objet au moment où la commande s’est exécutée sur l’ordinateur distant.
Cela ne signifie pas que vous ne pouvez pas démarrer ou arrêter un service à l’aide d’une méthode avec Invoke-Command
. Cela signifie simplement que la méthode doit être appelée dans la session à distance.
Je vais arrêter le service de temps Windows sur ces trois serveurs distants à l’aide de la méthode Stop() pour en apporter la preuve.
Invoke-Command -ComputerName dc01, sql02, web01 {(Get-Service -Name W32time).Stop()} -Credential $Cred
Invoke-Command -ComputerName dc01, sql02, web01 {Get-Service -Name W32time} -Credential $Cred
Status Name DisplayName PSComputerName
------ ---- ----------- --------------
Stopped W32time Windows Time web01
Stopped W32time Windows Time dc01
Stopped W32time Windows Time sql02
Comme mentionné dans un chapitre précédent, s’il existe une applet de commande pour accomplir une tâche, je vous recommande de l’utiliser plutôt que d’utiliser une méthode. Dans le scénario précédent, je recommande l’utilisation de l’applet de commande Stop-Service
au lieu de la méthode stop. J’ai choisi d’utiliser la méthode Stop() pour prouver une chose, car de nombreuses personnes pensent à tort qu’il n’est pas possible d’appeler des méthodes lors de l’utilisation de la communication à distance PowerShell. Elles ne peuvent pas être appelées sur l’objet qui est retourné car il est désérialisé, mais elles peuvent être appelées dans la session à distance elle-même.
Sessions PowerShell
Dans le dernier exemple de la section précédente, j’ai exécuté deux commandes à l’aide de l’applet de commande Invoke-Command
.
Cela signifie que deux sessions distinctes devaient être configurées et désactivées pour exécuter ces deux commandes.
À l’instar des sessions CIM présentées dans le chapitre 7, une session PowerShell sur un ordinateur distant peut être utilisée pour exécuter plusieurs commandes sur l’ordinateur distant sans la surcharge d’une nouvelle session pour chaque commande individuelle.
Créez une session PowerShell sur chacun des trois ordinateurs avec lesquels nous travaillons dans ce chapitre : DC01, SQL02 et WEB01.
$Session = New-PSSession -ComputerName dc01, sql02, web01 -Credential $Cred
À présent, utilisez la variable nommée $Session
pour démarrer le service de temps Windows à l’aide d’une méthode et vérifier l’état de ce service.
Invoke-Command -Session $Session {(Get-Service -Name W32time).Start()}
Invoke-Command -Session $Session {Get-Service -Name W32time}
Status Name DisplayName PSComputerName
------ ---- ----------- --------------
Running W32time Windows Time web01
Start... W32time Windows Time dc01
Running W32time Windows Time sql02
Une fois la session créée à l’aide d’autres informations d’identification, il n’est plus nécessaire de spécifier les informations d’identification à chaque exécution d’une commande.
Une fois que vous avez terminé d’utiliser les sessions, veillez à les supprimer.
Get-PSSession | Remove-PSSession
Résumé
Dans ce chapitre, vous avez appris à utiliser la communication à distance PowerShell, à exécuter des commandes dans une session interactive avec un ordinateur distant et à exécuter des commandes sur plusieurs ordinateurs à l’aide de la communication à distance un-à-plusieurs. Vous avez également découvert les avantages de l’utilisation d’une session PowerShell lors de l’exécution de plusieurs commandes sur le même ordinateur distant.
Révision
- Comment activer la communication à distance PowerShell ?
- Quelle est la commande PowerShell permettant de démarrer une session interactive avec un ordinateur distant ?
- Quel avantage présente l’utilisation d’une session de communication à distance PowerShell par rapport à la simple spécification du nom de l’ordinateur avec chaque commande ?
- Est-il possible d’utiliser une session de communication à distance PowerShell avec une session de communication à distance un-à-un ?
- Quelle est la différence entre le type des objets retournés par les applets de commande et ceux retournés lors de l’exécution de ces mêmes applets de commande sur des ordinateurs distants avec
Invoke-Command
?