optimize iob shutdown

This commit is contained in:
buanet
2022-06-13 22:55:32 +02:00
parent 3957414b2b
commit b8c67b7149
4 changed files with 197 additions and 171 deletions

View File

@@ -1 +1 @@
v6.1.0
v6.2.0-beta.1

View File

@@ -1,4 +1,7 @@
## Changelog
### v6.2.0-beta.1 (2022-06-13)
* rewrite maintenance script ([#243 by @agross](https://github.com/buanet/ioBroker.docker/pull/243))
* optimize container shutdown on SIGTERM ([as requested with #264 by @buzz0r](https://github.com/buanet/ioBroker.docker/pull/264))
### v6.1.0 (2022-03-01)
* v6.1.0-beta.2 (2022-02-11)
@@ -8,8 +11,8 @@
* optimize startup script logging
* add breaks and optimize maintenance script (fixes [#233](https://github.com/buanet/ioBroker.docker/issues/233))
* v6.1.0-beta.1 (2021-12-23)
* some more corrections in maintenance script ([#232 @agross](https://github.com/buanet/ioBroker.docker/pull/232))
* add auto confirm parameter to upgrade function in maintenance script ([#229 @thost96](https://github.com/buanet/ioBroker.docker/pull/229))
* some more corrections in maintenance script ([#232 by @agross](https://github.com/buanet/ioBroker.docker/pull/232))
* add auto confirm parameter to upgrade function in maintenance script ([#229 by @thost96](https://github.com/buanet/ioBroker.docker/pull/229))
* add alias "m" for maintenance script
### v6.0.0 (2021-12-09)
@@ -96,7 +99,7 @@
### v4.1.0 (2020-01-17)
* improved readme.md
* v4.0.3-beta (2020-01-06)
* added support to restore backup on startup ([#56 @duffbeer2000](https://github.com/buanet/ioBroker.docker/pull/56))
* added support to restore backup on startup ([#56 by @duffbeer2000](https://github.com/buanet/ioBroker.docker/pull/56))
* small fixes according to "docker best practices"
* v4.0.2-beta (2019-12-10)
* ~~added env for activating redis~~
@@ -116,13 +119,13 @@
* v3.1.2-beta (2019-09-03)
* using node 10 instead of node 8
* v3.1.1-beta (2019-09-02)
* adding env for setting uid/ gid for iobroker-user ([#33 @mplogas](https://github.com/buanet/ioBroker.docker/pull/33))
* adding env for setting uid/ gid for iobroker-user ([#33 by @mplogas](https://github.com/buanet/ioBroker.docker/pull/33))
### v3.1.0 (2019-08-21)
* v3.0.3-beta (2019-08-21)
* switching base image from "debian:latest" to "debian:stretch"
* v3.0.2-beta (2019-06-13)
* using gosu instead of sudo ([#26 @SchumyHao](https://github.com/buanet/ioBroker.docker/pull/26))
* using gosu instead of sudo ([#26 by @SchumyHao](https://github.com/buanet/ioBroker.docker/pull/26))
* changing output of ioBroker logging
* v3.0.1-beta (2019-05-18)
* ~~switching back to iobroker-daemon for startup~~

View File

@@ -19,6 +19,8 @@ statesdbtype=$IOB_STATESDB_TYPE
usbdevices=$USBDEVICES
zwave=$ZWAVE
pkill_timeout=10 # timeout for iobroker shutdown in seconds
# Getting date and time for logging
dati=`date '+%Y-%m-%d %H:%M:%S'`
@@ -497,8 +499,35 @@ echo "running" > /opt/scripts/.docker_config/.healthcheck
shut_down() {
echo ' '
echo "Recived termination signal (SIGTERM)."
echo "Shutting down ioBroker..."
pkill -SIGTERM -u iobroker -f iobroker.js-controller
echo -n "Shutting down ioBroker"
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
fi
if (( status == 1 )); then # no processes matched
return
fi
# pgrep exits with status 1 when there are no matches
while pgrep -u iobroker > /dev/null; (( $? != 1 )); do
if (($(date +%s) > timeout)); then
echo -e '\nTimeout reached. Killing remaining processes...'
pkill --signal SIGKILL -u iobroker
echo 'Done.'
exit
fi
echo -n '.'
sleep 1
done
echo -e '\nDone.'
exit
}

View File

@@ -1,234 +1,228 @@
#!/bin/bash
#!/usr/bin/env bash
############################
##### default settings #####
############################
# bash strict mode
set -euo pipefail
autoconfirm=no # could be set to true by commandline option
killbyname=no # could be set to true by commandline option / undocumented, only for use with backitup restore scripts
####################################
##### declaration of functions #####
####################################
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/scripts/.docker_config/.healthcheck # path of healthcheck file
pkill_timeout=10 # timeout for stopping iobroker in seconds
# display help text
display_help() {
echo "This script is build to manage your ioBroker container!"
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 shuts down or restarts container"
echo " upgrade > will put container to maintenance mode and upgrade ioBroker"
echo " help > shows this help"
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 ' help > shows this help'
echo ''
echo "OPTIONS"
echo "------------------"
echo " -y|--yes > confirms the used command without asking"
echo " -h|--help > shows this help"
echo 'OPTIONS'
echo '------------------'
echo ' -y|--yes > confirms the used command without asking'
echo ' -h|--help > shows this help'
echo ''
exit 0
}
# checking maintenance mode status
check_status() {
if [ $(cat /opt/scripts/.docker_config/.healthcheck) == 'maintenance' ]
then
# check maintenance enabled
maintenance_enabled() {
[[ -f "$healthcheck" && "$(cat "$healthcheck")" == maintenance ]]
}
# display maintenance status
maintenance_status() {
if maintenance_enabled; then
echo 'Maintenance mode is turned ON.'
elif [ $(cat /opt/scripts/.docker_config/.healthcheck) != 'maintenance' ]
then
else
echo 'Maintenance mode is turned OFF.'
fi
}
# turn maintenance mode ON
switch_on() {
if [ $(cat /opt/scripts/.docker_config/.healthcheck) != 'maintenance' ] && [ "$killbyname" == "yes" ] # maintenance mode OFF / killbyname = yes / undocumented, only for use with backitup restore scripts
then
# enable maintenance mode
enable_maintenance() {
if maintenance_enabled; then
echo 'Maintenance mode is already turned ON.'
return
fi
if [[ "$killbyname" == yes ]]; then
# undocumented option, only for use with backitup restore scripts
echo 'This command will activate maintenance mode and stop js-controller.'
echo 'Activating maintenance mode...'
echo "maintenance" > /opt/scripts/.docker_config/.healthcheck
echo 'maintenance' > "$healthcheck"
sleep 1
echo 'Done.'
echo 'Stopping ioBroker...'
pkill -u iobroker -f iobroker.js-controller
sleep 1
echo 'Done.'
exit 0
elif [ $(cat /opt/scripts/.docker_config/.healthcheck) != 'maintenance' ] && [ "$autoconfirm" == "no" ] # maintenance mode OFF / autoconfirm = no
then
echo 'You are now going to stop ioBroker and activating maintenance mode for this container.'
read -p 'Do you want to continue [yes/no]? ' A
if [ "$A" == "y" ] || [ "$A" == "Y" ] || [ "$A" == "yes" ]
then
echo 'Activating maintenance mode...'
echo "maintenance" > /opt/scripts/.docker_config/.healthcheck
sleep 1
echo 'Done.'
echo 'Stopping ioBroker...'
pkill -u iobroker
sleep 1
echo 'Done.'
exit 0
else
exit 0
echo -n 'Stopping ioBroker...'
stop_iob
return
fi
elif [ $(cat /opt/scripts/.docker_config/.healthcheck) != 'maintenance' ] && [ "$autoconfirm" == "yes" ] # maintenance mode OFF / autoconfirm = yes
then
echo 'You are now going to stop ioBroker and activating maintenance mode for this container.'
echo 'This command was already confirmed by -y or --yes option.'
echo 'Activating maintenance mode...'
echo "maintenance" > /opt/scripts/.docker_config/.healthcheck
sleep 1
echo 'Done.'
echo 'Stopping ioBroker...'
pkill -u iobroker
sleep 1
echo 'Done.'
exit 0
echo 'You are now going to stop ioBroker and activate maintenance mode for this container.'
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
echo 'Maintenance mode is already turned ON.'
return 1
fi
else
echo 'This command was already confirmed by the -y or --yes option.'
fi
echo 'Activating maintenance mode...'
echo 'maintenance' > "$healthcheck"
sleep 1
echo 'Done.'
echo -n 'Stopping ioBroker...'
stop_iob
}
# turn maintenance mode OFF
switch_off() {
if [ $(cat /opt/scripts/.docker_config/.healthcheck) == 'maintenance' ] && [ "$autoconfirm" == "no" ] # maintenance mode ON / autoconfirm = no
then
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.'
read -p 'Do you want to continue [yes/no]? ' A
if [ "$A" == "y" ] || [ "$A" == "Y" ] || [ "$A" == "yes" ]
then
echo 'Deactivating maintenance mode and forcing container to stop or restart...'
echo "stopping" > /opt/scripts/.docker_config/.healthcheck
pkill -u root
echo 'Done.'
exit 0
else
exit 0
fi
elif [ $(cat /opt/scripts/.docker_config/.healthcheck) == 'maintenance' ] && [ "$autoconfirm" == "yes" ] # maintenance mode ON / autoconfirm = yes
then
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.'
echo 'This command was already confirmed by -y or --yes option.'
echo 'Deactivating maintenance mode and forcing container to stop or restart...'
echo "stopping" > /opt/scripts/.docker_config/.healthcheck
pkill -u root
echo 'Done.'
exit 0
else
# 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
else
echo 'This command was already confirmed by the -y or --yes option.'
fi
echo 'Deactivating maintenance mode and forcing container to stop or restart...'
echo 'stopping' > "$healthcheck"
pkill -u root
echo 'Done.'
}
# upgrade js-controller
upgrade() {
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 of the restart policy, your container will be stopped or restarted automatically after the upgrade.'
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" == "no" ]
then
read -p 'Do you want to continue [yes/no]? ' A
if [ "$A" == "y" ] || [ "$A" == "Y" ] || [ "$A" == "yes" ]
then
: # Continue.
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
exit 0
return 1
fi
elif [ "$autoconfirm" == "yes" ]
then
echo 'This command was already confirmed by -y or --yes option.'
else
echo 'This command was already confirmed by the -y or --yes option.'
fi
if [ $(cat /opt/scripts/.docker_config/.healthcheck) != 'maintenance' ]
then
echo 'Activating maintenance mode...'
echo "maintenance" > /opt/scripts/.docker_config/.healthcheck
sleep 1
echo 'Done.'
echo 'Stopping ioBroker...'
pkill -u iobroker
sleep 5
echo 'Done.'
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" > /opt/scripts/.docker_config/.healthcheck
echo 'stopping' > "$healthcheck"
pkill -u root
exit 0
}
########################################
##### parsing commands and options #####
########################################
# stop iobroker and wait until all processes stopped or pkill_timeout is reached
stop_iob() {
local status timeout
# reading all arguments and putting them in reverse
reverse=
for i in "$@"; do
reverse="$i $reverse"
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
fi
if (( status == 1 )); then # no processes matched
return
fi
# pgrep exits with status 1 when there are no matches
while pgrep -u iobroker > /dev/null; (( $? != 1 )); do
if (($(date +%s) > timeout)); then
echo -e '\nTimeout reached. Killing remaining processes...'
pgrep --list-full -u iobroker
pkill --signal SIGKILL -u iobroker
echo 'Done.'
return
fi
echo -n '.'
sleep 1
done
# checking the arguments
for i in $reverse; do
case $i in
echo -e '\nDone.'
}
# 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)
display_help # calling function to display help text
break
run=(display_help)
;;
status)
check_status # calling function to check maintenance mode status
break
run=(maintenance_status)
;;
on)
switch_on # calling function to switch maintenance mode on
break
run=(enable_maintenance)
;;
off)
switch_off # calling function to switch maintenance mode off
break
run=(disable_maintenance)
;;
upgrade)
upgrade # calling function to upgrade js-controller
break
run=(upgrade_jscontroller)
;;
-y|--yes)
autoconfirm=yes # setting autoconfrm option to "yes"
shift
autoconfirm=yes
;;
-kbn|--killbyname)
killbyname=yes # setting killbyname option to "yes"
shift
killbyname=yes
;;
-a=*|--argument=*) # dummy exaple for parsing option with value
ARGUMENT="${i#*=}"
shift
;;
--) # End of all options.
shift
--)
break
;;
-?*|?*)
echo 'WARN: Unknown parameter. Please try again or see help (-h|--help).'
break
;;
*) # Default case: No more options, so break out of the loop.
break
*)
>&2 echo "Unknown parameter: $arg"
>&2 echo 'Please try again or see help (help|-h|--help).'
exit 1
;;
esac
done
exit 0
"${run[@]}"