Last active
June 27, 2024 06:20
-
-
Save davidlu1001/75b7a4b1adf1385b2e8c05f733073b5c to your computer and use it in GitHub Desktop.
Operation scripts for copy files and run commands on remote servers
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
## Usage Examples | |
# | |
### Execute a command on multiple remote computers | |
# .\ops.ps1 -ComputerName Server1, Server2 -Command "Get-Service | Where-Object {`$_.Status -eq 'Running'}" | |
# | |
### Run a script on a remote computer with arguments | |
# .\ops.ps1 -ComputerName Server1 -ScriptPath C:\Scripts\DiskCleanup.ps1 -ArgumentList @{DaysOld = 30; LogPath = "C:\Logs"} | |
# | |
### Copy files to multiple remote computers | |
# .\ops.ps1 -ComputerName Server1, Server2 -Source C:\Updates\Patch.msp -Destination C:\Temp -Recurse | |
# | |
### Use a config file to specify target computers | |
# .\ops.ps1 -ConfigFile C:\Servers.txt -Command "Get-EventLog -LogName System -Newest 10" | |
# | |
### Execute a command with specific credentials | |
# $cred = Get-Credential | |
# .\ops.ps1 -ComputerName RemoteServer -Command "Get-WmiObject Win32_LogicalDisk" -Credential $cred | |
# | |
### Perform a dry run of a script execution | |
# .\ops.ps1 -ComputerName Server1, Server2 -ScriptPath C:\Scripts\UpdateSoftware.ps1 -DryRun | |
# | |
### Execute a command and save results to a file | |
# .\ops.ps1 -ComputerName Server1, Server2 -Command "Get-HotFix" -OutputFile C:\Reports\InstalledUpdates.csv | |
# | |
### Limit concurrent operations | |
# .\ops.ps1 -ConfigFile C:\LargeServerList.txt -Command "ipconfig /all" -ThrottleLimit 5 | |
#Requires -Version 5.0 | |
[CmdletBinding(DefaultParameterSetName='Run')] | |
param ( | |
[Parameter(ParameterSetName='Run', Mandatory=$true)] | |
[Parameter(ParameterSetName='Copy', Mandatory=$true)] | |
[ValidateNotNullOrEmpty()] | |
[string[]]$ComputerName, | |
[Parameter(ParameterSetName='Run')] | |
[ValidateNotNullOrEmpty()] | |
[string]$Command, | |
[Parameter(ParameterSetName='Run')] | |
[ValidateScript({Test-Path $_ -PathType Leaf})] | |
[string]$ScriptPath, | |
[Parameter(ParameterSetName='Run')] | |
[hashtable]$ArgumentList, | |
[Parameter(ParameterSetName='Copy', Mandatory=$true)] | |
[ValidateScript({Test-Path $_})] | |
[string[]]$Source, | |
[Parameter(ParameterSetName='Copy', Mandatory=$true)] | |
[ValidateNotNullOrEmpty()] | |
[string]$Destination, | |
[Parameter(ParameterSetName='Copy')] | |
[switch]$Recurse, | |
[Parameter(ParameterSetName='Run')] | |
[Parameter(ParameterSetName='Copy')] | |
[ValidateScript({Test-Path $_ -PathType Leaf})] | |
[string]$ConfigFile, | |
[Parameter(ParameterSetName='Run')] | |
[switch]$DryRun, | |
[Parameter(ParameterSetName='Run')] | |
[Parameter(ParameterSetName='Copy')] | |
[ValidateNotNullOrEmpty()] | |
[string]$OutputFile, | |
[Parameter(ParameterSetName='Run')] | |
[Parameter(ParameterSetName='Copy')] | |
[ValidateRange(1, 3600)] | |
[int]$Timeout = 300, | |
[Parameter(ParameterSetName='Run')] | |
[Parameter(ParameterSetName='Copy')] | |
[System.Management.Automation.PSCredential] | |
[System.Management.Automation.Credential()] | |
$Credential = [System.Management.Automation.PSCredential]::Empty, | |
[Parameter(ParameterSetName='Run')] | |
[Parameter(ParameterSetName='Copy')] | |
[ValidateRange(1, 100)] | |
[int]$ThrottleLimit = 10 | |
) | |
function Get-RemoteHosts { | |
[CmdletBinding()] | |
param ( | |
[string]$ConfigFile, | |
[string[]]$ComputerName | |
) | |
if ($ConfigFile) { | |
if (Test-Path $ConfigFile) { | |
$hosts = Get-Content $ConfigFile | Where-Object { $_ -notmatch '^\s*$' -and $_ -notmatch '^\s*#' } | |
if ($hosts.Count -eq 0) { | |
throw "No valid hosts found in config file: $ConfigFile" | |
} | |
return $hosts | |
} else { | |
throw "Config file not found: $ConfigFile" | |
} | |
} elseif ($ComputerName) { | |
return $ComputerName | |
} else { | |
throw "No remote hosts specified. Use either -ConfigFile or -ComputerName" | |
} | |
} | |
function Invoke-RemoteOperation { | |
[CmdletBinding()] | |
param ( | |
[string[]]$ComputerName, | |
[hashtable]$Params | |
) | |
$scriptBlock = { | |
param($Params) | |
try { | |
switch ($Params.ParameterSet) { | |
'Run' { | |
if ($Params.Command) { | |
Invoke-Expression $Params.Command | |
} elseif ($Params.ScriptPath) { | |
& $Params.ScriptPath @Params.ArgumentList | |
} | |
} | |
'Copy' { | |
$drive = New-PSDrive -Name TempDrive -PSProvider FileSystem -Root $Params.Destination -Credential $Params.Credential -ErrorAction Stop | |
foreach ($src in $Params.Source) { | |
$dest = Join-Path -Path "TempDrive:" -ChildPath (Split-Path -Path $src -Leaf) | |
Copy-Item -Path $src -Destination $dest -Recurse:$Params.Recurse -Force -ErrorAction Stop | |
} | |
Remove-PSDrive -Name TempDrive | |
"Files copied successfully to $($Params.Destination)" | |
} | |
} | |
} | |
catch { | |
throw "Error on $env:COMPUTERNAME: $_" | |
} | |
} | |
$invokeCommandParams = @{ | |
ScriptBlock = $scriptBlock | |
ComputerName = $ComputerName | |
ArgumentList = $Params | |
ErrorAction = 'Stop' | |
ThrottleLimit = $Params.ThrottleLimit | |
} | |
if ($Params.Credential -and $Params.Credential -ne [System.Management.Automation.PSCredential]::Empty) { | |
$invokeCommandParams.Credential = $Params.Credential | |
} | |
$results = Invoke-Command @invokeCommandParams | ForEach-Object { | |
[PSCustomObject]@{ | |
ComputerName = $_.PSComputerName | |
Status = "Success" | |
Output = $_ | |
} | |
} | |
return $results | |
} | |
try { | |
$remoteHosts = Get-RemoteHosts -ConfigFile $ConfigFile -ComputerName $ComputerName | |
$params = $PSBoundParameters | |
$params.ParameterSet = $PSCmdlet.ParameterSetName | |
if ($params.ParameterSet -eq 'Copy') { | |
$params.Source = $params.Source | ForEach-Object { Resolve-Path -Path $_ -ErrorAction Stop | Select-Object -ExpandProperty Path } | |
} | |
if ($DryRun) { | |
Write-Host "Dry run mode. The following operations would be performed:" | |
foreach ($computer in $remoteHosts) { | |
if ($params.ParameterSet -eq 'Run') { | |
if ($Command) { | |
Write-Host "On $computer, would execute command: $Command" | |
} elseif ($ScriptPath) { | |
Write-Host "On $computer, would execute script: $ScriptPath" | |
} | |
} elseif ($params.ParameterSet -eq 'Copy') { | |
Write-Host "Would copy files from $($params.Source -join ', ') to $($params.Destination) on $computer" | |
} | |
} | |
} else { | |
$results = Invoke-RemoteOperation -ComputerName $remoteHosts -Params $params | |
if ($results) { | |
$results | Format-Table -AutoSize | |
if ($OutputFile) { | |
$results | Export-Csv -Path $OutputFile -NoTypeInformation | |
Write-Host "Results exported to $OutputFile" | |
} | |
} else { | |
Write-Host "No results obtained." | |
} | |
} | |
} | |
catch { | |
Write-Error "An error occurred: $_" | |
exit 1 | |
} | |
finally { | |
# Ensure all jobs are stopped and removed | |
Get-Job | Remove-Job -Force -ErrorAction SilentlyContinue | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment