I have an active production log file which deletes the contents of the logs after the file hits the size limit of 1 GB and also zips the file at every midnight thus in every day's zipped file, we do not have the complete log traffic for whole day. What we have is just the logs from the time it last hit 1 GB, till midnight of that day.
I am trying to watch that file and copy the contents of that file to some other file real-time. Upon some research, I came to know about FileSystemWatcher
and tried several variations however could not append the contents of the file to another file.
With the following script, I am able to get the message displayed on the console. However, I am not able to append the contents to another file.
So, what I am trying to achieve is, whenever the XML file is changed, a real-time sync happens between the log file and some other file (Which I will create with this script) so that at the end of the day, I have a complete log file. Since this is a production system (about to be retired), it's quite busy so I am trying to implement a real-time sync solution.
$folder = "C:\Users\hslasw\docs\Log_Truncation_Issue"
$filter = "*.xml"
$Watcher = New-Object IO.FileSystemWatcher $folder, $filter -Property @{
IncludeSubdirectories = $false
NotifyFilter = [IO.NotifyFilters]'FileName, LastWrite'
}
$onChanged = Register-ObjectEvent $Watcher -EventName Changed -SourceIdentifier FileChanged -Action {
$path = $Event.SourceEventArgs.FullPath
$name = $Event.SourceEventArgs.Name
$changeType = $Event.SourceEventArgs.ChangeType
$timeStamp = $Event.TimeGenerated
$filename = $path
Write-Host (Get-Content -Path $path) |
Out-File -Encoding Ascii -FilePath -Append C:\Users\xxxx\docs\Log_Truncation_Issue_Destination\testfile.xml
}
# Unregister-Event FileChanged
This is where the issue is:
Write-Host (Get-Content -Path $path) |
Out-File -Encoding Ascii -FilePath -Append C:\Users\xxxx\docs\Log_Truncation_Issue_Destination\testfile.xml
Is there a better approach? Splitting the log file so it never reaches 1 GB is not possible in my situation. Also to note, the APP cannot be modified to change the logging behavior. I also considered rsync
since it's an inbuilt tool. However, I need to pass the file name as a variable which doesn't seem to be supported by rsync
.
Write-Host
output goes directly to the host console, so the output does not go into the pipeline. Remove the Write-Host
, and also remove the parentheses (as for what you want to do you don't need to read the file into memory first). The parameter order of your Out-File
statement is incorrect too. The path argument belongs to the -FilePath
parameter.
$onChanged = Register-ObjectEvent $Watcher -EventName Changed -SourceIdentifier FileChanged -Action {
$path = $Event.SourceEventArgs.FullPath
$name = $Event.SourceEventArgs.Name
$changeType = $Event.SourceEventArgs.ChangeType
$timeStamp = $Event.TimeGenerated
Get-Content -Path $path |
Out-File -FilePath 'C:\path\to\output.xml' -Encoding Ascii -Append
}
Also, beware that you cannot simply append to an XML file, as that would produce invalid XML. If you need to add data from one XML file to another XML file you should use PowerShell's XML parser. However, that would be a different question and should be asked as such.