Existe uma maneira de redirecionar a saída para um arquivo sem armazenar em buffer no unix / linux?

49

Eu tenho um processo em lote de longa execução que gera algumas informações de depuração e processo para o stdout. Se eu apenas correr de um terminal, posso rastrear 'onde está', mas os dados ficam demais e rolam para fora da tela.

Se eu redirecionar para a saída para um arquivo '> out.txt', obtenho a saída inteira eventualmente, mas ela é armazenada em buffer, para que eu não possa mais ver o que está fazendo no momento.

Existe uma maneira de redirecionar a saída, mas fazer com que ela não armazene em buffer suas gravações?

James Dean
fonte
11
Você poderia, por favor, dar uma olhada no meu "debate" (e no @cnst) abaixo, acho que a única coisa que você deseja é ver a saída ao mesmo tempo em que a registra em um arquivo. Se você encontrou uma solução, informe-nos;)!
Benj
2
pergunta mais votada unix.stackexchange.com/questions/25372
Trevor Boyd Smith

Respostas:

52

Você pode definir explicitamente as opções de buffer dos fluxos padrão usando uma setvbufchamada em C (consulte este link ), mas se estiver tentando modificar o comportamento de uma tentativa de programa existente stdbuf(parte da coreutilspartida da versão 7.5 aparentemente).

Isso armazena stdoutem buffer até uma linha:

stdbuf -oL command > output

Isso desativa stdoutcompletamente o buffer:

stdbuf -o0 command > output
Eduardo Ivanec
fonte
aaarghhh ... Meu Ubuntu tem apenas 7,4 coreutils ... :(
Calmarius
@ Calmarius: compilar coreutils deve ser bastante fácil. Basta pegar uma nova versão em ftp.gnu.org/gnu/coreutils e experimentar . É ./configure && maketarifa padrão . Você nem precisa instalá-lo depois, basta usar o stdbufbinário desativado src/.
Eduardo Ivanec
argh duplo. Eu preciso disso em um velho centos distro e OSX, bem como no Ubuntu.
Edk750
resposta mais votada, unix.stackexchange.com/a/25378/5510
Trevor Boyd Smith,
Existe uma maneira de forçar os buffers pipe / printf externamente para o processo em execução com PID conhecido?
Mvorisek
9

Você pode obter saída com buffer de linha para um arquivo usando o scriptcomando da seguinte maneira:

stty -echo -onlcr   # avoid added \r in output
script -q /dev/null batch_process | tee output.log        # Mac OS X, FreeBSD
script -q -c "batch_process" /dev/null | tee output.log   # Linux
stty echo onlcr
fundidor
fonte
-1 porque: a) diferentemente da resposta aceita, isso não funciona se você deseja executar o comando em segundo plano (o comando termina imediatamente sem concluir batch_processse você anexa &ao comando acima, pelo menos na minha caixa Linux), o que parece como um caso de uso extremamente comum eb) não há explicação aqui sobre como esse encantamento funciona.
Mark Amery
8

No Ubuntu, o pacote do unbufferprograma (o expect-dev) fez o truque para mim. Apenas corra:

unbuffer your_command

e não vai amortecê-lo.

Calmarius
fonte
6

A solução mais fácil que encontrei (não precisava de pacotes de terceiros instalados) foi mencionada em um tópico semelhante no site do Unix e Linux : use o scriptcomando É antigo e provavelmente já está instalado.

$ script -q /dev/null long_running_command | print_progress       # FreeBSD, Mac OS X
$ script -q -c "long_running_command" /dev/null | print_progress  # Linux

Observe que o primeiro parâmetro de nome de arquivo para o scriptcomando é o arquivo de log a ser gravado . Se você simplesmente executar script -q your_command, substituirá o comando que recuou para executar com o arquivo de log. Verifique man script, para estar seguro, antes de tentar.

Steve HHH
fonte
4

tente o scriptcomando; se o seu sistema possui, ele recebe um nome de arquivo como argumento, todo o texto despejado no stdout é copiado para o arquivo. É muito útil quando um programa de instalação requer interação.

Chris S
fonte
Eu sei do truque 'script -a out.txt'. Fiquei me perguntando se existe alguma outra maneira de tornar o processo de gravação sem buffer.
James Dean
3

Pessoalmente, prefiro canalizar a saída de um comando que quero examinar tee.

scriptregistra muitas informações, incluindo o tempo das teclas pressionadas e muitos caracteres não imprimíveis. O que teeeconomiza é muito mais legível para mim.

Paweł Brodacki
fonte
Eu também adicionaria "| less" à linha de comando.
HUB
4
Tenho certeza de que isso também teeé afetado pelo buffer. Frequentemente, ainda recebo linhas parciais exibidas por tee ao dividir a saída dos findcomandos.
Magellan
2

Redirecione a saída para um arquivo e siga o arquivo com o tail -fcomando

Editar

Se isso ainda sofrer buffer, use o recurso syslog (que geralmente é sem buffer). Se o processo em lote for executado como um script de shell, você poderá usar o comando logger para fazer isso. Se o trabalho em lotes for executado em uma linguagem de script, deve haver um recurso de registro de qualquer maneira.

wolfgangsz
fonte
3
É isso que eu faço agora, mas o processo armazena em buffer a gravação no arquivo e é exatamente isso que eu quero evitar.
James Dean
Veja minha edição para uma proposta atualizada.
27611 Wolfgangsz
11
Isso não funciona por razões óbvias. Quem diabos dá This answer is usefulrespostas que não funcionam e que não podem funcionar?
CNST
1

Você pode usar o teecomando, apenas mágica!

someCommand | tee logFile.logserá tanto visor no console e escrever no arquivo de log.

Benj
fonte
Não funciona teenão impedirá a realização de buffer.
CNST
11
@cnst Efetivamente, teenão evitará alguns buffers, mas apenas permitirá que você dê uma olhada no que é a saída. Era isso que @JamesDean queria (como eu subestime sua pergunta), mas acho que o buffer não é realmente o problema aqui. Se você tiver mais detalhes, me avise.
Benj
Ele queria ver a saída, e ele não está obtendo nenhuma saída (de uma maneira sem buffer), e ainda assim você sugere usar teepara obter uma melhor visualização da saída que não está recebendo?
CNST
11
Como eu redijo a pergunta @JamesDean: "Eu redireciono para a saída para um arquivo '> out.txt'" significa para mim nenhuma saída do console, aguarde a conclusão do processo enquanto toda a saída é redirecionada. Quando você está usando >, não vê nada no console. Eu acho que @ JamesDean está usando a palavra "buffering" para descrever isso. Vou postar um comentário em sua pergunta para ele dizer mais sobre o que ele quer.
Benj