Reputation: 322
I am trying to write logs to a single log file using the PSlogging PowerShell module.
The Script is using the Foreach-object parallel.
The script works, But sometimes the script gets stuck in between.
Please help me to resolve it? Is there a better way to achieve this?
Powershell core 7
#Script Version
$sScriptVersion = '1.0'
$sScriptVersion = '1.0'
$sLogName = 'custom.log'
#Log File Info
$sLogPath = "C:\Users\Dixon\Desktop\automation\azure\log"
$sLogFile = Join-Path -Path $sLogPath -ChildPath $sLogName
Start-Log -LogPath $sLogPath -LogName $sLogName -ScriptVersion $sScriptVersion
$allServers = $(Get-AzVM -Status)
try {
$allServers | ForEach-Object -parallel {
$sScriptVersion = '1.0'
$sLogName = "parallel-" + $_.Name +".log"
#Log File Info
$sLogPath = "C:\Users\Dixon\Desktop\automation\azure\log"
$sLogFile = Join-Path -Path $sLogPath -ChildPath $sLogName
Import-Module .\modules\pwshAzMod\pwshAzMod.psd1 -Force
$version = "1.0.11"
$vmName = $_.Name
$vmLocation = $_.Location
$vmResourceGroupName = $_.ResourceGroupName
$powerState = $_.PowerState | Out-String
if ($powerState -match "running") {
if ($_.OSProfile.WindowsConfiguration) {
Write-LogInfo -LogPath $sLogFile -Message "Start --- Windows Servers --- $vmResourceGroupName $vmLocation $vmName $version $powerState"
Write-LogInfo -LogPath $sLogFile -Message "Done --- Windows Servers --- $vmResourceGroupName $vmLocation $vmName $version"
}
elseif ($_.OSProfile.LinuxConfiguration) {
$extensionName = "CustomScript"
Write-LogInfo -LogPath $sLogFile -Message "Start --- Linux Servers --- $vmResourceGroupName $vmLocation $vmName $version $powerState"
Write-LogInfo -LogPath $sLogFile -Message "Done --- Linux Servers --- $vmResourceGroupName $vmLocation $vmName $version"
}
else {
Write-LogInfo -LogPath $sLogFile -Message "OS Type not handled"
}
}
else {
if ($_.OSProfile.WindowsConfiguration) {
Write-LogInfo -LogPath $sLogFile -Message "Deallocated --- Windows Servers --- $vmResourceGroupName $vmLocation $vmName $version $powerState"
}
elseif ($_.OSProfile.LinuxConfiguration) {
Write-LogInfo -LogPath $sLogFile -Message "Deallocated --- Linux Servers --- $vmResourceGroupName $vmLocation $vmName $version $powerState"
}
else {
Write-LogInfo -LogPath $sLogFile -Message "Deallocated --- Other Servers --- $vmResourceGroupName $vmLocation $vmName $version $powerState"
}
}
} -ThrottleLimit 5
}
catch {
$errorMessage = $_
$errorMessage
}
finally {
Get-Content $sLogPath/parallel-*.log | Add-Content $sLogFile
Remove-Item –path $sLogPath\* -Filter parallel*
Stop-Log -LogPath $sLogFile
}
Upvotes: 0
Views: 1810
Reputation: 27423
It won't be in order unless you sort it:
1..10 | foreach-object -Parallel { sleep 1;$_ } | set-content file.txt
Upvotes: 1
Reputation: 883
I stumbled upon this via google and didn't like any of the solutions I found, so I made up my own for logging that you might want to try. This example is how to write to a text file in the current directory safely in a foreach parallel loop:
$tw = [System.IO.TextWriter]::Synchronized([System.IO.File]::AppendText("$PSScriptRoot\log.txt"))
0..100 | Foreach-Object -Parallel {
$writer = $Using:tw
$writer.WriteLine("hello $_")
}
$tw.Close()
Optionally wrap the whole thing in a try/finally with the $tw.Close() in the finally block to ensure that the log file buffer gets flushed and then closed if the script is interrupted.
The TextWriter object handles the locking for you and works just like a StreamWriter object. Note that this is assuming you aren't trying to also read from the file in any of the threads, for that you'd need something a lot more complex.
Upvotes: 2