Como capturar e manipular status de saída diferente de zero dentro de uma função Bash?

3

Digamos que eu tenha a seguinte função de Bash (sem sentido):

myfunc() {
    ls
    failfailfail
    uptime
}

Eu o corro assim:

myfunc || echo "Something is wrong."

O que eu quero que aconteça é que ls é executado (como deveria), failfailfail não funciona (já que não existe) e uptime não é executado. O valor de retorno da função seria diferente de zero e a mensagem de erro seria mostrada. O valor de retorno não precisa ser o status de saída exato do comando com falha, ele não deveria ser zero.

O que realmente acontece é que recebo a saída de ls , seguida de "-bash: failfailfail: comando não encontrado", seguida da saída de uptime . A mensagem de erro não é mostrada, porque o status de saída com falha está sendo comido.

set -e não tem efeito útil, seja dentro da função ou no escopo onde a função é chamada. A única maneira de fazer isso funcionar do jeito que eu quero é:

myfunc() {
    ls || return $?
    failfailfail || return $?
    uptime || return $?
}

Mas isso parece terrivelmente repetitivo e feio. Existe outra maneira de limpar isso?

    
por smitelli 28.04.2016 / 18:15

4 respostas

1

Em set -e , a inexistência de failfailfail faz com que todo o script saia (ou o subshell, se a função for executada em um subshell).

Se você não precisa modificar o estado do shell da função, você pode executá-lo em um subshell.

myfunc() (
    set -e
    ls
    failfailfail
    uptime
)

Outra abordagem no bash é definir uma ERR interceptação para execute return . Se você quiser torná-lo uma configuração local, será necessário restaurar o valor da trap antiga, o que é um pouco complicado.

myfunc() {
    local old_ERR_trap=$(trap -p ERR)
    if [[ -z $old_ERR_trap ]]; then old_ERR_trap="trap - ERR"; fi
    trap 'local ret=$?; eval "$old_ERR_trap"; return $ret' ERR
    ls
    failfailfail
    uptime
}
    
por 29.04.2016 / 02:19
0

A única maneira de simplificar é combinando tudo em um comando, mas isso torna o script mais difícil de manter do que sua última versão:

myfunc() {
    ls && failfailfail && uptime || return $?
}
    
por 28.04.2016 / 18:27
0

Como todos são comandos simples, você pode fazer algo como o seguinte:

myfunc() {
  ls &&
  failfailfail &&
  uptime ||
  return $?
}
    
por 28.04.2016 / 18:34
0

Às vezes, as coisas são melhor colocadas em um Makefile, que lida com esse tipo de coisa.

#!/bin/bash
myfunc() { # watch out for tabs!
        make -f - <<!
default:
        ls -d
        failfailfail
        uptime
!
}
    
por 29.04.2016 / 20:17