Existe uma orientação oficial POSIX, GNU ou outra orientação sobre onde os relatórios de progresso e as informações de registro (coisas como "Fazendo o foo; o foo feito") devem ser impressos? Pessoalmente, costumo escrevê-los no stderr para poder redirecionar o stdout e obter apenas a saída real do programa. Recentemente me disseram que isso não é uma boa prática, pois os relatórios de progresso não são realmente erros e apenas as mensagens de erro devem ser impressas no stderr.
Ambas as posições fazem sentido e, é claro, você pode escolher uma ou outra, dependendo dos detalhes do que está fazendo, mas eu gostaria de saber se existe um padrão comumente aceito para isso. Não consegui encontrar nenhuma regra específica no POSIX, nos padrões de codificação GNU ou em qualquer outra lista de boas práticas amplamente aceita.
Temos algumas perguntas semelhantes, mas elas não abordam exatamente esse problema:
Quando usar o redirecionamento para stderr em scripts de shell : A resposta aceita sugere o que eu costumo fazer, mantenha a saída final do programa em stdout e qualquer outra coisa em stderr. No entanto, isso é apresentado apenas como uma opinião do usuário, embora apoiada por argumentos.
A mensagem de uso deve ir para stderr ou stdout? : Isso é específico para ajudar mensagens, mas cita o padrão de codificação GNU. Esse é o tipo de coisa que estou procurando, mas não restrito a ajudar apenas as mensagens.
Portanto, existem regras oficiais sobre onde os relatórios de progresso e outras mensagens informativas (que não fazem parte da produção real do programa) devem ser impressos?
stdout
juntamente com os resultados, é uma maneira segura de tornar os resultados inúteis. Se você precisar canalizar os resultados para outro programa, esse programa precisará separar os resultados dos giradores. Além disso, se você redirecionar a saída para um arquivo, não poderá ver os giradores. NA MINHA HUMILDE OPINIÃO.stdout
é realmente uma maneira segura e correta de extrair spinners e outras mensagens informativas, mas, como muitos programadores dizem, 'O silêncio é ouro. Não produza nada se estiver tudo bem. Então, na verdade, stderr é sempre usado para fazer isso por causa da definição vaga e também StdOut pode quebrar o tubo sequence.for guia oficialstderr
para relatar mensagens de erro, exceto quando um--verbose
sinalizador é usado, momento em que os relatórios de progresso também são incluídos.Respostas:
O Posix define os fluxos padrão assim :
A GNU C Library descreve os fluxos padrão da mesma forma:
Portanto, as definições padrão têm pouca orientação para o uso do fluxo além da "saída convencional / normal" e da "saída de diagnóstico / erro". Na prática, é comum redirecionar um ou ambos os fluxos para arquivos e pipelines, onde os indicadores de progresso serão um problema . Alguns sistemas até monitoram
stderr
a saída e a consideram um sinal de problemas. Informações de progresso puramente auxiliares são, portanto, problemáticas em qualquer fluxo.Em vez de enviar indicadores de progresso incondicionalmente para qualquer fluxo padrão, é importante reconhecer que a saída do progresso é apropriada apenas para fluxos interativos . Com isso em mente, recomendo escrever contadores de progresso somente após verificar se o fluxo é interativo (por exemplo, com
isatty()
) ou quando ativado explicitamente por uma opção de linha de comando. Isso é especialmente importante para que os medidores de progresso que dependem do comportamento de atualização do terminal façam sentido, como barras com% concluído.Para certas mensagens de progresso muito simples ("Iniciando X" ... "Concluído com X"), é mais razoável incluir a saída mesmo para fluxos não interativos. Nesse caso, considere como os usuários podem interagir com os fluxos, como pesquisar com
grep
ou paginar comless
ou monitorar comtail -f
. Se fizer sentido ver as mensagens de progresso nesses contextos, elas serão muito mais fáceis de consumirstdout
.fonte
N% done
e comodoing foo
efoo done
. O último deve sempre ser mantido, pois é usado para depuração quando redirecionado para um arquivo. Portanto, sua sugestão de verificar se o fluxo é interativo não é aplicável (embora geralmente seja uma boa ideia).curl
eyum
. Nesse caso, eu pensaria se e como o usuário gostaria de interagir com a saída por meio degrep
ouless
ferramentas semelhantes.POSIX define erro padrão como
Isso não limita seu uso apenas a mensagens de erro. Eu consideraria as informações de progresso como saída de diagnóstico, portanto elas pertencem ao erro padrão.
fonte
stdout
é buffer de linha por padrão, enquanto nãostderr
é armazenado em buffer, assimstderr
como a escolha natural para escrever textos / barras / giradores de progresso que não contenham uma nova linha. (Se você escrever esse texto,stdout
precisará desorganizar as chamadas de saída de progressostdout.flush()
para torná-lo visível).stdout
, você precisa liberar mesmo que seu texto não conter uma nova linha se você quiser que os seus relatórios de progresso para mostrar realmente em tempo real quando redirecionado.O POSIX é um pouco mais concreto sobre "informações de diagnóstico" no Shell e Utilitários , 1.4: Padrões de Descrição do Utilitário (ênfase minha):
IANASL, mas interpreto que isso signifique que o stderr terá saída apenas se o utilitário retornar um código de saída de erro. Como esse não deve ser o curso normal dos eventos para uma execução bem-sucedida, nenhuma informação de progresso deve ser impressa por um utilitário POSIX, a menos que ocorra um erro (a menos que, é claro, se especificado de outra forma, etc.).
fonte
Pelo princípio da exclusão, ele só pode ir para o stderr. Sim, eu sei que você perguntou sobre uma especificação oficial, que não posso apresentar além do link para a especificação POSIX, fornecida por Stephen Kitt, que afirma que stderr é para fins de diagnóstico.
O ponto mais importante é que stdin e stdout têm uma função que desaprova a impressão de relatórios de progresso para stdout - eles naturalmente formam a sequência de pipes que, nos comandos shell do Unix, não é apenas um efeito colateral, mas o cerne da poderosa abordagem de pipelining .
Assim. Nada, exceto a "carga útil" real do seu programa, pertence ao stdout. Se o seu programa não tiver saída, nada deve ser levado ao stdout. Isso deixa o stderr para todo o resto , incluindo relatórios de progresso.
É verdade que isso deixa um buraco - provavelmente seria bom ter um "stdfluff" ou algo parecido que não serve para saída nem erros, mas para relatórios de progresso, depuração e algo assim. De fato, nada impede você de fazer isso, ou seja, você pode imprimir seu progresso no descritor de arquivo 3. Exemplo:
Isso não produz saída. (*)
Isso imprime em fd-3, que é redirecionado para stdout.
(*) O primeiro exemplo não produz saída, mas ainda é um pouco rebuscado; a
open
falha e$!
conteriano such file or directory
; apenas tome isso como um exemplo, é claro que não deve ser usado dessa maneira a sério. Em um programa real, se você quiser seguir esse caminho, poderá testar se/dev/fd/3
é utilizável e usar isso como uma dica para ativar seus relatórios de progresso; você teria que fazer isso bem cedo para não se confundir com seus própriosopen
arquivos reais e coisas assim ...fonte
fd-3
? O terceiro disquete?A mensagem de uso deve ir para stdout se o usuário a tiver chamado
--help
e stderr se tiver cometido um erro. Imprimir no stderr incondicionalmente é desagradável, pois torna mais difícil visualizá-lo com um pager / grep / etc.Além disso, posso sugerir uma terceira maneira: abra / dev / tty para relatórios de progresso / spinners / etc.
fonte
--help
nem ajudando mensagens. Por favor, leia novamente a pergunta.