Sometimes you need to specify different courses of action to be taken in a shell script, depending on the success or failure of a command. The if construction allows you to specify such conditions. The most common syntax of the if command is:
if TEST-COMMAND
then
POSITIVE-CONSEQUENT-COMMANDS
else
NEGATIVE-CONSEQUENT-COMMANDS
fi
If the TEST-COMMAND is successful (returns an exit status of 0), then the positive consequent commands are executed, otherwise, the negative consequent commands (if provided) are executed.
The if
statement is terminated with the fi
command.
Before you start, review the man page of the test
command
The first example checks for the existence of a file:
echo "This script checks the existence of the messages file."
echo "Checking..."
if [ -f /var/log/messages ]
then
echo "/var/log/messages exists."
fi
echo
echo "...done."
Recall that the $?
variable holds the exit status of the previously executed command. The following example utilize this variable to take a decision according to the success or failure of the previous command:
curl google.com &> /dev/null
if [ $? -eq 0 ]
then
echo "Request succeeded"
else
echo "Request failed, trying again..."
fi
The below example demonstrates numeric comparison between a variable and 20. Don't worry is it doesn't work, you'll fix it soon 🙂
num=$(wc -l /etc/passwd)
echo $num
if [ "$num" -gt "20" ]; then
echo "Too many users in the system."
fi
if [[ "$(whoami)" != 'root' ]]; then
echo "You have no permission to run $0 as non-root user."
exit 1;
fi
echo "Bash is ok" > file
if grep -q Bash file
then
echo "File contains at least one occurrence of Bash."
fi
Another example:
word=Linux
letter_sequence=inu
if echo "$word" | grep -q "$letter_sequence"
# The "-q" option to grep suppresses output.
then
echo "$letter_sequence found in $word"
else
echo "$letter_sequence not found in $word"
fi
With version 2.02, Bash introduced the [[ ... ]]
extended test command, which performs comparisons in a manner more familiar to programmers from other languages. The [[...]]
construct is the more versatile Bash version of [...]
. Using the [[...]]
test construct, rather than [...]
can prevent many logic errors in scripts.
Enter the interactive self-check page
Write a bash script geo_by_ip.sh
that given an ip address, prints geo-location details, as follows:
- The script first checks if
jq
cli is installed, if not, it prints a message to the user with a link to download the tool: https://stedolan.github.io/jq/download/ - The script checks that exactly one argument was sent to it, which represents the ip address to check. Otherwise, an informative message is being printed to stdout.
- The script checks that the given IP argument is not equal to
127.0.0.1
- The script performs an HTTP GET request to
http://ip-api.com/json/<ip>
while<ip>
is the IP argument. The results should be stored in a variable. - Using the
jq
tool and the variable containing the HTTP response, check that the request has been succeeded by checking that thestatus
key has a value of success. The commandjq -r '.<key>'
can extract a key from the json (e.g.echo $RESPONSE | jq -r '.status'
) - If the request succeed, print the following information to the user:
- country
- city
- regionName
Extending the above script to be more modular. Assume availability_test.sh
is:
curl google.com &> /dev/null
if [ $? -eq 0 ]
then
echo "Request succeeded"
else
echo "Request failed, trying again..."
fi
Change the script such that can be working for any URL input from the user, in the following form:
myuser@hostname:~$ ./availability_test.sh google.com
...
myuser@hostname:~$ ./availability_test.sh cnn.com
...
myuser@hostname:~$ ./availability_test.sh abcdefg
...
myuser@hostname:~$ ./availability_test.sh
A valid URL is required