Question:
I’m using powershell to write and read log files.
One script is generating a log file with Add-Content. Another script is tailing the log file, using Get-Content -Wait. This seems like it should be pretty reliable.
However, the writer is frequently unable to write, and the reader is frequently unable to read and gives up. I can only assume these two commands aren’t opening the file with the appropriate access flags, and so they’re fighting each other.
Here’s a nasty little script that demonstrates the problem with two jobs in the same process, although the same happens between different powershell processes:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
$writer = start-job -ScriptBlock { foreach($i in 1..500) { "$i" | Add-Content "c:\temp\blah.txt" Sleep -Milliseconds 10 } } $reader = start-job -ScriptBlock { Get-Content "c:\temp\blah.txt" -wait } while($writer.State -eq "Running") { Sleep 1 } Sleep 2 "Checking writer" receive-job $writer "Checking reader" receive-job $reader remove-job $writer -force remove-job $reader -force |
On my Windows 7 x64 machine with powershell 3 ISE, I typically get lots of write errors:
1 2 3 4 5 6 |
Checking writer The process cannot access the file 'C:\temp\blah.txt' because it is being used by another process. + CategoryInfo : ReadError: (C:\temp\blah.txt:String) [Get-Content], IOException + FullyQualifiedErrorId : GetContentReaderIOError,Microsoft.PowerShell.Commands.GetContentCommand + PSComputerName : localhost |
And then the file being read has gaps in it:
1 2 3 4 5 6 7 8 9 10 |
Checking reader ... 23 24 25 54 55 56 ... |
NB this is a different problem to the one discussed here: Get-Content -wait not working as described in the documentation and here: https://social.technet.microsoft.com/Forums/windowsserver/en-US/e8ed4036-d822-43d3-9ee5-dd03df3d9bfc/why-doesnt-wait-work-and-why-doesnt-anyone-seem-to-care?forum=winserverpowershell which are about tailing a file which isn’t being closed in between writes.
Is there any way of using Get-Content and Add-Content like this, or should I give up, and use something else to read and write my log files?
Answer:
Try using Out-File instead of Add-Content
Replace
1 2 |
Add-Content "c:\temp\blah.txt" |
With:
1 2 |
Out-File "c:\temp\blah.txt" -Append -Encoding ascii |
You need to specify encoding as ascii with Out-File if that’s what you want, since it’s the default for add-content but not the default for out-file. You also need to to use -append and/or -noclobber to avoid overwriting existing file content.