stderr é liberado antes do stdout, ao usar o registrador de arquivos

2

Meu código python:

import sys
print "i am a daemon"
print "i will be run using nohup"
sys.stderr.write("i am an error message inside nohup process\n")

Quando executo o código como python a.py , ele mostra

i am a daemon
i will be run using nohup
i am an error message inside nohup process

Quando executo o código como nohup python a.py > a.log 2>&1 < /dev/null & , a.log mostra,

i am an error message inside nohup process
i am a daemon
i will be run using nohup

Por que os logs stderr são liberados / gravados antes dos logs stdout ao usar nohup ?

    
por Madhavan Kumar 29.05.2015 / 03:27

2 respostas

7

Eu não acho que tenha algo a ver com nohup . Você obtém o mesmo comportamento quando executa python a.py > a.log 2>&1 .

O Python provavelmente está usando o arquivo C stdio abaixo. Com isso, stdout , quando em um terminal, será armazenado em buffer de linha e armazenado em buffer quando stdout for um arquivo. stderr está sempre sem buffer.

Redirecionar stdout para um arquivo alternará o armazenamento em buffer de stdout do buffer de linha para o buffer e fará com que a sequência print ed fique presa no buffer, que só é liberada quando o programa (o fluxo) fecha. O fluxo stderr chega ao arquivo mais rápido porque não está bufferizado.

Você pode usar stdbuf para ajustar o buffer padrão, forçando as linhas a serem impressas na ordem correta:

stdbuf -o0 python a.py  >a.log 2>&1
    
por 29.05.2015 / 03:42
3

Esse é um comportamento normal para fluxos de saída na maioria dos idiomas: eles são armazenados em buffer , ou seja, write realmente grava em um buffer na memória e esse buffer é gravado no fluxo em lotes. O padrão é armazenado em buffer ao gravar em um terminal (ou seja, uma gravação real ocorre toda vez que uma nova linha é impressa), mas totalmente armazenada em buffer (os dados são gravados na memória até que o buffer fique cheio) ao gravar em um arquivo normal ou em um pipe. Stderr é unbuffered ou line buffered.

No Python, você pode escolher o tipo de buffer ao abrir um arquivo, mas não para os fluxos padrão. Se você quiser que todos os fluxos sejam sem buffer, defina a variável de ambiente PYTHONUNBUFFERED para forçar os fluxos padrão a serem unbuffered. Como alternativa, você pode executar o programa em stdbuf ou unbuffer .

Mas se o seu programa não emitir saída em uma ordem apropriada quando o stdout for redirecionado, isso é um defeito no programa, que você deve corrigir. Em particular, se você emitir uma mensagem de erro relacionada à saída gravada no stdout, deverá liberar a stdout primeiro:

print some_data
if errro_condition():
    file.stdout.flush()
    sys.stderr.write('Bad stuff happened\n')
    
por 29.05.2015 / 23:59