Existe um teste simples para qualquer coisa impressa em stderr no shell / Bash?

5

Gostaria de chamar um comando dentro de um script de shell para fins de Integração Contínua. Sair do status 0 significa sucesso, caso contrário, falha. Estou escrevendo um script wrapper para executar vários comandos e falhar se algum erro tiver ocorrido de um deles.

No entanto, um dos comandos (software de terceiros) não está de acordo com o status de saída "de fato"! = 1 na falha. No entanto, ele imprime seus erros no stderr em caso de falha.

Script de wrapper atual, que deve ter funcionado bem se mycommand e other-command falharem com status de saída! = 0 devido à opção -e :

#!/bin/bash -ex
mycommand --some-argument /some/path/to/file
other-command --other-argument /some/other/file

Como faço para verificar se há algo sendo impresso no stderr (para falhar no script principal)? Aqui está o que eu tentei:

  1. redirecionamento de saída do stderr para o arquivo, verifique o conteúdo do arquivo.
    Gostaria de evitar a criação de arquivos temporários.
  2. Redirecionar stderr para subshell stdin, por exemplo:

    mycommand 2> >(if grep .; then echo NOK; else echo OK; fi)
    

    Isso parece funcionar bem, no entanto, não consigo controlar o shell principal aqui para sair, ou seja, exit 1 não sairá do programa principal. Também não posso controlar variáveis fora do subshell para propagar seu resultado. Eu realmente tenho que criar um pipe nomeado ou algo assim?

  3. Configure descritores de arquivos extras, como esta resposta .
    Não parece muito elegante para mim, na verdade.

Alguns "requisitos":

  • Não deve falhar na saída regular no stdout (saída também).
  • Gostaria de manter a saída útil no stdout.
  • Gostaria de manter qualquer saída atualmente em stderr impressa (pode ser stdout, mas não deve ser hidded).

Portanto, ele deve se comportar como um wrapper que só sai com um status sujo, mantendo a saída impressa.

Eu estava apenas esperando que houvesse algo mais elegante para verificar qualquer coisa no stderr. Bascos aceitáveis.

    
por gertvdijk 23.08.2017 / 16:49

2 respostas

2

Você poderia fazer (POSIXly):

if { cmd 2>&1 >&3 3>&- | grep '^' >&2; } 3>&1; then
  echo there was some output on stderr
fi

Ou para preservar o status de saída original se não for zero:

fail_if_stderr() (
  rc=$({
    ("$@" 2>&1 >&3 3>&- 4>&-; echo "$?" >&4) |
    grep '^' >&2 3>&- 4>&-
  } 4>&1)
  err=$?
  [ "$rc" -eq 0 ] || exit "$rc"
  [ "$err" -ne 0 ] || exit 125
) 3>&1

Usando o código de saída 125 para os casos em que o comando retorna com um status de saída 0, mas produz uma saída de erro.

Para ser usado como:

fail_if_stderr cmd its args || echo "Failed with $?"
    
por 23.08.2017 / 18:11
0
# output "NOK" if standard error has any output; "OK" otherwise:
errlog=$(mktemp)
somecommand 1>> "$stdlog" 2> "$errlog"
if [[ -s "$errlog" ]]; then
    # File exists and has a size greater than zero
    echo "NOK"
else
    echo "OK"  
fi
# Done parsing standard error; tack it to the regular log
cat "$errlog" >> "$stdlog"
rm -f "$errlog"
    
por 23.08.2017 / 17:50