Skip to content

Instantly share code, notes, and snippets.

@sbrl
Last active June 15, 2020 14:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sbrl/08e13f2ceedafe35ac7f8dbdfb8bfde7 to your computer and use it in GitHub Desktop.
Save sbrl/08e13f2ceedafe35ac7f8dbdfb8bfde7 to your computer and use it in GitHub Desktop.
Bash script to automatically reboot if the network connection goes down
[Unit]
Description=Reboot if the network connection is down
After=network.target
[Service]
Type=simple
# Because it needs to be able to reboot
User=root
Group=root
EnvironmentFile=-/etc/default/ensure-network
ExecStartPre=/bin/sleep 60
ExecStart=/bin/bash "/usr/local/lib/ensure-network/ensure-network.sh"
SyslogIdentifier=ensure-access
StandardError=syslog
StandardOutput=syslog
[Install]
WantedBy=multi-user.target
#!/usr/bin/env bash
# ███████ ███ ██ ███████ ██ ██ ██████ ███████
# ██ ████ ██ ██ ██ ██ ██ ██ ██
# █████ ██ ██ ██ ███████ ██ ██ ██████ █████ █████
# ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
# ███████ ██ ████ ███████ ██████ ██ ██ ███████
#
# ███ ██ ███████ ████████ ██ ██ ██████ ██████ ██ ██
# ████ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
# ██ ██ ██ █████ ██ ██ █ ██ ██ ██ ██████ █████
# ██ ██ ██ ██ ██ ██ ███ ██ ██ ██ ██ ██ ██ ██
# ██ ████ ███████ ██ ███ ███ ██████ ██ ██ ██ ██
#
# By Starbeamrainbowlabs
#
# Changelog:
### 15th June 2020
##### Initial Release
#
# This script is licenced under the Mozilla Public Licence 2.0.
# See the full legal text here: https://www.mozilla.org/MPL/2.0/
# See a summary of the licence here: https://tldrlegal.com/license/mozilla-public-license-2.0-(mpl-2)
#
# Contributions are welcome!
# Please also consider getting in touch if you're using this script, as it'd be great to hear how people are using it.
#
# Associated blog post:
# (leave a comment on here if you like!)
#
CHECK_EXTERNAL_HOST="${CHECK_EXTERNAL_HOST:-starbeamrainbowlabs.com}"; # External host to check against
CHECK_INTERVAL="${CHECK_INTERVAL:-3600}"; # In seconds
CHECK_TIMEOUT="${CHECK_TIMEOUT:-5}" # In seconds
CHECK_RETRIES="${CHECK_RETRIES:-5}"; # Retry this many times before rebooting
CHECK_RETRY_DELAY="${CHECK_RETRY_DELAY:-60}"; # Delay this many seconds between retries
CHECK_DRY_RUN="${CHECK_DRY_RUN:-false}"; # Whether to to a dry run or not
CHECK_REBOOT_DELAY="60"; # In *minutes* - reboot at most every hour
# If this file exists and has an mtime in the past 7 days, delay restarting
CHECK_POSTPONE_FILE="${CHECK_POSTPONE_FILE}";
CHECK_POSTPONE_MAXAGE="10080" # In *minutes* - default: 7 days
# Use this file to properly delay reboots
__reboot_delay_file="${__reboot_delay_file:-/var/cache/ensure-network}";
###############################################################################
log_msg() {
echo -ne "[$(date -u +"%Y-%m-%d %H:%M:%S")] $*";
if [[ -z "${NO_NEWLINE}" ]]; then
echo;
fi
}
# From https://github.com/dylanaraps/pure-bash-bible#use-read-as-an-alternative-to-the-sleep-command
# Usage: snore 1
# snore 0.2
snore() {
log_msg "[snore] Sleeping for ${1}s"
read -rt "$1" <> <(:) || :
}
# From https://stackoverflow.com/a/59643790/1460422
file_age() {
local filename="${1}"
if [[ -z "${filename}" ]]; then
echo "[file_age] Error: filenam may not my empty";
return 1;
fi
echo "$(( $(date +%s) - $(date -r $filename +%s) ))"
}
# $1 The filename to check
# $2 The maximum number of minutes the file's age is allowed to be before it is marked stale
is_stale() {
local filename="${1}";
local max_minutes="${2:-20}";
[ $(file_age $filename) -gt $(( $max_minutes*60 )) ]
}
is_fresh() {
is_stale "${1}" "${2}";
if [[ "$?" -eq 0 ]]; then return 1; else return 0; fi
}
###############################################################################
while :; do
log_msg "Checking for connection";
got_connection="false";
for (( i = 0; i < "${CHECK_RETRIES}"; i++ )); do
NO_NEWLINE=true log_msg "Check attempt $i: ";
transcript="$(ping -c1 "${CHECK_EXTERNAL_HOST}" -W "${CHECK_TIMEOUT}" 2>&1)";
exit_code="$?";
if [[ "${exit_code}" -eq "0" ]]; then
echo "success";
got_connection="true";
break;
fi
echo "failed with code ${exit_code}";
log_msg "${transcript}";
snore "${CHECK_RETRY_DELAY}";
done
if [[ "${got_connection}" != "true" ]]; then
log_msg "Failed to get a connection after ${CHECK_RETRIES} attempts.";
if [[ ! -z "${CHECK_POSTPONE_FILE}" ]] && is_fresh "${CHECK_POSTPONE_FILE}" "${CHECK_POSTPONE_MAXAGE}"; then
log_msg "Fresh postpone file detected, delaying reboot";
snore "${CHECK_INTERVAL}";
continue;
else
log_msg "No fresh postpone file detected";
fi
if [[ -f "${__reboot_delay_file}" ]] && is_fresh "${__reboot_delay_file}" "${CHECK_REBOOT_DELAY}"; then
log_msg "It's been less than ${CHECK_REBOOT_DELAY}s since the last reboot, delaying";
continue;
else
log_msg "Last reboot was more than ${CHECK_REBOOT_DELAY}s ago";
fi
touch "${__reboot_delay_file}";
log_msg "Rebooting.";
if [[ "${CHECK_DRY_RUN}" == "false" ]]; then
reboot;
else
while :; do snore 9999999; done
fi
else
log_msg "Got connection after ${i} attempts";
fi
snore "${CHECK_INTERVAL}";
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment