Reputation: 5423
I have a script which logs via Write-Output and Write-Error, and which calls many other scripts and executables. When I run it directly, I'm happy with what I see in the terminal. But I'd like to additionally capture the two streams to two separate files, while maintaining behavior in the terminal.
This comes close, but the terminal doesn't get stderr:
& .\main.ps1 2> stderr.log | Tee-Object -FilePath stdout.log
I've considered running it as a background task, but I worry that I'd lose the ability to Ctrl-C it easily. My work will be used by many engineers, so I don't want to introduce unexpected behaviors.
Upvotes: 2
Views: 670
Reputation: 437111
# (Re)create the log files.
New-Item stdout.log, stderr.log -Force
# Merge the error stream (2) into the success stream (1) with 2>&1
# Then use the type of the objects to distinguish between
# error-stream output (whose objects are of type [System.Management.Automation.ErrorRecord])
# and success-stream output (all other types).
.\main.ps1 2>&1 | ForEach-Object {
if ($_ -is [System.Management.Automation.ErrorRecord]) { $_ >> stderr.log }
else { $_ >> stdout.log }
$_ # pass through
}
Note: Given that the output files are opened and closed (for appending to via >>
) in every iteration, this solution will be slow.
Upvotes: 1
Reputation: 13412
If you can live with the fact, that both streams land in one file (basically like the view in the terminal), this will do the trick:
& .\main.ps1 2>&1 | Tee-Object -FilePath stdout_and_stderr.log
It redirects stderr
to stdout
and pipes it to Tee-Object
like before.
Upvotes: 2