0
#!/bin/bash
HOSTS="cyberciti.biz theos.in router"
    
COUNT=4

for myHost in $HOSTS
do
  count=$(ping -c $COUNT $myHost | grep 'received' | awk -F',' '{ print $2 }' | awk '{ print $1 }')
  if [ $count -eq 0 ]; then
    # 100% failed 
    echo "Host : $myHost is down (ping failed) at $(date)"
  fi
done
joanis
  • 10,635
  • 14
  • 30
  • 40
  • Fix the formatting of your question, please. – Shawn Jul 08 '22 at 07:34
  • 4
    Pasting your script into [ShellCheck.net](https://www.shellcheck.net/) will disclose quoting issues likely responsible for your syntax issues. (Rule: always quote within `[...]`) – David C. Rankin Jul 08 '22 at 07:37
  • Quoting problems (although they should be fixed) shouldn't cause a syntax error like that. Does the script have [DOS/Windows line endings](https://stackoverflow.com/questions/39527571/are-shell-scripts-sensitive-to-encoding-and-line-endings) or any other weird formatting? If not, what is the [exact, full error message](https://meta.stackoverflow.com/questions/359146/why-should-i-post-complete-errors-why-isnt-the-message-itself-enough/359147)? – Gordon Davisson Jul 08 '22 at 09:13
  • @GordonDavisson my guess was `count` contained whitespace after the command substitution which would generate the syntax error in `[ $count -eq 0 ]`. For example if `ping` received the `4` responses requested, then the `grep` and two `awk` calls would return 4 lines of data. – David C. Rankin Jul 08 '22 at 20:19
  • @DavidC.Rankin, but how would that turn into `fi` being invalid? – Charles Duffy Oct 17 '22 at 17:15
  • I suspect the OP's code was saved with DOS newlines -- then the `then` would instead be `$'then\r'` and not recognized as a token. If the `fi` had a space after it it'd be legitimate instead of `$'fi\r'`, so you could get into this state. – Charles Duffy Oct 17 '22 at 17:16
  • 1
    @T.Collins ...btw, in general, `grep | awk` is unnecessary; think about `awk -F', ' '/received/ { print $2 }'` -- or to avoid needing more than one awk, `awk -F', ' '{sub(/ .*/, "", $2); print $2}'` – Charles Duffy Oct 17 '22 at 17:19
  • There's really no need for a lot of this. If you want to parse the output of `ping` to count the number of packets received, you can just do something like `if ping ... | awk '/received/{ exit $4 != 0}'; then echo host is down >&2; fi`. (This is very fragile, but no less than the code in the question.). – William Pursell Oct 17 '22 at 17:30
  • @CharlesDuffy because `$count` wasn't quoted that would blow up `test`. – David C. Rankin Oct 17 '22 at 23:14
  • @DavidC.Rankin, yes, but `test` doesn't interact with the shell parser so it won't change the meaning of `if`, `then` or `fi`. Improper `test` usage can cause errors, sure, but it won't cause _this_ error. – Charles Duffy Oct 17 '22 at 23:27
  • @CharlesDuffy - I got you. What was posted shouldn't have caused that error either. Quotes were missing, but the interpreter should see the `if` and `fi` – David C. Rankin Oct 18 '22 at 00:43

1 Answers1

1

I've added some double quotes, this should do the trick:

#!/bin/bash
HOSTS="cyberciti.biz theos.in router"

COUNT=4

for myHost in $HOSTS
do
  count=$(ping -c $COUNT "$myHost" | grep 'received' | awk -F',' '{ print $2 }' | awk '{ print $1 }')
  if [ "$count" -eq "0" ]; then
    # 100% failed 
    echo "Host : $myHost is down (ping failed) at $(date)"
  fi
done
Dominique
  • 16,450
  • 15
  • 56
  • 112
  • though it's not exactly great form to use a string to store a list. To make this good-practice code, `hosts=( cyberciti.biz theos.in router )` followed by `for myHost in "${hosts[@]}"` would be more appropriate. – Charles Duffy Oct 17 '22 at 17:13
  • (also, all the locally-defined all-caps variables shouldn't be, per [POSIX-specified convention](https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html); all-caps names are used for variables that reflect or modify behavior of the shell and OS-provided tools, whereas names with at least one lower-case character are reserved for application use) – Charles Duffy Oct 17 '22 at 17:14