I am trying to make a simple bash script to check if a ping command could be executed (there is internet) or if not otherwise.
I already had a code which works perfectly which checked directly in the if statement if the ping command can be executed without making an output using /dev/null.
Old code:
#! /usr/bin/bash
YELLOW="\e[33m"
RED="\e[1;31m"
GREEN="\e[1;32m"
ENDCOLOR="\e[0m"
if ping -c 1 8.8.8.8 > /dev/null 2>&1; then
echo -e "${YELLOW}[*]${ENDCOLOR} You have Internet access."
else
echo -e "\n ${RED}[!]${ENDCOLOR} You don't have Internet access !"
echo -e "\n ${YELLOW}[*]${ENDCOLOR} Quitting webDirDiscover..."
exit 1
fi
Now what I want to do is store the command ping -c 1 8.8.8.8 in a variable called PING. Once this is done, execute the if statement and check the result.
The problem is that doing this returns the error:
./webDirDiscover.sh: line 10: PING: command not found
When I think that the if statement should work correctly.
Current code:
#! /usr/bin/bash
YELLOW="\e[33m"
RED="\e[1;31m"
GREEN="\e[1;32m"
ENDCOLOR="\e[0m"
PING=$(ping -c 1 8.8.8.8)
if $PING -eq 0; then
echo -e "${YELLOW}[*]${ENDCOLOR} You have Internet access."
else
echo -e "\n ${RED}[!]${ENDCOLOR} You don't have Internet access !"
echo -e "\n ${YELLOW}[*]${ENDCOLOR} Quitting webDirDiscover..."
exit 1
fi
In addition to solving this simple script, this will come in handy when executing more complex commands and thus have a more visual and visually pleasing code.
CodePudding user response:
Your script attempts to store the output of the command to the PING variable, but not the command itself. There are two basic ways to test the result of a command, and it's either by checking its output or by checking its return code.
In the case of ping, you can simply check if it's successful by checking its return code, so you can do something like this:
if ping -qc1 8.8.8.8 -W1 >/dev/null; then
But if you want to store the command, you can do so by storing its arguments as an array so:
PING=(ping -qc1 8.8.8.8 -W1)
if "${PING[@]}"; then
However, this does not allow you store redirections like >/dev/null, so instead of storing it as an array, better store is a function:
do_ping() {
ping -qc1 8.8.8.8 -W1 >/dev/null
}
Then you can execute:
if do_ping; then
Beware of using function names that has similar name as its external commands as this would cause circular calls:
ping() {
ping -qc1 8.8.8.8 -W1 >/dev/null
}
You can avoid it by using the command command:
ping() {
command ping -qc1 8.8.8.8 -W1 >/dev/null
}
CodePudding user response:
the simple mantra
Variables hold data. Functions hold code. Don't put code inside [string] variables!
source for more info / going further: comprehensive answer on StackExchange
the advanced mantra regarding storing commands in variables is to use arrays as pointed in the comments.
however i personally prefer not to. if at all i am dealing with runtime information, i would use an array only for the arguments, and not for the command itself
i would use functions, as follows
using a function part 1
#!/usr/bin/env bash
# ...
# use descriptive function names
pingGoogleDnsOnce () {
ping -c 1 8.8.8.8
}
if pingGoogleDnsOnce >/dev/null; then
# do stuff
else
# do other stuff
fi
using a function part 2
#!/usr/bin/env bash
# ...
# use descriptive function names
pingGoogleDnsOnce () {
ping -c 1 8.8.8.8
}
# use descriptive function names
quietlyPingGoogleDnsOnce () {
pingGoogleDnsOnce >/dev/null
}
if quietlyPingGoogleDnsOnce; then
# do stuff
else
# do other stuff
fi
in both these there is no need to "check" anything explicitly in the if-block. the -eq 0 is unnecessary
a defined function can be used like any other command. the exit code of last executed command in the body is the function's exit code.
so if ping fails, the function pingGoogleDnsOnce fails; if ping succeeds, the function succeeds
an exit code of 0 indicates success
and if constructs simply check the exit code of the "command" which follows it, in our case a function.
there is another practice where people check the value of $? - the variable which holds the exit code of the previous command. in such cases the construct is
if [ $? -eq 0 ]; then
BUT THIS IS NOT RECOMMENDED. and placing the command within the if condition is a better approach
why PING=$(ping -c 8.8.8.8) fails
the $(...) construct is called command substitution. it is substituted by the output of the command that is within the (). so the variable PING holds the output of ping...blah blah and the output is a long multiline string that's not a command
