src/public/Remote/Invoke-AitherRemoteCommand.ps1
|
#Requires -Version 7.0 <# .SYNOPSIS Execute a command on a remote computer using stored credentials .DESCRIPTION Executes a PowerShell script block on a remote computer using stored credentials. This is a convenience wrapper that creates a session, runs the command, and cleans up automatically - perfect for one-off remote commands. Supports both Windows (WinRM) and Linux/macOS (SSH) targets. .PARAMETER ComputerName Target computer name or IP address. This parameter is REQUIRED. You can specify multiple computers to run the command on all of them. .PARAMETER Credential PSCredential object for authentication. This parameter is REQUIRED unless CredentialName is provided. .PARAMETER CredentialName Name of a stored credential to use. Alternative to providing Credential directly. .PARAMETER ScriptBlock PowerShell script block to execute on the remote computer. This parameter is REQUIRED. Example: { Get-Service | Where-Object Status -eq 'Running' } Example: { Get-Process | Sort-Object CPU -Descending | Select-Object -First 10 } .PARAMETER UseSSH Use SSH transport instead of WinRM. Required for Linux/macOS targets. .PARAMETER UseSSL Use SSL/TLS for WinRM connection (more secure). .PARAMETER Port Port number for the connection. Defaults to 5985 (WinRM), 5986 (WinRM HTTPS), or 22 (SSH). .PARAMETER AsJob Run the command as a background job. Useful for long-running commands. .INPUTS System.String You can pipe computer names to Invoke-AitherRemoteCommand. .OUTPUTS System.Object Returns the output from the remote script block execution. When -AsJob is used, returns System.Management.Automation.Job objects. .EXAMPLE Invoke-AitherRemoteCommand -ComputerName "server01" -Credential (Get-Credential) -ScriptBlock { Get-Service | Where-Object Status -eq 'Running' } Gets running services on server01. .EXAMPLE Invoke-AitherRemoteCommand -ComputerName "server01" -CredentialName "Admin" -ScriptBlock { Get-Process | Sort-Object CPU -Descending | Select-Object -First 10 } Gets top 10 CPU processes using a stored credential. .EXAMPLE $servers = "web01", "web02", "web03" $servers | Invoke-AitherRemoteCommand -CredentialName "Deploy" -ScriptBlock { Stop-Service MyApp Copy-Item \\share\release\*.* C:\App\ Start-Service MyApp } Deploys to multiple servers by piping computer names. .EXAMPLE Invoke-AitherRemoteCommand -ComputerName "linux-server" -Credential (Get-Credential) -UseSSH -ScriptBlock { uname -a } Runs a command on a Linux server using SSH. .EXAMPLE Invoke-AitherRemoteCommand -ComputerName "server01" -CredentialName "Admin" -ScriptBlock { Get-EventLog -LogName Application -Newest 100 } -AsJob Runs a long-running command as a background job. .NOTES This cmdlet automatically: - Creates a PSSession - Executes the script block - Closes the session when done For multiple commands to the same server, consider creating a session with New-AitherPSSession and reusing it for better performance. .LINK New-AitherPSSession Invoke-Command #> function Invoke-AitherRemoteCommand { [OutputType([System.Object], [System.Management.Automation.Job])] [CmdletBinding()] param( [Parameter(Mandatory = $false, Position = 0, ValueFromPipeline, ValueFromPipelineByPropertyName, HelpMessage = "Target computer names or IP addresses.")] [ValidateNotNullOrEmpty()] [string[]]$ComputerName, [Parameter(HelpMessage = "Credential to use for the connection.")] [System.Management.Automation.PSCredential]$Credential, [Parameter(HelpMessage = "Name of a stored credential to use.")] [string]$CredentialName, [Parameter(Mandatory = $false, Position = 1, HelpMessage = "Script block to execute on the remote computer.")] [ValidateNotNull()] [System.Management.Automation.ScriptBlock]$ScriptBlock, [Parameter(HelpMessage = "Use SSH for connection (Linux/macOS targets).")] [switch]$UseSSH, [Parameter(HelpMessage = "Use SSL/HTTPS for WinRM connection.")] [switch]$UseSSL, [Parameter(HelpMessage = "Custom port for the connection.")] [int]$Port, [Parameter(HelpMessage = "Run the command as a background job.")] [switch]$AsJob, [Parameter(HelpMessage = "Show command output in console.")] [switch]$ShowOutput ) begin { # Manage logging targets for this execution $originalLogTargets = $script:AitherLogTargets if ($ShowOutput) { if ($script:AitherLogTargets -notcontains 'Console') { $script:AitherLogTargets += 'Console' } } else { # Ensure Console is NOT in targets if ShowOutput is not specified $script:AitherLogTargets = $script:AitherLogTargets | Where-Object { $_ -ne 'Console' } } # Get credential if CredentialName provided if ($CredentialName -and -not $Credential) { try { $Credential = Get-AitherCredential -Name $CredentialName } catch { Write-AitherLog -Level Warning -Message "Could not retrieve credential '$CredentialName'. You may need to provide Credential directly." -Source 'Invoke-AitherRemoteCommand' -Exception $_ } } } process { foreach ($computer in $ComputerName) { $session = $null try { # Create session $sessionParams = @{ ComputerName = $computer } if ($Credential) { $sessionParams.Credential = $Credential } if ($UseSSH) { $sessionParams.UseSSH = $true if ($Port) { $sessionParams.Port = $Port } } else { if ($UseSSL) { $sessionParams.UseSSL = $true } if ($Port) { $sessionParams.Port = $Port } } $session = New-AitherPSSession @sessionParams # Execute command if ($AsJob) { $job = Invoke-Command -Session $session -ScriptBlock $ScriptBlock -AsJob -ErrorAction Stop return $job } else { $result = Invoke-Command -Session $session -ScriptBlock $ScriptBlock -ErrorAction Stop if ($ShowOutput) { $result | ForEach-Object { Write-AitherLog -Level Information -Message $_ -Source 'Invoke-AitherRemoteCommand' } } return $result } } catch { Invoke-AitherErrorHandler -ErrorRecord $_ -Operation "Executing remote command on $computer" -Parameters $PSBoundParameters -ThrowOnError } finally { if ($session) { Remove-PSSession -Session $session -ErrorAction SilentlyContinue } # Restore original log targets $script:AitherLogTargets = $originalLogTargets } } } } |