#!/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
Asked
Active
Viewed 65 times
0

joanis
- 10,635
- 14
- 30
- 40

T. Collins
- 9
- 2
-
Fix the formatting of your question, please. – Shawn Jul 08 '22 at 07:34
-
4Pasting 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 Answers
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