Saída de tubulação de linha de comando por linha no Windows

2

Estou executando um servidor a partir de um arquivo em lotes e quero que a saída do servidor seja exibida na tela e também gravada em um arquivo de log. Eu encontrei uma maneira de fazer isso com esta resposta :

powershell "startmyserver | tee server.log"

O problema é que o canal faz com que o primeiro comando seja executado e completamente concluído antes da execução do segundo comando. Isso significa que não consigo monitorar o stdout do meu servidor enquanto ele estiver em execução, e é isso que estou tentando fazer (não quero desligar o servidor apenas para verificar as mensagens de log mais recentes).

Para um exemplo mais simples, tentei pause. Bem, pausenão existe no Powershell, então tive que executá-lo dentro de um cmdshell aninhado :

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

Sem surpresa, depois de executar este comando, recebo um cursor piscando. Depois de um tempo, pressiono uma tecla e, em seguida, "Pressione qualquer tecla para continuar" aparece e é gravado no arquivo quase ao mesmo tempo.

O que eu quero que aconteça é o canal para transmitir o stdout linha por linha para o próximo comando. Em outras palavras, sempre que encontrar um caractere EOL, ele deverá enviar alguma saída e isso (no meu caso tee) fará com que o texto apareça na tela e seja gravado simultaneamente no arquivo. (Na verdade, eu nem me preocupo em saber se o texto está escrito no arquivo linha por linha, ele pode ser escrito no final, embora isso não seja o ideal. Eu só quero poder ver as linhas na tela como estão escritos.)

Isso é possível no prompt de comando e / ou no PowerShell?

Kidburla
fonte
@PimpJuiceIT Acho que isso importa com as posições de aspas duplas. Se você executa, powershell cmd /c pause | tee "test.txt"está executando o tee no seu contexto atual. Como estou executando isso no cmd (não no ps1), esse comando falhará, como teeé um comando do PowerShell. se esse comando funcionou para você, presumo que (a) você tenha outro teeno seu sistema ou (b) você o executou no Powershell. Nenhum dos quais é o meu caso de uso.
Kidburla
@PimpJuiceIT você tem outro exemplo de comando que eu poderia usar em vez de pause? I utilizado pauseapenas por conveniência, porque eu não queria um comando que iria encerrar imediatamente e, portanto, torná-lo impossível dizer se as linhas foram transmitidos antes do comando foi concluído
Kidburla
Talvez durma, talvez, mas parece que você encontrou uma solução funcional, então está tudo discutido agora.
Pimp Juice IT

Respostas:

1

Esse problema é explicado no Stack Overflow como o fato de o PowerShell Tee-Objectnão liberar o fluxo de saída, mas espera apenas pela origem, para que você obtenha a saída no final da operação. Isso ocorre por design.

A solução proposta na resposta foi usar este código:

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

Uma formulação alternativa para tentar se a acima não funcionou é:

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

Portanto, o comando seria semelhante a:

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

No meu teste modesto, a saída foi gerada muito rápido para eu ver se isso funcionava como você especificou.

harrymc
fonte
Obrigado! Você tem alguma idéia de como (a) fazer isso escrever stdout e stderr, (b) anexar a um arquivo que já existe, em vez de criar um novo?
Kidburla #
1
Veja este post .
#
Obrigado, e eu consegui resolver parte (b), utilizando Add-Content, em vez deSet-Content
Kidburla