Files
romm/docker/init_scripts/init
Georges-Antoine Assi b2085f87a8 bunch of fixes for trunk
2024-05-21 17:10:11 -04:00

159 lines
4.5 KiB
Bash
Executable File

#!/usr/bin/env bash
set -o errexit # treat errors as fatal
set -o nounset # treat unset variables as an error
set -o pipefail # treat errors in pipes as fatal
shopt -s inherit_errexit # inherit errexit
# use virtualenvs
# shellcheck disable=SC1091
source /backend/bin/activate
# make it possible to disable the inotify watcher process
ENABLE_RESCAN_ON_FILESYSTEM_CHANGE="${ENABLE_RESCAN_ON_FILESYSTEM_CHANGE:="true"}"
# Set INIT_DEBUG to false if not set by docker env
# (this env var is currently undocumented and usually just needed for development purposes)
INIT_DEBUG="${INIT_DEBUG:="false"}"
# print debug log output if enabled
debug_log() {
if [[ ${INIT_DEBUG} == "true" ]]; then
echo "DEBUG: [init][$(date +"%Y-%m-%d %T")]" "${@}" || true
fi
}
# print debug log output if enabled
info_log() {
echo "INFO: [init][$(date +"%Y-%m-%d %T")]" "${@}" || true
}
# print error log output if enabled
error_log() {
echo "ERROR: [init][$(date +"%Y-%m-%d %T")]" "${@}" || true
exit 1
}
# function that runs or main process and creates a corresponding PID file,
start_bin_gunicorn() {
# cleanup potentially leftover socket
rm /tmp/gunicorn.sock -f
# Commands to start our main application and store its PID to check for crashes
info_log "starting gunicorn"
gunicorn \
--access-logfile - \
--error-logfile - \
--worker-class uvicorn.workers.UvicornWorker \
--bind=0.0.0.0:5000 \
--bind=unix:/tmp/gunicorn.sock \
--pid=/tmp/gunicorn.pid \
--workers 2 \
main:app &
}
# Commands to start nginx (handling PID creation internally)
start_bin_nginx() {
info_log "starting nginx"
if [[ ${EUID} -ne 0 ]]; then
nginx
else
# if container runs as root, drop permissions
nginx -g 'user romm;'
fi
}
start_bin_redis-server() {
info_log "starting redis-server"
# Check if /usr/local/etc/redis/redis.conf exists and use it if so
if [[ -f /usr/local/etc/redis/redis.conf ]]; then
redis-server /usr/local/etc/redis/redis.conf &
else
redis-server --dir /redis-data &
fi
REDIS_PID=$!
echo "${REDIS_PID}" >/tmp/redis-server.pid
}
# function that runs our independent python scripts and creates corresponding PID files,
start_python() {
SCRIPT="${1}"
info_log "starting ${SCRIPT}.py"
python3 "${SCRIPT}.py" &
WATCHER_PID=$!
echo "${WATCHER_PID}" >"/tmp/${SCRIPT}.pid"
}
watchdog_process_pid() {
TYPE=$1
PROCESS=$2
if [[ -f "/tmp/${PROCESS}.pid" ]]; then
# check if the pid we last wrote to our state file is actually active
PID=$(cat "/tmp/${PROCESS}.pid") || true
if [[ -d "/proc/${PID}" ]]; then
debug_log "${PROCESS} still running, no need to start"
else
if [[ ${TYPE} == "bin" ]]; then
start_bin_"${PROCESS}"
elif [[ ${TYPE} == "python" ]]; then
start_python "${PROCESS}"
fi
fi
else
if [[ ${TYPE} == "bin" ]]; then
start_bin_"${PROCESS}"
elif [[ ${TYPE} == "python" ]]; then
start_python "${PROCESS}"
fi
fi
}
# switch to backend directory
cd /backend || { error_log "/backend directory doesn't seem to exist"; }
info_log "Starting up, please wait..."
# function definition done, lets start our main loop
while true; do
# check for died processes every 5 seconds
sleep 5
# Start redis server if we dont have a corresponding PID file
# and REDIS_HOST is not set (which would mean we're using an external redis)
if [[ -z ${REDIS_HOST:=""} ]]; then
watchdog_process_pid bin redis-server
fi
# Run needed database migrations on startup,
# but only if it was not successful since the last full docker container start
if [[ ${ALEMBIC_SUCCESS:="false"} == "false" ]]; then
if alembic upgrade head; then
debug_log "database schema migrations suceeded"
ALEMBIC_SUCCESS="true"
else
error_log "Something went horribly wrong with our database"
fi
else
debug_log "database schema already upgraded during current container lifecycle"
fi
# Start nginx if we dont have a corresponding PID file
watchdog_process_pid bin nginx
# Start uvicorn if we dont have a corresponding PID file
watchdog_process_pid bin gunicorn
# only start the watcher.py if we actually want to use the rescan on fs change feature
if [[ ${ENABLE_RESCAN_ON_FILESYSTEM_CHANGE} == "true" ]]; then
# Start watcher if we dont have a corresponding PID file
watchdog_process_pid python watcher
fi
# Start background worker processes
debug_log "Starting worker and scheduler"
# Start worker if we dont have a corresponding PID file
watchdog_process_pid python worker
# Start scheduler if we dont have a corresponding PID file
watchdog_process_pid python scheduler
done