3

I'm running a server from a batch file and I want the server output to be displayed both on the screen and also written to a log file. I found a way to do this from this answer:

powershell "startmyserver | tee server.log"

The problem is that the pipe causes the first command to run and fully complete before the second command runs. This means I can't monitor my server's stdout while it's actually running, which is what I'm trying to do (I don't want to have to shut down the server just to check the most recent log messages).

For a more simple example I tried pause. Well, pause doesn't exist on Powershell, so I had to run it inside a nested cmd shell:

powershell "cmd /c pause | tee test.txt"

Unsurprisingly, after executing this command I just get a flashing cursor. After a while, I press a key, and then "Press any key to continue" appears and is written to the file at nearly the same time.

What I want to happen is the pipe to stream the stdout line by line to the next command. In other words whenever it encounters an EOL character it should send some output and this should (in my case of tee) cause the text to appear on the screen and simultaneously written to the file. (In fact, I'm even not bothered about whether the text is written to the file line-by-line, it could be written all at the end although that would not be ideal. I just want to be able to see the lines on the screen as they are written.)

Is this possible in Command Prompt and/or Powershell?

Kidburla
  • 573

1 Answers1

2

This problem is explained on Stack Overflow as the fact that the PowerShell Tee-Object doesn't flush the output stream, but only waits for the source to do it, so you get the output at the end of the operation. This is by design.

The workaround proposed in the answer was to use this code:

./program | ForEach-Object {
    Write-Host $_
    $_
} | Set-Content program.log

An alternative formulation to try if the above one didn't work is:

./program | ForEach-Object {
    [Console]::WriteLine($_)
    [Console]::Out.Flush()
    $_
} | Set-Content program.log

So the command would look like :

PowerShell -ExecutionPolicy Unrestricted "startmyserver | ForEach-Object { Write-Host $_; $_} | Set-Content server.log"

In my modest testing the output was generated too fast for me to see if this worked as you specified.

harrymc
  • 498,455