diff --git a/customer/usr/local/bin/common.sh b/customer/usr/local/bin/common.sh index 64415d2..51786e1 100644 --- a/customer/usr/local/bin/common.sh +++ b/customer/usr/local/bin/common.sh @@ -1,10 +1,9 @@ #!/bin/bash -# Ver: 1.4 by Endial Fang (endial@126.com) +# Ver: 1.5 by Endial Fang (endial@126.com) # # 应用通用业务处理函数 . /colovu/lib/libcommon.sh # 通用函数库 - . /colovu/lib/libfile.sh . /colovu/lib/libfs.sh . /colovu/lib/liblog.sh @@ -128,30 +127,6 @@ app_generate_conf() { app_update_conf } -# 设置环境变量 JVMFLAGS -# 参数: -# $1 - value -app_export_jvmflags() { - local -r value="${1:?value is required}" - - export JVMFLAGS="${JVMFLAGS} ${value}" - echo "export JVMFLAGS=\"${JVMFLAGS}\"" > "${APP_CONF_DIR}/java.env" -} - -# 配置 HEAP 大小 -# 参数: -# $1 - HEAP 大小 -app_configure_heap_size() { - local -r heap_size="${1:?heap_size is required}" - - if [[ "${JVMFLAGS}" =~ -Xm[xs].*-Xm[xs] ]]; then - LOG_D "Using specified values (JVMFLAGS=${JVMFLAGS})" - else - LOG_D "Setting '-Xmx${heap_size}m -Xms${heap_size}m' heap options..." - app_export_jvmflags "-Xmx${heap_size}m -Xms${heap_size}m" - fi -} - # 检测用户参数信息是否满足条件; 针对部分权限过于开放情况,打印提示信息 app_verify_minimum_env() { local error_code=0 @@ -232,68 +207,72 @@ app_start_server_bg() { LOG_I "Starting ${APP_NAME} in background..." - # 使用内置脚本启动服务 - #local start_command="zkServer.sh start" - #if is_boolean_yes "${ENV_DEBUG}"; then - # $start_command & - #else - # $start_command >/dev/null 2>&1 & - #fi - - # 使用内置命令启动服务 - # if [[ "${ENV_DEBUG:-false}" = true ]]; then - # debug_execute "rabbitmq-server" & - #else - # debug_execute "rabbitmq-server" >/dev/null 2>&1 & - #fi + # 使用 debug_execute 并以守护进程方式启动服务 + # debug_execute "zkServer.sh" start + # debug_execute "redis-server" "--daemonize" "yes" - LOG_D "Checking ${APP_NAME} ready status..." - local counter=10 - while ! app_is_server_running ; do - LOG_D "Waiting for ${APP_NAME} to ready ... $counter" - if [[ "$counter" -ne 0 ]]; then - break + # 直接使用应用命令并以守护进程方式启动服务 + # 使用内置命令启动服务 + # if is_boolean_yes ${ENV_DEBUG}; then + # "rabbitmq-server" & + # else + # "rabbitmq-server" >/dev/null 2>&1 & + # fi + + # 使用端口检测方式 + # app_wait_service "${APP_HOST}:${APP_PORT}" + + # 使用 PID 文件检测方式 + local counter=30 + while app_is_server_not_running ; do + sleep 1 + counter=$(( counter - 1 )) + if (( counter <= 0 )); then + LOG_E "${APP_NAME} is not ready after 30 seconds" + exit 1 fi - sleep 1; - counter=$((counter - 1)) + LOG_D "Waiting for ${APP_NAME} to start ... $counter" done } # 停止应用服务 app_stop_server() { - if app_is_server_running ; then - LOG_I "Stopping ${APP_NAME}..." + app_is_server_not_running && return + + LOG_I "Stopping ${APP_NAME}..." + + # 使用 debug_execute 关闭服务 + # debug_execute "zkServer.sh" stop + # debug_execute "redis-cli" shutdown + + # 直接使用内置命令停止服务 + # if is_boolean_yes ${ENV_DEBUG}; then + # rabbitmqctl stop + #else + # rabbitmqctl stop >/dev/null 2>&1 + #fi - # 使用 PID 文件 kill 进程 - stop_service_using_pid "$APP_PID_FILE" + # 使用 PID 文件 kill 进程(不建议) + # stop_service_using_pid "$APP_PID_FILE" - # 使用内置命令停止服务 - #debug_execute "rabbitmqctl" stop - - # 使用内置脚本关闭服务 - #if [[ "$ENV_DEBUG" = true ]]; then - # "zkServer.sh" stop - #else - # "zkServer.sh" stop >/dev/null 2>&1 - #fi - - # 检测停止是否完成 - LOG_D "Checking ${APP_NAME} running status..." - local counter=10 - while [[ "$counter" -ne 0 ]] && app_is_server_running; do - LOG_D "Waiting for ${APP_NAME} to stop ... $counter" - sleep 1 - counter=$((counter - 1)) - done - fi + # 检测停止是否完成 + local counter=30 + while app_is_server_running ; do + sleep 1 + counter=$(( counter - 1 )) + if (( counter <= 0 )); then + LOG_E "${APP_NAME} is not stoped after 30 seconds" + exit 1 + fi + LOG_D "Waiting for ${APP_NAME} to stop ... $counter" + done } # 检测应用服务是否在后台运行中 app_is_server_running() { - LOG_D "Check if ${APP_NAME} is running..." local pid - pid="$(get_pid_from_file '${APP_PID_FILE}')" - LOG_D "${APP_NAME} PID: ${pid}" + pid="$(get_pid_from_file ${APP_PID_FILE})" + LOG_D "Checking ${APP_NAME} running status with PID: ${pid}" if [[ -n "${pid}" ]]; then is_service_running "${pid}" @@ -312,7 +291,8 @@ app_is_server_not_running() { # 清理初始化应用时生成的临时文件 app_clean_tmp_file() { - LOG_D "Clean ${APP_NAME} tmp files for init..." + LOG_D "Clean ${APP_NAME} tmp files ..." + local -r -a files=( "${APP_PID_FILE}" ) @@ -320,95 +300,108 @@ app_clean_tmp_file() { for file in ${files[@]}; do if [[ -f "$file" ]]; then LOG_D " Remove $file" - rm "$file" + rm -rf "$file" fi done } -# 用户自定义的前置初始化操作,依次执行目录 preinitdb.d 中的初始化脚本 -# 执行完毕后,生成文件 ${APP_DATA_DIR}/.custom_preinit_flag +# 用户自定义的前置初始化操作,依次执行目录 preinit.d 中的初始化脚本 +# 执行完毕后,生成以当前时间命名的'.tar'的文件,包含执行记录、已执行的脚本,同时删除已执行的脚本 app_custom_preinit() { LOG_I "Process pre-init for ${APP_NAME}..." - # 检测用户配置文件目录是否存在 preinitdb.d 文件夹,如果存在,尝试执行目录中的初始化脚本 - if [ -d "${APP_CONF_DIR}/preinitdb.d" ]; then - # 检测数据存储目录是否存在已初始化标志文件;如果不存在,检索可执行脚本文件并进行初始化操作 - if [[ -n $(find "${APP_CONF_DIR}/preinitdb.d/" -type f -regex ".*\.\(sh\)") ]] && \ - [[ ! -f "${APP_DATA_DIR}/.custom_preinit_flag" ]]; then - LOG_I "Process custom pre-init scripts from /srv/conf/${APP_NAME}/preinitdb.d..." + # 检测用户配置文件目录是否存在 preinit.d 文件夹,如果存在,尝试执行目录中的初始化脚本 + if [[ -d "${APP_CONF_DIR}/preinit.d" ]] && [[ -n $(find "${APP_CONF_DIR}/preinit.d/" -type f -regex ".*\.\(sh\)") ]]; then + echo "$(date '+%Y-%m-%d %H:%M:%S') : Init success." > "${APP_CONF_DIR}/preinit.d/preinit_info" + local tarFile="preinit-$(date '+%Y-%m-%d-%H%M%S').tar" + tar --remove-files -cf "${tarFile}" "${APP_CONF_DIR}/preinit.d/preinit_info" - # 检索所有可执行脚本,排序后执行 - find "${APP_CONF_DIR}/preinitdb.d/" -type f -regex ".*\.\(sh\)" | sort | process_init_files - - touch "${APP_DATA_DIR}/.custom_preinit_flag" - echo "$(date '+%Y-%m-%d %H:%M:%S') : Init success." >> "${APP_DATA_DIR}/.custom_preinit_flag" - LOG_I "Custom preinit for ${APP_NAME} complete." - else - LOG_I "Custom preinit for ${APP_NAME} already done before, skipping initialization." - fi + for f in $(find "${APP_CONF_DIR}/preinit.d/" -type f -regex ".*\.\(sh\)" | sort); do + LOG_D " Process: ${f}" + process_init_files "${f}" + tar --remove-files -f "${tarFile}" -r "${f}" + done fi } # 应用默认初始化操作 -# 执行完毕后,生成文件 ${APP_CONF_DIR}/.app_init_flag 及 ${APP_DATA_DIR}/.data_init_flag 文件 app_default_init() { LOG_I "Process default init for ${APP_NAME}..." + # 特殊情况下,生成默认配置文件(如默认不存在或仅存在 sample 配置文件) + app_generate_conf + + # 更新配置文件 app_update_conf + + # 启用远程访问 app_enable_remote_connections } -# 用户自定义的应用初始化操作,依次执行目录initdb.d中的初始化脚本 -# 执行完毕后,生成文件 ${APP_DATA_DIR}/.custom_init_flag +# 用户自定义的应用初始化操作,依次执行目录 initdb.d 中的初始化脚本 +# 执行完毕后,生成以当前时间命名的'.tar'的文件,包含执行记录、已执行的脚本,同时删除已执行的脚本 app_custom_init() { - LOG_I "Process customer init ${APP_NAME}..." + LOG_I "Process DB-init for ${APP_NAME}..." - # 检测用户配置文件目录是否存在 initdb.d 文件夹,如果存在,尝试执行目录中的初始化脚本 - if [ -d "${APP_CONF_DIR}/initdb.d" ]; then - # 检测数据存储目录是否存在已初始化标志文件;如果不存在,检索可执行脚本文件并进行初始化操作 - if [[ -n $(find "${APP_CONF_DIR}/initdb.d/" -type f -regex ".*\.\(sh\|sql\|sql.gz\)") ]] && \ - [[ ! -f "${APP_DATA_DIR}/.custom_init_flag" ]]; then - LOG_I "Process custom init scripts from ${APP_CONF_DIR}/initdb.d..." + # 检测用户配置文件目录是否存在 preinit.d 文件夹,如果存在,尝试执行目录中的初始化脚本 + if [[ -d "${APP_CONF_DIR}/initdb.d" ]] && [[ -n $(find "${APP_CONF_DIR}/initdb.d/" -type f -regex ".*\.\(sh\|sql\|sql.gz\)") ]]; then + echo "$(date '+%Y-%m-%d %H:%M:%S') : Init success." > "${APP_CONF_DIR}/initdb.d/dbinit_info" + local tarFile="initdb-$(date '+%Y-%m-%d-%H%M%S').tar" + tar --remove-files -cf "${tarFile}" "${APP_CONF_DIR}/initdb.d/initdb_info" - # 启动后台服务 - app_disable_remote_connections - app_start_server_bg + # 启动后台服务 + app_disable_remote_connections + app_start_server_bg - # 检索所有可执行脚本,排序后执行 - find "${APP_CONF_DIR}/initdb.d/" -type f -regex ".*\.\(sh\|sql\|sql.gz\)" | sort | while read -r f; do - case "$f" in - *.sh) - if [[ -x "$f" ]]; then - LOG_D "Executing $f"; "$f" - else - LOG_D "Sourcing $f"; . "$f" - fi - ;; - *.sql) - LOG_D "Executing $f"; - postgresql_execute "${PG_DATABASE}" "${PG_INITSCRIPTS_USERNAME}" "${PG_INITSCRIPTS_PASSWORD}" < "$f" - ;; - *.sql.gz) - LOG_D "Executing $f"; - gunzip -c "$f" | postgresql_execute "${PG_DATABASE}" "${PG_INITSCRIPTS_USERNAME}" "${PG_INITSCRIPTS_PASSWORD}" - ;; - *) - LOG_D "Ignoring $f" ;; - esac - done + for f in $(find "${APP_CONF_DIR}/initdb.d/" -type f -regex ".*\.\(sh\|sql\|sql.gz\)" | sort); do + case "$f" in + *.sh) + LOG_D " Process Shell: ${f}" + process_init_files "$f" + ;; + *.sql) + LOG_D " Process SQL: ${f}"; + postgresql_execute "${PG_DATABASE}" "${PG_INITSCRIPTS_USERNAME}" "${PG_INITSCRIPTS_PASSWORD}" < "$f" + ;; + *.sql.gz) + LOG_D " Process SQLs in ${f}"; + gunzip -c "$f" | postgresql_execute "${PG_DATABASE}" "${PG_INITSCRIPTS_USERNAME}" "${PG_INITSCRIPTS_PASSWORD}" < + ;; + *) + LOG_D " Ignoring $f" + ;; + esac - touch "${APP_DATA_DIR}/.custom_init_flag" - echo "$(date '+%Y-%m-%d %H:%M:%S') : Init success." >> "${APP_DATA_DIR}/.custom_init_flag" - LOG_I "Custom init for ${APP_NAME} complete." + tar --remove-files -f "${tarFile}" -r "${f}" + done - # 检测服务是否运行中;如果运行,则停止后台服务 - app_is_server_running && app_stop_server - app_clean_tmp_file - app_enable_remote_connections - else - LOG_I "Custom init for ${APP_NAME} already done before, skipping initialization." - fi + # 检测服务是否运行中;如果运行,则停止后台服务 + app_is_server_running && app_stop_server + app_clean_tmp_file + app_enable_remote_connections fi } +# 设置环境变量 JVMFLAGS +# 参数: +# $1 - value +app_export_jvmflags() { + local -r value="${1:?value is required}" + export JVMFLAGS="${JVMFLAGS} ${value}" + echo "export JVMFLAGS=\"${JVMFLAGS}\"" > "${APP_CONF_DIR}/java.env" +} + +# 配置 HEAP 大小 +# 参数: +# $1 - HEAP 大小 +app_configure_heap_size() { + local -r heap_size="${1:?heap_size is required}" + + if [[ "${JVMFLAGS}" =~ -Xm[xs].*-Xm[xs] ]]; then + LOG_D "Using specified values (JVMFLAGS=${JVMFLAGS})" + else + LOG_D "Setting '-Xmx${heap_size}m -Xms${heap_size}m' heap options..." + app_export_jvmflags "-Xmx${heap_size}m -Xms${heap_size}m" + fi +} diff --git a/customer/usr/local/bin/entry.sh b/customer/usr/local/bin/entry.sh index a663c6b..a1a112c 100755 --- a/customer/usr/local/bin/entry.sh +++ b/customer/usr/local/bin/entry.sh @@ -1,5 +1,5 @@ #!/usr/bin/dumb-init /bin/bash -# Ver: 1.5 by Endial Fang (endial@126.com) +# Ver: 1.6 by Endial Fang (endial@126.com) # # 容器入口脚本;当前脚本执行完毕时,使用默认用户执行镜像 CMD 定义的命令(默认为'/usr/local/bin/run.sh') @@ -20,7 +20,7 @@ LOG_I "** Processing entry.sh **" if [[ "$(id -u)" == '0' ]] && [[ "$1" == "run.sh" ]]; then print_welcome_info /usr/local/bin/setup.sh - /usr/local/bin/init.sh + gosu "${APP_USER}" /usr/local/bin/init.sh # 执行应用启动脚本并替换当前进程 exec gosu "${APP_USER}" "$@" @@ -29,7 +29,7 @@ fi # 处理 root 用户**且**使用init.sh脚本时的初始化 if [[ "$(id -u)" == '0' ]] && [[ "$1" == "init.sh" ]]; then /usr/local/bin/setup.sh - /usr/local/bin/init.sh + exec gosu "${APP_USER}" /usr/local/bin/init.sh fi # 处理非以上情形的自定义命令 diff --git a/customer/usr/local/bin/environment.sh b/customer/usr/local/bin/environment.sh index 889fc77..5b6b46b 100644 --- a/customer/usr/local/bin/environment.sh +++ b/customer/usr/local/bin/environment.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Ver: 1.2 by Endial Fang (endial@126.com) +# Ver: 1.3 by Endial Fang (endial@126.com) # # 应用环境变量定义及初始化 @@ -23,7 +23,7 @@ unset app_env_file_lists # 应用路径参数(Dockerfile 已定义:APP_NAME、APP_VER,可能定义 APP_USER、APP_EXEC) export APP_EXEC="${APP_EXEC:-${APP_NAME}}" export APP_USER="${APP_USER:-${APP_NAME}}" -export APP_GROUP="${APP_USER:-${APP_NAME}}" +export APP_GROUP="${APP_GROUP:-${APP_USER}}" export APP_HOME="${APP_HOME:-/srv/${APP_NAME}}" export APP_BASE="${APP_BASE:-/usr/local/${APP_NAME}}" diff --git a/customer/usr/local/bin/init.sh b/customer/usr/local/bin/init.sh index 5272030..fe47000 100755 --- a/customer/usr/local/bin/init.sh +++ b/customer/usr/local/bin/init.sh @@ -1,7 +1,7 @@ #!/bin/bash -# Ver: 1.3 by Endial Fang (endial@126.com) +# Ver: 1.4 by Endial Fang (endial@126.com) # -# 应用初始化脚本 +# 应用初始化脚本;当前脚本使用‘gosu ${APP_USER}’方式切换至用户空间执行 # 设置 shell 执行参数,可使用'-'(打开)'+'(关闭)控制。常用: # -e: 命令执行错误则报错; -u: 变量未定义则报错; -x: 打印实际待执行的命令行; -o pipefail: 设置管道中命令遇到失败则报错 @@ -13,6 +13,7 @@ set -euo pipefail LOG_I "** Processing init.sh **" trap "app_stop_server" EXIT +# 检测最小环境变量配置 app_verify_minimum_env # 执行应用预初始化操作 diff --git a/customer/usr/local/bin/setup.sh b/customer/usr/local/bin/setup.sh index 065da69..9ddd57c 100755 --- a/customer/usr/local/bin/setup.sh +++ b/customer/usr/local/bin/setup.sh @@ -21,7 +21,7 @@ APP_DIRS+=(${APP_HOME}/conf ${APP_HOME}/data ${APP_HOME}/cert ${APP_HOME}/log) LOG_I "Ensure directory exists: ${APP_DIRS[@]}" for dir in ${APP_DIRS[@]}; do - ensure_dir_exists ${dir} + ensure_dir_exists ${dir} ${APP_USER} done # 检测指定文件是否在配置文件存储目录存在,如果不存在则拷贝(新挂载数据卷、手动删除都会导致不存在)