sai sem terminar o script [duplicado]

7

exit não finaliza o script quando o erro é chamado ..

saída

Error: Could not resolve localhost
after exit

script

#!/bin/sh

resolve_ip (){
    if [ -z "$1" ]; then
        host="localhost"
        ip=$(dig +short myip.opendns.com @resolver1.opendns.com)
    else
        host="$1"
        ip=$(dig +short $1)
    fi

    if [ -z "$ip" ]; then
        error "Could not resolve $host"
    fi

    echo "$ip"
}

error (){
    (>&2 echo "Error: $1")
    exit 1
}

master_host='google.com'

if [ "$(resolve_ip)" = "$(resolve_ip $master_host)" ]; then
    error "some error"
fi

echo "after exit"
exit
    
por clarkk 25.10.2018 / 13:02

1 resposta

18

exit sai do processo atual do shell¹.

Em $(resolve_ip) , resolve_ip está sendo executado em um processo de subshell.

Você pode fazer:

my_ip=$(resolve_ip) || exit
master_ip=$(resolve_ip "$hostname") || exit
if [ "$my_ip" = "$master_ip" ]; ...

Para o shell principal sair (com o mesmo código de saída que o subshell) quando a subshell sair com um status de saída diferente de zero.

Além disso, como resolve_ip é executado em um ambiente subshell, as variáveis $ip e $host não sobreviverão depois que a subshell retornar.

Observe também que o (...) in (>&2 echo "Error: $1") também inicia uma subshell. Não é realmente necessário aqui, a menos que você queira cobrir o caso em que stderr é um pipe quebrado e gravar a mensagem de erro causaria uma entrega SIGPIPE para o processo principal do shell, pois echo está embutido.

Aqui, em vez de retornar a saída ao stdout, você poderia retorná-lo armazenando-o em variáveis fornecidas pelo usuário:

resolve_ip (){ # args: ip_var [host]
    if [ "$#" -eq 1 ]; then
        host=localhost
        eval "$1="'$(dig +short myip.opendns.com @resolver1.opendns.com)'
    else
        host=$2
        eval "$1="'$(dig +short "$2")'
    fi

    if eval '[ -z "${'"$1"'}" ]'; then
        error "Could not resolve $host"
    fi
}

# ...

resolve_ip my_ip
resolve_ip master_ip "$hostname"

if [ "$my_ip" = "$master_ip" ]; ...

¹ Estritamente ambientes subshell não precisam ser implementados com processos filho, e alguns shells como ksh93 não são como uma otimização, mas ainda assim exit só sai da subshell, não o principal Concha. ksh93 no entanto tem uma ${ ...; } forma ou substituição de comando que não envolve um ambiente subshell, então exit em que sairia do shell principal.

    
por 25.10.2018 / 13:06