As some of our Unifi network components have very long uptimes, we need a script to restart them automatically.
First, ICMP ping is used to check which devices are online in the network and then they are restarted. There is a waiting time between the restart of the individual components, so that switches or APs start up again completely before the next device is restarted.
The latest version is always available on Github: https://github.com/LinuxLinusDE/unifi
ping_sweep.sh
#!/usr/bin/env bash
#############################
# Farben
#############################
RED="\e[31m"
GREEN="\e[32m"
YELLOW="\e[93m"
CYAN="\e[36m"
BOLD="\e[1m"
RESET="\e[0m"
#############################
# Datei-Definitionen
#############################
DATA_DIR="data" # Unterordner für unsere Dateien
NETWORKS_FILE="${DATA_DIR}/networks.txt" # Hier stehen die Netzwerke (CIDR) zeilenweise.
ALIVE_FILE="${DATA_DIR}/alive_hosts.txt" # Hier werden alle erreichbaren IPs gespeichert.
#############################
# Funktionen
#############################
# Titelzeile (ASCII-Banner o.Ä.)
function print_banner() {
echo -e "${CYAN}${BOLD}"
echo "=============================================================="
echo " P I N G - S W E E P S C R I P T"
echo "=============================================================="
echo -e "${RESET}"
}
# Check auf fping
function check_fping() {
if ! command -v fping &> /dev/null
then
echo -e "${RED}[FEHLER]${RESET} Das Programm 'fping' ist nicht installiert!"
echo "Bitte installiere fping (z.B. sudo apt-get install fping) und versuche es erneut."
exit 1
fi
}
# Kurze Hilfe-/Usage-Anzeige
function usage() {
echo "Usage: $0 [OPTION]"
echo " -n, --networks Dateiname mit den CIDR-Netzwerken (Standard: $NETWORKS_FILE)"
echo " -o, --output Dateiname für die erreichbaren Hosts (Standard: $ALIVE_FILE)"
echo " -h, --help Hilfe anzeigen"
exit 0
}
#############################
# Argumente parsen
#############################
while [[ "$#" -gt 0 ]]; do
case $1 in
-n|--networks)
NETWORKS_FILE="$2"
shift
;;
-o|--output)
ALIVE_FILE="$2"
shift
;;
-h|--help)
usage
;;
*)
echo -e "${RED}[FEHLER]${RESET} Unbekannte Option: $1"
usage
;;
esac
shift
done
#############################
# Hauptprogramm
#############################
print_banner
check_fping
# Prüfen, ob das data-Verzeichnis existiert, ggf. erstellen
if [[ ! -d "$DATA_DIR" ]]; then
mkdir -p "$DATA_DIR"
echo -e "${YELLOW}[INFO]${RESET} Ordner '${BOLD}$DATA_DIR${RESET}' wurde erstellt."
fi
# Prüfen, ob die Datei mit den Netzwerken existiert
if [[ ! -f "$NETWORKS_FILE" ]]; then
echo -e "${RED}[FEHLER]${RESET} Datei ${BOLD}$NETWORKS_FILE${RESET} nicht gefunden!"
echo "Bitte sicherstellen, dass die Datei existiert und erneut ausführen."
exit 1
fi
# Alive-Hosts-Datei leeren
> "$ALIVE_FILE"
echo -e "${GREEN}[INFO]${RESET} Alte Einträge in ${BOLD}$ALIVE_FILE${RESET} wurden gelöscht."
# Netzwerke einlesen und abarbeiten
echo -e "${GREEN}[INFO]${RESET} Beginne mit dem Ping-Sweep..."
echo
while read -r NETWORK
do
# Leere Zeilen oder Zeilen mit Kommentar (#) überspringen
if [[ -z "$NETWORK" || "$NETWORK" =~ ^# ]]; then
continue
fi
echo -e "${YELLOW}[STARTE]${RESET} Bearbeite Netzwerk: ${BOLD}$NETWORK${RESET}"
# fping -a -g pingt alle IP-Adressen im Bereich an und gibt nur erreichbare aus
# 2>/dev/null leitet Fehlermeldungen (z.B. bei nicht erreichbaren IPs) ab
fping -a -g "$NETWORK" 2>/dev/null >> "$ALIVE_FILE"
echo -e "${GREEN}[FERTIG]${RESET} Netzwerk ${BOLD}$NETWORK${RESET} abgearbeitet."
echo
done < "$NETWORKS_FILE"
echo -e "${CYAN}[INFO]${RESET} Alle IPs, die auf ICMP geantwortet haben, stehen in ${BOLD}$ALIVE_FILE${RESET}."
echo -e "${CYAN}[ENDE]${RESET} Skript abgeschlossen."
Bashreboot_hosts.sh
#!/usr/bin/env bash
#################################################################
# Farb-Definitionen (ANSI/VT100)
#################################################################
C_RESET="\033[0m"
C_BOLD="\033[1m"
C_RED="\033[1;31m"
C_GREEN="\033[1;32m"
C_YELLOW="\033[1;33m"
C_BLUE="\033[1;34m"
C_MAGENTA="\033[1;35m"
C_CYAN="\033[1;36m"
#################################################################
# Hilfsfunktionen für gefärbte Ausgaben
#################################################################
function info() {
echo -e "${C_BLUE}[INFO]${C_RESET} $*"
}
function warn() {
echo -e "${C_YELLOW}[WARNUNG]${C_RESET} $*"
}
function error() {
echo -e "${C_RED}[FEHLER]${C_RESET} $*"
}
function sshOutput() {
echo -e "${C_MAGENTA}[SSH-AUSGABE]${C_RESET} $*"
}
#################################################################
# Konfigurationsvariablen
#################################################################
HOSTLIST="data/alive_hosts.txt" # Pfad zur Hostliste
SSH_USER="sit" # SSH-Benutzername
REBOOT_CMD="reboot" # Auszuführender Befehl (z.B. "sudo /usr/sbin/reboot")
WAIT_BETWEEN_HOSTS=200 # Zeit (Sekunden) zwischen Hosts (NUR bei Erfolg)
CONNECT_TIMEOUT=10 # SSH-Verbindungs-Timeout (nur Verbindungsaufbau)
SERVER_ALIVE_INTERVAL=2 # Keep-Alive-Interval (Sekunden)
SERVER_ALIVE_COUNTMAX=5 # Anzahl fehlender Antworten bis Abbruch
#################################################################
echo -e "${C_CYAN}=========================================================${C_RESET}"
info "Skript gestartet"
info "Hostliste: $HOSTLIST"
info "SSH-Benutzer: $SSH_USER"
info "Auszuführender Befehl: $REBOOT_CMD"
info "Zeit zwischen Hosts: $WAIT_BETWEEN_HOSTS Sekunden (nur bei erfolgreicher Verbindung)"
info "SSH-Timeout (Connect): $CONNECT_TIMEOUT Sekunden"
info "ServerAliveInterval: $SERVER_ALIVE_INTERVAL Sekunden"
info "ServerAliveCountMax: $SERVER_ALIVE_COUNTMAX"
echo -e "${C_CYAN}=========================================================${C_RESET}"
# Prüfen, ob die Hostliste existiert
if [ ! -f "$HOSTLIST" ]; then
error "Hostliste '$HOSTLIST' wurde nicht gefunden!"
exit 1
fi
# Hostliste auf Dateideskriptor 3 öffnen
exec 3< "$HOSTLIST"
# Zeilenweises Einlesen der IP-Liste von FD 3
while IFS= read -u 3 -r ip; do
# Leerzeilen oder Kommentarzeilen überspringen
if [[ -z "$ip" ]] || [[ "$ip" =~ ^# ]]; then
continue
fi
# Gateways erkennen (IPs, die auf '.1' enden) und überspringen
if [[ "$ip" =~ \.1$ ]]; then
info "Überspringe Gateway: $ip"
continue
fi
echo -e "${C_CYAN}---------------------------------------------------------${C_RESET}"
info "Verarbeite Host: $ip"
info "Versuche SSH-Verbindung aufzubauen..."
# SSH-Befehl ausführen
ssh_output=$(
ssh \
-o StrictHostKeyChecking=no \
-o PasswordAuthentication=no \
-o ConnectTimeout="$CONNECT_TIMEOUT" \
-o ServerAliveInterval="$SERVER_ALIVE_INTERVAL" \
-o ServerAliveCountMax="$SERVER_ALIVE_COUNTMAX" \
"$SSH_USER"@"$ip" \
"echo '[HOST $ip] Starte Befehl...'; $REBOOT_CMD; sleep 1; exit" \
2>&1
)
# Exit-Code prüfen
ret_code=$?
if [ $ret_code -ne 0 ]; then
warn "Fehler beim Verbinden zu Host $ip (Exit-Code: $ret_code)."
sshOutput "$ssh_output"
warn "Keine Wartezeit, weiter mit dem nächsten Host..."
continue
else
info "Host $ip: Befehl '$REBOOT_CMD' abgesetzt."
sshOutput "$ssh_output"
fi
# NUR bei erfolgreicher Verbindung: Countdown
info "Warte nun $WAIT_BETWEEN_HOSTS Sekunden, bevor der nächste Host angesprochen wird..."
for (( i="$WAIT_BETWEEN_HOSTS"; i>0; i-- )); do
printf "\r${C_GREEN}Noch %02d Sekunden...${C_RESET}" "$i"
sleep 1
done
printf "\n"
done
# Dateideskriptor schließen
exec 3<&-
echo -e "${C_CYAN}---------------------------------------------------------${C_RESET}"
info "Skript beendet."
echo -e "${C_CYAN}=========================================================${C_RESET}"
Bash