Stuart Rothrock
Stuart Rothrock

Reputation: 38

Bash function return not as expected

I have a bash script with a function that is not returning from the function as I think it should.

If the host responds to any of the 3 pings - it should exit the function with a return code 0 - otherwise it would fall out of the loop and exit with a return code 1.

What I find confusing is the trace shows executing the return 0 - but not actually doing it.

I also tried wrapping the ping with a 2nd while loop with a break 2 from the inner "while" but that didn't work as expected either.

What am I missing?

#!/bin/bash
pingCheck() {
  ping -c 3 -W 1 $1 2>&1 | grep --line-buffered time= | while read a; do
    return 0
  done
  return 1
}

set -x
pingCheck note5 || exit
...

and here is the trace output to a reachable host

+ ping -c 3 -W 1 note5
+ grep --line-buffered time=
+ read a
+ return 0
+ return 1
+ exit 

and here is the trace output to a non-reachable host (works as expected)

+ ping -c 3 -W 1 note5x
+ grep --line-buffered time=
+ read a
+ return 1
+ exit

Upvotes: 1

Views: 104

Answers (2)

David C. Rankin
David C. Rankin

Reputation: 84642

Or drop everything except ping:

pingCheck() {
    if ping -c 3 -W 1 $1 2>&1 ; then
        return 0
    else
        return 1
    fi
}

If you are simply interested in 3-successful pings with no output and a return of 0 on success and 1 on failure, then:

pingCheck() {
    if ping -c 3 -W 1 $1 >/dev/null 1>&2 ; then
        return 0
    else
        return 1
    fi
}

note: the point made is well taken. Using only ping will cause a return on the first failure. So this will confirm 3 successful pings, or a failure of 1 of the 3.

Upvotes: 1

cuonglm
cuonglm

Reputation: 2816

The return 0 statement was associated with while loop body, and since when each parts of pipelines in bash was run in subshell, the return 0 cause the subshell executed while loop exit, not the entire function.

You can simply drop the while part, and using grep -c:

pingCheck() {
  num_res=$(ping -c 3 -W 1 "$1" 2>&1 | grep -c --line-buffered time=)
  if [ "$num_res" -ne 0 ]; then
    return 0
  else
    return 1
  fi
}

In some shells like zsh and ksh, the last part of pipelines was run in current shell, so your function will work in those shells.

Upvotes: 4

Related Questions