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 ## 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 (2022-03-01)
* v6.1.0-beta.2 (2022-02-11) * v6.1.0-beta.2 (2022-02-11)
@@ -8,8 +11,8 @@
* optimize startup script logging * optimize startup script logging
* add breaks and optimize maintenance script (fixes [#233](https://github.com/buanet/ioBroker.docker/issues/233)) * add breaks and optimize maintenance script (fixes [#233](https://github.com/buanet/ioBroker.docker/issues/233))
* v6.1.0-beta.1 (2021-12-23) * v6.1.0-beta.1 (2021-12-23)
* some more corrections in maintenance script ([#232 @agross](https://github.com/buanet/ioBroker.docker/pull/232)) * 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 @thost96](https://github.com/buanet/ioBroker.docker/pull/229)) * 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 * add alias "m" for maintenance script
### v6.0.0 (2021-12-09) ### v6.0.0 (2021-12-09)
@@ -96,7 +99,7 @@
### v4.1.0 (2020-01-17) ### v4.1.0 (2020-01-17)
* improved readme.md * improved readme.md
* v4.0.3-beta (2020-01-06) * 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" * small fixes according to "docker best practices"
* v4.0.2-beta (2019-12-10) * v4.0.2-beta (2019-12-10)
* ~~added env for activating redis~~ * ~~added env for activating redis~~
@@ -116,13 +119,13 @@
* v3.1.2-beta (2019-09-03) * v3.1.2-beta (2019-09-03)
* using node 10 instead of node 8 * using node 10 instead of node 8
* v3.1.1-beta (2019-09-02) * 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.1.0 (2019-08-21)
* v3.0.3-beta (2019-08-21) * v3.0.3-beta (2019-08-21)
* switching base image from "debian:latest" to "debian:stretch" * switching base image from "debian:latest" to "debian:stretch"
* v3.0.2-beta (2019-06-13) * 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 * changing output of ioBroker logging
* v3.0.1-beta (2019-05-18) * v3.0.1-beta (2019-05-18)
* ~~switching back to iobroker-daemon for startup~~ * ~~switching back to iobroker-daemon for startup~~

View File

@@ -19,6 +19,8 @@ statesdbtype=$IOB_STATESDB_TYPE
usbdevices=$USBDEVICES usbdevices=$USBDEVICES
zwave=$ZWAVE zwave=$ZWAVE
pkill_timeout=10 # timeout for iobroker shutdown in seconds
# Getting date and time for logging # Getting date and time for logging
dati=`date '+%Y-%m-%d %H:%M:%S'` dati=`date '+%Y-%m-%d %H:%M:%S'`
@@ -497,8 +499,35 @@ echo "running" > /opt/scripts/.docker_config/.healthcheck
shut_down() { shut_down() {
echo ' ' echo ' '
echo "Recived termination signal (SIGTERM)." echo "Recived termination signal (SIGTERM)."
echo "Shutting down ioBroker..." echo -n "Shutting down ioBroker"
pkill -SIGTERM -u iobroker -f iobroker.js-controller
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 exit
} }

View File

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