Você poderia elaborar o ato de forma diferente como parte de sua pergunta?
precisa saber é
Você tem controle limitado sobre o quanto prog2progrediu quando as prog1saídas são devido ao buffer interno usado para implementar o canal e como prog1e prog2está programado.
chepner
Também olhar para [Em que ordem fazer comandos canalizada correr?] (Unix.stackexchange.com/q/37508)
DK Bose
Respostas:
4
A resposta geral é não. É possível prog2sair antes prog1mesmo do início (obviamente isso não pode acontecer se, prog2na verdade, você ler alguma entrada, o que você esperaria que estivesse fazendo se estiver usando em um pipeline). Definitivamente, é possível prog2sair antes prog1; isso acontece, por exemplo, quando prog2é um programa de pesquisa que sai assim que encontra uma correspondência, caso em que prog1ainda não terminou de produzir todos os dados.
Não há uma maneira direta prog2de recuperar o status de saída prog1ou até mesmo saber que prog1saiu. Tudo o que prog2podemos saber é que prog1fechou a extremidade do tubo, o que pode ser feito sem morrer.
Se você quiser obter o status de saída prog1de prog2, há dois métodos comuns: você pode escrevê-lo em um arquivo, ou você pode enviá-lo através do tubo. Enviar o status de saída como a última linha dos dados canalizados é uma possibilidade. Você deve certificar-se de não processar a última linha até saber que é a última linha, ou seja, até tentar ler a próxima linha.
{ prog1; echo $?;}|…
Aqui está um exemplo em que o lado direito é um filtro de texto que colore todas as linhas que contêm a palavra "erro" em vermelho. Se o lado esquerdo falhar, o lado direito sai com o mesmo status.
{ prog1; echo $?;}| awk '
NR != 1 {
if (line ~ /[Ee][Rr][Rr][Oo][Rr]/) print "\033[31m" line "\033[0m";
else print line;
}
{line = $0}
END {exit($0)}
'
Eu estava tentando fazer { command; echo ${PIPESTATUS[@]}; } | sort | ...com que o status de saída fosse o primeiro no fluxo. É tudo muito interessante!
@ illuminÉ Isso só funcionaria se ${PIPESTATUS[@]}for classificado antes de qualquer outra coisa na saída de command. Se commandimprimir vários números ou se puder imprimir texto arbitrário, você estará com problemas: não será possível distinguir sua saída da linha de status.
Gilles 'SO- stop be evil'
Obrigado, na verdade, ele só consegue classificar um status de sucesso para o topo se o comando não contiver 0 em sua saída lol. Tgif / s.
2
Embora você possa, em alguns casos especiais (ver as outras respostas), não é possível em todos os casos. Alguns programas de filtro continuam, enquanto outros retêm toda a saída, liberam-na em uma única explosão e saem.
Para um exemplo de um programa "apenas continue", grepo servidor irá, como faria tail -f /var/log/some_log_file. O uso sortem um pipeline causa uma "paralisação", pois sortele coletará entradas até que o cano na frente dele se feche. O uso xargsadiciona uma complicação adicional: os programas iniciados por xargs(podem iniciar várias instâncias) fazem parte do pipeline ou não?
-1 porque você foi votado por racionalizar uma resposta incorreta.
ctrl-alt-Delor
@richard Huh? A resposta de Bruce está correta (embora o segundo parágrafo seja um pouco confuso).
Gilles 'SO- stop be evil'
1
A resposta: não diretamente.
@terdon ilustrou que o código de saída do comando anterior no canal deve ser enviado como um parâmetro explícito para o próximo comando.
Lembre-se de que o canal é apenas um mapeamento do STDOUT do comando anterior para o STDIN do próximo comando; os códigos de saída não são enviados para STDOUT (ou STDERR).
-1 porque você foi votado por citar uma resposta incorreta e não dizer muito mais.
ctrl-alt-Delor
bastante justo @ Richard ... Eu deveria ter checado duas vezes ... foi o que aconteceu, se eu me forço a responder a uma pergunta, quando muito cansado ...
pepoluan
1
Todo o processo, no pipeline, é iniciado antes de qualquer saída. Portanto, prog2poderia ter que obter essas informações depois de ter iniciado, também teria que adiar o processamento até prog1sair, isso poderia parar o tubo. Parece haver problemas fundamentais ao fazer o que você pede, não limitações do sistema operacional.
Você provavelmente precisa considerar um arquivo temporário ou colocar o resultado em uma variável.
Exemplo para pequena quantidade de dados, usando uma variável
tmp=$(prog1)if test "z$PIPESTATUS"=="z0"then…else…fi
Há uma lacuna no seu raciocínio. prog2é iniciado antes da prog1conclusão em geral, mas pode haver uma maneira de receber o status de saída prog1enquanto estiver em execução.
prog2
progrediu quando asprog1
saídas são devido ao buffer interno usado para implementar o canal e comoprog1
eprog2
está programado.Respostas:
A resposta geral é não. É possível
prog2
sair antesprog1
mesmo do início (obviamente isso não pode acontecer se,prog2
na verdade, você ler alguma entrada, o que você esperaria que estivesse fazendo se estiver usando em um pipeline). Definitivamente, é possívelprog2
sair antesprog1
; isso acontece, por exemplo, quandoprog2
é um programa de pesquisa que sai assim que encontra uma correspondência, caso em queprog1
ainda não terminou de produzir todos os dados.Não há uma maneira direta
prog2
de recuperar o status de saídaprog1
ou até mesmo saber queprog1
saiu. Tudo o queprog2
podemos saber é queprog1
fechou a extremidade do tubo, o que pode ser feito sem morrer.Se você quiser obter o status de saída
prog1
deprog2
, há dois métodos comuns: você pode escrevê-lo em um arquivo, ou você pode enviá-lo através do tubo. Enviar o status de saída como a última linha dos dados canalizados é uma possibilidade. Você deve certificar-se de não processar a última linha até saber que é a última linha, ou seja, até tentar ler a próxima linha.Aqui está um exemplo em que o lado direito é um filtro de texto que colore todas as linhas que contêm a palavra "erro" em vermelho. Se o lado esquerdo falhar, o lado direito sai com o mesmo status.
fonte
{ command; echo ${PIPESTATUS[@]}; } | sort | ...
com que o status de saída fosse o primeiro no fluxo. É tudo muito interessante!${PIPESTATUS[@]}
for classificado antes de qualquer outra coisa na saída decommand
. Secommand
imprimir vários números ou se puder imprimir texto arbitrário, você estará com problemas: não será possível distinguir sua saída da linha de status.Embora você possa, em alguns casos especiais (ver as outras respostas), não é possível em todos os casos. Alguns programas de filtro continuam, enquanto outros retêm toda a saída, liberam-na em uma única explosão e saem.
Para um exemplo de um programa "apenas continue",
grep
o servidor irá, como fariatail -f /var/log/some_log_file
. O usosort
em um pipeline causa uma "paralisação", poissort
ele coletará entradas até que o cano na frente dele se feche. O usoxargs
adiciona uma complicação adicional: os programas iniciados porxargs
(podem iniciar várias instâncias) fazem parte do pipeline ou não?fonte
A resposta: não diretamente.
@terdon ilustrou que o código de saída do comando anterior no canal deve ser enviado como um parâmetro explícito para o próximo comando.
Lembre-se de que o canal é apenas um mapeamento do STDOUT do comando anterior para o STDIN do próximo comando; os códigos de saída não são enviados para STDOUT (ou STDERR).
fonte
Todo o processo, no pipeline, é iniciado antes de qualquer saída. Portanto,
prog2
poderia ter que obter essas informações depois de ter iniciado, também teria que adiar o processamento atéprog1
sair, isso poderia parar o tubo. Parece haver problemas fundamentais ao fazer o que você pede, não limitações do sistema operacional.Você provavelmente precisa considerar um arquivo temporário ou colocar o resultado em uma variável.
Exemplo para pequena quantidade de dados, usando uma variável
fonte
prog2
é iniciado antes daprog1
conclusão em geral, mas pode haver uma maneira de receber o status de saídaprog1
enquanto estiver em execução.Para finalizar a resposta de Gilles ,
é uma abordagem.
prog2
poderia/tmp/prog1.status
ou/tmp/prog1.status
periodicamente enquanto lê a entrada padrão.fonte