Skip to main content
added 576 characters in body
Source Link
Stéphane Chazelas
  • 584.9k
  • 96
  • 1.1k
  • 1.7k

exit exits the current shell process¹.

In $(resolve_ip), resolve_ip is running in a subshell process.

You can do:

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

For the main shell to exit (with the same exit code as the subshell) when the subshell exits with a non-zero exit status.

Also, as resolve_ip is run in a subshell environment, the $ip and $host variables will not survive after that subshell returns.

Also note that the (...) in (>&2 echo "Error: $1") also starts a subshell. Not really necessary here unless you want to cover for the case where stderr is a broken pipe and writing the error message would cause a SIGPIPE delivery to the main shell process as echo is builtin.

Here, instead of returning the output over stdout, you could return it by storing it in user supplied variables:

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" ]; ...

¹ Strictly speaking subshell environments don't have to be implemented with child processes, and some shells like ksh93 don't as an optimisation, but still exit there only exits the subshell, not the main shell. ksh93 however has a ${ ...; } form or command substitution that doesn't involve a subshell environment, so exit in that would exit the main shell.

exit exits the current shell process¹.

In $(resolve_ip), resolve_ip is running in a subshell process.

You can do:

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

For the main shell to exit (with the same exit code as the subshell) when the subshell exits with a non-zero exit status.

Also, as resolve_ip is run in a subshell environment, the $ip and $host variables will not survive after that subshell returns.

Also note that the (...) in (>&2 echo "Error: $1") also starts a subshell. Not really necessary here unless you want to cover for the case where stderr is a broken pipe and writing the error message would cause a SIGPIPE delivery to the main shell process as echo is builtin.


¹ Strictly speaking subshell environments don't have to be implemented with child processes, and some shells like ksh93 don't as an optimisation, but still exit there only exits the subshell, not the main shell. ksh93 however has a ${ ...; } form or command substitution that doesn't involve a subshell environment, so exit in that would exit the main shell.

exit exits the current shell process¹.

In $(resolve_ip), resolve_ip is running in a subshell process.

You can do:

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

For the main shell to exit (with the same exit code as the subshell) when the subshell exits with a non-zero exit status.

Also, as resolve_ip is run in a subshell environment, the $ip and $host variables will not survive after that subshell returns.

Also note that the (...) in (>&2 echo "Error: $1") also starts a subshell. Not really necessary here unless you want to cover for the case where stderr is a broken pipe and writing the error message would cause a SIGPIPE delivery to the main shell process as echo is builtin.

Here, instead of returning the output over stdout, you could return it by storing it in user supplied variables:

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" ]; ...

¹ Strictly speaking subshell environments don't have to be implemented with child processes, and some shells like ksh93 don't as an optimisation, but still exit there only exits the subshell, not the main shell. ksh93 however has a ${ ...; } form or command substitution that doesn't involve a subshell environment, so exit in that would exit the main shell.

added 521 characters in body
Source Link
Stéphane Chazelas
  • 584.9k
  • 96
  • 1.1k
  • 1.7k

exit exits the current shell processprocess¹.

In $(resolve_ip), resolve_ip is running in a subshell process.

You can do:

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

For the main shell to exit (with the same exit code as the subshell) when the subshell exits with a non-zero exit status.

Also, as resolve_ip is run in a subshell environment, the $ip and $host variables will not survive after that subshell returns.

Also note that the (...) in (>&2 echo "Error: $1") also starts a subshell. Not really necessary here unless you want to cover for the case where stderr is a broken pipe and writing the error message would cause a SIGPIPE delivery to the main shell process as echo is builtin.


¹ Strictly speaking subshell environments don't have to be implemented with child processes, and some shells like ksh93 don't as an optimisation, but still exit there only exits the subshell, not the main shell. ksh93 however has a ${ ...; } form or command substitution that doesn't involve a subshell environment, so exit in that would exit the main shell.

exit exits the current shell process.

In $(resolve_ip), resolve_ip is running in a subshell process.

You can do:

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

For the main shell to exit (with the same exit code as the subshell) when the subshell exits with a non-zero exit status.

exit exits the current shell process¹.

In $(resolve_ip), resolve_ip is running in a subshell process.

You can do:

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

For the main shell to exit (with the same exit code as the subshell) when the subshell exits with a non-zero exit status.

Also, as resolve_ip is run in a subshell environment, the $ip and $host variables will not survive after that subshell returns.

Also note that the (...) in (>&2 echo "Error: $1") also starts a subshell. Not really necessary here unless you want to cover for the case where stderr is a broken pipe and writing the error message would cause a SIGPIPE delivery to the main shell process as echo is builtin.


¹ Strictly speaking subshell environments don't have to be implemented with child processes, and some shells like ksh93 don't as an optimisation, but still exit there only exits the subshell, not the main shell. ksh93 however has a ${ ...; } form or command substitution that doesn't involve a subshell environment, so exit in that would exit the main shell.

Source Link
Stéphane Chazelas
  • 584.9k
  • 96
  • 1.1k
  • 1.7k

exit exits the current shell process.

In $(resolve_ip), resolve_ip is running in a subshell process.

You can do:

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

For the main shell to exit (with the same exit code as the subshell) when the subshell exits with a non-zero exit status.