#!/usr/bin/env bash # bash strict mode set -euo pipefail autoconfirm= # can be set to 'yes' by command line option killbyname= # can be set to 'yes' by command line option (undocumented, only for use with backitup restore scripts) healthcheck=/opt/.docker_config/.healthcheck # path of healthcheck file pkill_timeout=10 # timeout for stopping iobroker in seconds # check for user root if [ "$(id -u)" -eq 0 ]; then echo "WARNING! This script should be executed as user "iobroker"! Please switch user and try again." exit 1 fi # display help text display_help() { echo "This script helps you manage your ioBroker container!" echo " " echo "Usage: maintenance [ COMMAND ] [ OPTION ]" echo " maint [ COMMAND ] [ OPTION ]" echo " m [ COMMAND ] [ OPTION ]" echo " " echo "COMMANDS" echo "------------------" echo " status > reports the current state of maintenance mode" echo " on > switches mantenance mode ON" echo " off > switches mantenance mode OFF and stops or restarts the container" echo " upgrade > puts the container to maintenance mode and upgrades ioBroker" echo " restart > stops iobroker and stops or restarts the container" echo " help > shows this help" echo " " echo "OPTIONS" echo "------------------" echo " -y|--yes > confirms the used command without asking" echo " -h|--help > shows this help" echo " " } # check maintenance enabled maintenance_enabled() { [[ -f "$healthcheck" && "$(cat "$healthcheck")" == maintenance ]] } # check status starting check_starting() { [[ -f "$healthcheck" && "$(cat "$healthcheck")" == starting ]] } # display maintenance status maintenance_status() { if maintenance_enabled; then echo "Maintenance mode is turned ON." else echo "Maintenance mode is turned OFF." fi } # enable maintenance mode enable_maintenance() { if maintenance_enabled; then echo "Maintenance mode is already turned ON." return fi echo "You are now going to stop ioBroker and activate maintenance mode for this container." if [[ "$killbyname" != yes ]]; then if [[ "$autoconfirm" != yes ]]; then local reply read -rp 'Do you want to continue [yes/no]? ' reply if [[ "$reply" == y || "$reply" == Y || "$reply" == yes ]]; then : # continue else return 1 fi fi fi echo "Activating maintenance mode..." echo "maintenance" > "$healthcheck" sleep 1 echo -n "Stopping ioBroker..." stop_iob } # disable maintenance mode disable_maintenance() { if ! maintenance_enabled; then echo "Maintenance mode is already turned OFF." return fi echo "You are now going to deactivate maintenance mode for this container." echo "Depending on the restart policy, your container will be stopped or restarted immediately." if [[ "$autoconfirm" != yes ]]; then local reply read -rp 'Do you want to continue [yes/no]? ' reply if [[ "$reply" == y || "$reply" == Y || "$reply" == yes ]]; then : # continue else return 1 fi fi echo "Deactivating maintenance mode and forcing container to stop or restart..." echo "stopping" > "$healthcheck" pkill -u iobroker echo "Done." } # upgrade js-controller upgrade_jscontroller() { echo "You are now going to upgrade your js-controller." echo "As this will change data in /opt/iobroker, make sure you have a backup!" echo "During the upgrade process, the container will automatically switch into maintenance mode and stop ioBroker." echo "Depending on the restart policy, your container will be stopped or restarted automatically after the upgrade." if [[ "$autoconfirm" != yes ]]; then local reply read -rp 'Do you want to continue [yes/no]? ' reply if [[ "$reply" == y || "$reply" == Y || "$reply" == yes ]]; then : # continue else return 1 fi fi if ! maintenance_enabled > /dev/null; then autoconfirm=yes enable_maintenance fi echo "Upgrading js-controller..." iobroker update sleep 1 iobroker upgrade self sleep 1 echo "Done." echo "Container will be stopped or restarted in 5 seconds..." sleep 5 echo "stopping" > "$healthcheck" pkill -u iobroker } # stop iobroker and wait until all processes stopped or pkill_timeout is reached stop_iob() { local status timeout timeout="$(date --date="now + $pkill_timeout sec" +%s)" pkill -u iobroker -f 'iobroker.js-controller[^/]*$' status=$? if (( status >= 2 )); then # syntax error or fatal error return 1 elif (( status == 1 )); then # no processes matched return fi if [[ "$killbyname" != yes ]]; then # pgrep exits with status 1 when there are no matches while pgrep -u iobroker -f 'io\..' > /dev/null; (( $? != 1 )); do if (($(date +%s) > timeout)); then echo -e "\nTimeout reached. Killing remaining processes..." pgrep --list-full -u iobroker -f 'io\..' pkill --signal SIGKILL -u iobroker -f 'io\..' echo "Done." return fi sleep 1 echo -n "." done else for ((i=0; i<3; i++)); do sleep 1 echo -n "." done fi echo -e "Done." echo " " } # restart container restart_container() { echo "You are now going to call a restart of your container." echo "Restarting will work depending on the configured restart policy." if [[ "$autoconfirm" != yes ]]; then local reply read -rp 'Do you want to continue [yes/no]? ' reply if [[ "$reply" == y || "$reply" == Y || "$reply" == yes ]]; then : # continue else return 1 fi fi if ! maintenance_enabled > /dev/null; then echo -n "Stopping ioBroker..." stop_iob fi echo "Container will be stopped or restarted in 5 seconds..." sleep 5 echo "stopping" > "$healthcheck" pkill -u iobroker } # restore iobroker <<< Removed due to changes in backup structure and the availability of the graphical restore with backitup restore_iobroker() { echo "Due to changes in ioBroker backup structure, restoring is no longer supported by this script." echo "Please use the original ioBroker commands or the graphical ui of backitup adapter." } # parsing commands and options # default command to run unless another was given run=(display_help) for arg in "$@"; do case $arg in help|-h|--help) run=(display_help) ;; status|stat|s) run=(maintenance_status) ;; on) run=(enable_maintenance) ;; off) run=(disable_maintenance) ;; upgrade|upgr|u) run=(upgrade_jscontroller) ;; restart|rest|r) run=(restart_container) ;; restore) run=(restore_iobroker) ;; -y|--yes) autoconfirm=yes ;; -kbn|--killbyname) killbyname=yes ;; --) break ;; *) >&2 echo "Unknown parameter: $arg" >&2 echo "Please try again or see help (help|-h|--help)." exit 1 ;; esac done "${run[@]}"