Last active
February 18, 2025 12:30
-
-
Save sbrl/08e13f2ceedafe35ac7f8dbdfb8bfde7 to your computer and use it in GitHub Desktop.
Bash script to automatically reboot if the network connection goes down
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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