Conditional Logic with Multiple Criteria in Bash

Bash scripts often need to make decisions based on multiple conditions. This tutorial explains how to combine conditions within if statements, focusing on the common pitfalls and best practices.

Understanding Boolean Logic

At its core, conditional logic involves evaluating whether conditions are true or false. In Bash, the success (exit status 0) or failure (non-zero exit status) of a command determines its truthiness. To combine multiple conditions, we use logical operators. The key ones are:

  • AND: Both conditions must be true for the overall expression to be true.
  • OR: At least one of the conditions must be true for the overall expression to be true.

The test Command and [ Syntax

Bash uses the test command (or its synonym, [ ]) to evaluate conditions. The test command (and [ ]) takes arguments that specify the conditions to check. It’s crucial to remember that [ is actually a command, and requires a closing ] as its final argument.

Here’s a basic example:

#!/bin/bash

file="my_file.txt"

if [ -f "$file" ]; then
  echo "$file exists"
fi

In this example, -f "$file" checks if the file exists and is a regular file. The if statement executes the echo command only if the file exists. Note the use of double quotes around the variable $file; this is important to prevent word splitting and globbing.

Combining Conditions with AND

To combine multiple conditions with AND, you can use the -a operator with the [ command. However, using -a is considered bad practice. A more reliable and readable approach is to use separate test commands (or [ ] statements) chained with the && operator.

Here’s an example:

#!/bin/bash

status_code=404
string_value="example"
expected_value="test"

if [ "$status_code" -ne 200 ] && [ "$string_value" != "$expected_value" ]; then
  echo "Status code is not 200 and string values are different"
fi

In this example, the if statement will only execute the echo command if both conditions are true: the status_code is not equal to 200, and the string_value is not equal to expected_value.

Important Considerations

  • Exit Status: The if statement evaluates the exit status of the command(s) it runs. A zero exit status indicates success (true), while a non-zero exit status indicates failure (false).
  • Variable Quoting: Always quote your variables (e.g., "$variable") to prevent unexpected behavior due to word splitting and globbing.
  • Whitespace: Use whitespace around operators (e.g., [ "$a" -eq "$b" ]) to improve readability.
  • Avoid [[ ]]: While [[ ]] offers some advantages in certain situations, it is a Bash-specific extension and may not be portable to other shells. It can also suppress error messages which is undesirable. For maximum portability and clarity, stick to the [ and test commands.

Example: Checking Website Status and Content

Here’s a practical example that combines multiple conditions to check if a website is down and if a specific string is present on the page:

#!/bin/bash

WEBSITE="domain.example"
SUBJECT="$WEBSITE DOWN!"
EMAILID="[email protected]"

STATUS=$(curl -sI "$WEBSITE" | awk '/HTTP\/1.1/ { print $2 }')
STRING=$(curl -s "$WEBSITE" | grep -o "string_to_search")
VALUE="string_to_search"

if [ "$STATUS" -ne 200 ] && [ "$STRING" != "$VALUE" ]; then
    echo "Website: $WEBSITE is down, status code: '$STATUS' - $(date)" | mail -s "$SUBJECT" "$EMAILID"
fi

This script checks if the HTTP status code is not 200 (indicating an error) and if the string_to_search is not found on the website. If both conditions are true, it sends an email notification.

Leave a Reply

Your email address will not be published. Required fields are marked *