Configurando o pipefail para um único comando canalizado

11

Eu preciso executar vários comandos de shell canalizados de um script não-BASH (ou seja, script PHP) como estes:

command1 | command2 | command3

para que, se command1 falhar com um código de saída diferente de zero, o outro comando falhe também. Até agora, o que eu tenho é:

set -o pipefail && command1 | command2 | command3

Mas apesar de funcionar bem no terminal, ele produz isso se executado a partir do script:

sh: 1: set: Illegal option -o pipefail

    
por Desmond Hume 24.11.2012 / 14:46

3 respostas

12

Na linha de comando do Bash, você precisaria invocar um subshell para evitar que pipefail fosse definido posteriormente:

$ (set -o pipefail && command1 | command2 | command3)

Isso limitaria o efeito da opção pipefail à subshell criada pelos parênteses (...) .

Um exemplo real:

$ (set -o pipefail && false | true) && echo pipefail inactive || echo pipefail active
pipefail active

Se você usar uma chamada explícita do shell com a opção -c , não precisará de um subshell, seja com bash ou com um sh alias para bash :

$ bash -c "set -o pipefail && false | true" && echo pipefail inactive || echo pipefail active
pipefail active
$ sh -c "set -o pipefail && false | true" && echo pipefail inactive || echo pipefail active
pipefail active

Como o seu sh não aceita a opção pipefail , eu teria que assumir que é uma versão antiga ou modificada do bash - ou que é realmente algum outro shell completamente.

    
por 24.11.2012 / 19:39
0

Você pode usar $ (command1) combinado com $? :

a=$(echo "a")
[ $? -eq 0 ] && b=$(echo $a"b")
[ $? -eq 0 ] && c=$(echo $b"c")
echo $c

Imprime "abc"

a=$(ls unexitingDir)
[ $? -eq 0 ] && b=$(echo $a"b")
[ $? -eq 0 ] && c=$(echo $b"c")
echo $c

Imprime "".

"[$? -eq 0] & &" significa que o seguinte comando é executado apenas se o anterior suceder.

Isso não responde à sua pergunta, mas é uma solução para o seu problema.

    
por 24.11.2012 / 16:16
0

Não sei por que não foi mencionado acima, mas é possível desabilitar explicitamente pipefail , usando set +o pipefail .

set -o pipefail
command1 | command2 | command3
set +o pipefail

Se você estiver executando um fragmento e não tiver certeza sobre o pipefail já definido, poderá usá-lo com o subshell, como sugerido anteriormente:

# explicitly execute with pipefail set
(set -o pipefail ; command1 | command2 | command3 )
# explicitly execute with pipefail unset
(set +o pipefail ; command1 | command2 | command3 )
    
por 03.10.2018 / 18:43