Ensuring that a website remains online and accessible is crucial for any business or individual relying on web presence. Automated monitoring can help quickly identify downtime and performance issues, allowing for swift corrective actions.
This Bash script checks the status of a website at regular intervals and logs whether the site is up or down along with the HTTP status code and the time taken for each check.
#!/bin/bash
# Base URL of the site to monitor
site_url=$1
# Delay between requests in seconds
delay_between_requests=60
# Function to check site status
check_site() {
# Define the user agent for the request
local user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36"
# Record the start time of the request
local start_time=$(date +%s)
# Get the HTTP status code from the request
local status_code=$(curl -H "$user_agent" -s -o /dev/null -w "%{http_code}" $site_url)
# Get the current date and time for logging
local date_time_log=$(date +"%Y-%m-%d %H:%M:%S")
# Record the end time of the request
local end_time=$(date +%s)
# Calculate the elapsed time for the request
local elapsed_time=$((end_time - start_time))
# Log the status based on the HTTP status code
if [ $status_code -ne 200 ]; then
echo "[$date_time_log]: The site is down. Status code: $status_code - Elapsed time: $elapsed_time seconds"
else
echo "[$date_time_log]: The site is up. Status code: $status_code - Elapsed time: $elapsed_time seconds"
fi
}
# Infinite loop to repeatedly check the site
while true; do
check_site
sleep $delay_between_requests
done
How the script works:
URL Input: The script takes the website URL as an argument when executed.
Request Interval: The variable
delay_between_requests
specifies the delay in seconds between each check, set to 60 seconds by default.User Agent: The
user_agent
variable is set to mimic a request from a common web browser, ensuring that the request is handled similarly to a real user visit.HTTP Request and Timing: The
check_site
function:- Records the start time.
- Sends an HTTP GET request using
curl
, capturing the HTTP status code. - Records the end time.
- Calculates the elapsed time for the request.
Logging: The script logs the current date and time, the HTTP status code, and the elapsed time for each check. If the status code is not 200, it indicates that the site is down.
Infinite Loop: The script runs indefinitely, checking the site's status every 60 seconds (or the specified interval).
Using cron
To execute the script via cron
, removing the infinite loop is necessary because cron
will handle the periodic execution of the script. Here's how you can modify the script and set it up with cron
.
Remove the infinite loop and the sleep
command from the script:
#!/bin/bash
# Base URL of the site to monitor
site_url=$1
# Function to check site status
check_site() {
# Define the user agent for the request
local user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36"
# Record the start time of the request
local start_time=$(date +%s)
# Get the HTTP status code from the request
local status_code=$(curl -H "$user_agent" -s -o /dev/null -w "%{http_code}" $site_url)
# Get the current date and time for logging
local date_time_log=$(date +"%Y-%m-%d %H:%M:%S")
# Record the end time of the request
local end_time=$(date +%s)
# Calculate the elapsed time for the request
local elapsed_time=$((end_time - start_time))
# Log the status based on the HTTP status code
if [ $status_code -ne 200 ]; then
echo "[$date_time_log]: The site is down. Status code: $status_code - Elapsed time: $elapsed_time seconds"
else
echo "[$date_time_log]: The site is up. Status code: $status_code - Elapsed time: $elapsed_time seconds"
fi
}
# Call the check_site function
check_site
Save the modified script to a file, for example, check_site.sh
and ensure the script has execute permissions.
chmod a+x check_site.sh
Now open the crontab editor for the current user and add a new line to the crontab to schedule the script. For example, to run the script every 5 minutes:
*/5 * * * * /path/to/check_site.sh https://example.com >> /path/to/logfile.log 2>&1
This line does the following:
*/5 * * * *
: Runs the script every 5 minutes./path/to/check_site.sh https://example.com
: Specifies the path to the script and the URL to check.>> /path/to/logfile.log 2>&1
: Appends the output tologfile.log
and redirects errors to the same file.
By setting up the script with cron
, you offload the periodic execution responsibility to the cron daemon, ensuring the script runs at your specified intervals without the need for an infinite loop within the script itself.
Using systemd
To execute the script via systemd
, you'll need to create a systemd service unit file and a timer unit file to schedule the script execution.
Remove the infinite loop and the sleep
command from the script:
#!/bin/bash
# Base URL of the site to monitor
site_url=$1
# Function to check site status
check_site() {
# Define the user agent for the request
local user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36"
# Record the start time of the request
local start_time=$(date +%s)
# Get the HTTP status code from the request
local status_code=$(curl -H "$user_agent" -s -o /dev/null -w "%{http_code}" $site_url)
# Get the current date and time for logging
local date_time_log=$(date +"%Y-%m-%d %H:%M:%S")
# Record the end time of the request
local end_time=$(date +%s)
# Calculate the elapsed time for the request
local elapsed_time=$((end_time - start_time))
# Log the status based on the HTTP status code
if [ $status_code -ne 200 ]; then
echo "[$date_time_log]: The site is down. Status code: $status_code - Elapsed time: $elapsed_time seconds"
else
echo "[$date_time_log]: The site is up. Status code: $status_code - Elapsed time: $elapsed_time seconds"
fi
}
# Call the check_site function
check_site
Save the modified script to a file and make sure the script has execute permissions. Then create a new file at /etc/systemd/system/check_site.service
with the following content:
[Unit]
Description=Check Site Status
[Service]
Type=oneshot
ExecStart=/usr/local/bin/check_site.sh https://example.com
Now create the systemd timer unit file by adding a new file at /etc/systemd/system/check_site.timer
with the following content:
[Unit]
Description=Run Check Site Script Every 5 Minutes
[Timer]
OnBootSec=5min
OnUnitActiveSec=5min
Unit=check_site.service
[Install]
WantedBy=timers.target
Reload the systemd manager configuration to recognize the new unit files.
sudo systemctl daemon-reload
Enable the timer to start at boot.
sudo systemctl enable check_site.timer
Start the timer immediately.
sudo systemctl start check_site.timer
Finally, verify that the timer is active.
sudo systemctl status check_site.timer
By default, the output of the script run by systemd
will be captured by the journalctl
logs. You can view the logs using:
journalctl -u check_site.service
If you want to log the output to a specific file, you can modify the service file:
[Service]
Type=oneshot
ExecStart=/usr/local/bin/check_site.sh https://example.com
StandardOutput=append:/var/log/check_site.log
StandardError=append:/var/log/check_site.log
By setting up the script with systemd
, you delegate the responsibility of periodic execution to systemd
's timer units. This approach is robust and integrates well with the system's init process, providing better management and logging capabilities compared to cron
.
Conclusion
This simple Bash script provides a foundational tool for monitoring website uptime. By adjusting its parameters and expanding its functionalities, it can be tailored to meet more complex monitoring needs. Automating such tasks ensures that website administrators can stay informed about their site's status and respond quickly to any issues that arise.