diff --git a/rootfs/tmp/etc/docker/daemon.json b/rootfs/tmp/etc/docker/daemon.json index 0b45dce..b89966b 100644 --- a/rootfs/tmp/etc/docker/daemon.json +++ b/rootfs/tmp/etc/docker/daemon.json @@ -5,6 +5,7 @@ "experimental": true, "pidfile": "/tmp/docker.pid", "cgroup-parent": "/docker", + "storage-driver": "fuse-overlayfs", "default-address-pools": [ {"base": "172.17.0.0/12", "size": 24}, {"base": "192.168.0.0/16", "size": 24}, diff --git a/rootfs/tmp/etc/gitea/app.ini b/rootfs/tmp/etc/gitea/app.ini index 9816631..d281661 100644 --- a/rootfs/tmp/etc/gitea/app.ini +++ b/rootfs/tmp/etc/gitea/app.ini @@ -200,6 +200,12 @@ REVERSE_PROXY_AUTHENTICATION_USER = X-WEBAUTH-USER REVERSE_PROXY_AUTHENTICATION_EMAIL = X-WEBAUTH-EMAIL REVERSE_PROXY_AUTHENTICATION_FULL_NAME = X-WEBAUTH-FULLNAME X_FRAME_OPTIONS = SAMEORIGIN +ALLOWED_HOST_LIST = * +; explicit: defaults to true starting Gitea 1.23 and deprecates ?token=/?access_token= +; auth entirely in 1.24 โ€” pin false so query-token API calls keep authenticating on +; upgrade instead of silently downgrading to anonymous; migrate callers to +; "Authorization: token " when convenient +DISABLE_QUERY_AUTH_TOKEN = false ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; [time] DEFAULT_UI_LOCATION = REPLACE_TZ @@ -224,7 +230,6 @@ http.sslVerify = false [webhook] QUEUE_LENGTH = 1000 DELIVER_TIMEOUT = 30 -ALLOWED_HOST_LIST = * SKIP_TLS_VERIFY = true PAGING_NUM = 10 PROXY_URL = diff --git a/rootfs/usr/local/bin/entrypoint.sh b/rootfs/usr/local/bin/entrypoint.sh index 344a1de..973800f 100755 --- a/rootfs/usr/local/bin/entrypoint.sh +++ b/rootfs/usr/local/bin/entrypoint.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash # shellcheck shell=bash # - - - - - - - - - - - - - - - - - - - - - - - - - -##@Version : 202606261500-git +##@Version : 202609030524-git # @@Author : Jason Hempstead # @@Contact : jason@casjaysdev.pro # @@License : WTFPL @@ -20,6 +20,8 @@ # - - - - - - - - - - - - - - - - - - - - - - - - - # shellcheck disable=SC1001,SC1003,SC2001,SC2003,SC2016,SC2031,SC2090,SC2115,SC2120,SC2155,SC2199,SC2229,SC2317,SC2329 # - - - - - - - - - - - - - - - - - - - - - - - - - +VERSION="202609030524-git" +# - - - - - - - - - - - - - - - - - - - - - - - - - # run trap command on exit trap 'retVal=$?;[ "$SERVICE_IS_RUNNING" != "yes" ] && [ -f "$SERVICE_PID_FILE" ] && rm -Rf "$SERVICE_PID_FILE";exit $retVal' INT TERM trap 'retVal=$?;[ "$SERVICE_IS_RUNNING" != "yes" ] && [ -f "$SERVICE_PID_FILE" ] && rm -Rf "$SERVICE_PID_FILE";exit $retVal' SIGPWR 2>/dev/null || true @@ -330,7 +332,7 @@ if [ "$ENTRYPOINT_FIRST_RUN" != "no" ]; then # if ipv6 add it to /etc/hosts if [ "$UPDATE_FILE_HOSTS" = "yes" ]; then echo "# known hostname mappings" >"/etc/hosts" 2>/dev/null || true - if [ -n "$(ip a 2>/dev/null | grep 'inet6.*::' || ifconfig 2>/dev/null | grep 'inet6.*::')" ]; then + if [ -n "$(ip a 2>/dev/null | grep -- 'inet6.*::' || ifconfig 2>/dev/null | grep -- 'inet6.*::')" ]; then __printf_space "40" "::1" "localhost" >>"/etc/hosts" 2>/dev/null || true __printf_space "40" "127.0.0.1" "localhost" >>"/etc/hosts" 2>/dev/null || true else @@ -371,7 +373,7 @@ if [ "$ENTRYPOINT_FIRST_RUN" != "no" ]; then # - - - - - - - - - - - - - - - - - - - - - - - - - # import hosts file into container if [ -f "/usr/local/etc/hosts" ] && [ "$UPDATE_FILE_HOSTS" = "yes" ]; then - grep -vF "$HOSTNAME" "/usr/local/etc/hosts" 2>/dev/null >>"/etc/hosts" || true + grep -vF -- "$HOSTNAME" "/usr/local/etc/hosts" 2>/dev/null >>"/etc/hosts" || true fi # - - - - - - - - - - - - - - - - - - - - - - - - - # import resolv.conf file into container @@ -431,9 +433,16 @@ fi # - - - - - - - - - - - - - - - - - - - - - - - - - # if no pid assume container restart - clean stale files on restart if [ -f "$ENTRYPOINT_PID_FILE" ]; then - # Check if the PID in the file is still running + # Check if the PID in the file is still running. /run persists across + # `docker restart` (same container filesystem), but the PID namespace + # resets every restart, so a recorded PID can coincidentally be reused by + # an unrelated early-boot process in the new namespace. A bare `kill -0` + # would then wrongly treat this as "entrypoint already running" and skip + # __start_init_scripts entirely on a genuine restart, so also require the + # live process's own cmdline to actually be this entrypoint script. entrypoint_pid=$(<"$ENTRYPOINT_PID_FILE") 2>/dev/null - if [ -n "$entrypoint_pid" ] && kill -0 "$entrypoint_pid" 2>/dev/null; then + if [ -n "$entrypoint_pid" ] && kill -0 "$entrypoint_pid" 2>/dev/null \ + && grep -q -- "entrypoint.sh" "/proc/$entrypoint_pid/cmdline" 2>/dev/null; then # Process is still running, don't restart services START_SERVICES="no" touch "$ENTRYPOINT_PID_FILE" @@ -550,7 +559,7 @@ cron) shift 1 __cron "$@" & __log_info "Cron script is running with PID: $!" - exit + exit 0 ;; # backup data and config dirs backup) @@ -581,7 +590,7 @@ healthcheck) services+="$name " done fi - services="$(printf '%s\n' $services | sort -u | grep -v '^$')" + services="$(printf '%s\n' $services | sort -u | grep -v -- '^$')" for proc in $services; do if [ -n "$proc" ]; then if ! __pgrep "$proc"; then @@ -592,7 +601,7 @@ healthcheck) done for port in $healthPorts; do if command -v netstat &>/dev/null && [ -n "$port" ]; then - if ! netstat -taupln | grep -q ":$port "; then + if ! netstat -taupln | grep -q -- ":$port "; then echo "$port isn't open" >&2 healthStatus=$((healthStatus + 1)) fi @@ -622,7 +631,7 @@ ports) # show running processes procs) shift 1 - ps="$(__ps axco command 2>/dev/null | grep -vE '^(COMMAND|grep|ps)$' | sort -u)" + ps="$(__ps axco command 2>/dev/null | grep -vE -- '^(COMMAND|grep|ps)$' | sort -u)" [ -n "$ps" ] && printf '%s\n%s\n' "Found the following processes" "$ps" | tr '\n' ' ' exit $? ;; @@ -659,7 +668,7 @@ start) if [ $# -eq 0 ]; then scripts="$(ls -A "/usr/local/etc/docker/init.d")" [ -n "$scripts" ] && echo "$scripts" || echo "No scripts found in: /usr/local/etc/docker/init.d" - exit + exit 0 elif [ "$1" = "all" ]; then shift $# if [ "$START_SERVICES" = "yes" ]; then diff --git a/rootfs/usr/local/bin/start-runners b/rootfs/usr/local/bin/start-runners index c8010bc..ee5569a 100755 --- a/rootfs/usr/local/bin/start-runners +++ b/rootfs/usr/local/bin/start-runners @@ -1,8 +1,31 @@ #!/usr/bin/env bash -# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +# shellcheck shell=bash +# - - - - - - - - - - - - - - - - - - - - - - - - - +##@Version : 202609030524-git +# @@Author : Jason Hempstead +# @@Contact : jason@casjaysdev.pro +# @@License : LICENSE.md +# @@ReadME : start-runners --help +# @@Copyright : Copyright: (c) 2026 Jason Hempstead, Casjays Developments +# @@Created : Friday, Jun 05, 2026 18:14 EDT +# @@File : start-runners +# @@Description : Start act runners +# @@Changelog : New script +# @@TODO : Better documentation +# @@Other : +# @@Resource : +# @@Terminal App : no +# @@sudo/root : no +# @@Template : shell/bash +# - - - - - - - - - - - - - - - - - - - - - - - - - +# shellcheck disable=SC1001,SC1003,SC2001,SC2003,SC2016,SC2031,SC2090,SC2115,SC2120,SC2155,SC2199,SC2229,SC2317,SC2329 +# - - - - - - - - - - - - - - - - - - - - - - - - - +VERSION="202609030524-git" set -e # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -trap 'retVal=$?; echo "โŒ Fatal error occurred: Exit code $retVal at line $LINENO in command: $BASH_COMMAND"; kill -TERM 1' ERR +trap 'retVal=$?; emoji=$( [ -z "$NO_COLOR" ] && echo "โŒ " || echo "" ); \ +echo "${emoji}Fatal error occurred: Exit code $retVal at line $LINENO in command: $BASH_COMMAND"; \ +kill -TERM 1' ERR trap 'retVal=$?;if [ "$SERVICE_IS_RUNNING" != "yes" ] && [ -f "$SERVICE_PID_FILE" ]; then rm -Rf "$SERVICE_PID_FILE"; fi;exit $retVal' SIGINT SIGTERM SIGPWR # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # Function to __log messages with timestamp @@ -33,7 +56,37 @@ if [ -z "$SERVER_TOKEN" ]; then exit 1 fi # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -RUNNER_LABELS="${RUNNER_LABELS:-linux:host,node14:docker://node:14,node16:docker://node:16,node18:docker://node:18,node20:docker://node:20,node22:docker://node:22,node:docker://node:latest,perl:docker://perl:latest,ruby:docker://ruby:latest,python:docker://python:latest,python3:docker://python:latest,php7:docker://casjaysdevdocker/php:7,php8:docker://casjaysdevdocker/php:8,php:docker://casjaysdevdocker/php:latest,alpine:docker://casjaysdev/alpine:latest,debian:docker://casjaysdev/debian:latest,ubuntu:docker://casjaysdev/ubuntu:latest,rhel:docker://casjaysdev/almalinux:latest,redhat:docker://casjaysdev/almalinux:latest,almalinux:docker://casjaysdev/almalinux:latest,act_runner:docker://catthehacker/ubuntu:full-latest,ubuntu-latest:docker://catthehacker/ubuntu:full-latest}" +if [ -z "$RUNNER_LABELS" ]; then + _default_runner_labels=( + "linux:host" + "node14:docker://node:14" + "node16:docker://node:16" + "node18:docker://node:18" + "node20:docker://node:20" + "node22:docker://node:22" + "node:docker://node:latest" + "perl:docker://perl:latest" + "ruby:docker://ruby:latest" + "python:docker://python:latest" + "python3:docker://python:latest" + "php7:docker://casjaysdevdocker/php:7" + "php8:docker://casjaysdevdocker/php:8" + "php:docker://casjaysdevdocker/php:latest" + "alpine:docker://casjaysdev/alpine:latest" + "debian:docker://casjaysdev/debian:latest" + "ubuntu:docker://casjaysdev/ubuntu:latest" + "rhel:docker://casjaysdev/almalinux:latest" + "redhat:docker://casjaysdev/almalinux:latest" + "almalinux:docker://casjaysdev/almalinux:latest" + "act_runner:docker://catthehacker/ubuntu:full-latest" + "ubuntu-latest:docker://catthehacker/ubuntu:full-latest" + ) + RUNNER_LABELS="$( + IFS=, + echo "${_default_runner_labels[*]}" + )" + unset _default_runner_labels +fi # Determine number of runners to start RUNNERS_START=${RUNNERS_START:-1} # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/rootfs/usr/local/etc/docker/functions/entrypoint.sh b/rootfs/usr/local/etc/docker/functions/entrypoint.sh index 263836a..21d1602 100644 --- a/rootfs/usr/local/etc/docker/functions/entrypoint.sh +++ b/rootfs/usr/local/etc/docker/functions/entrypoint.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash # shellcheck shell=bash # - - - - - - - - - - - - - - - - - - - - - - - - - -##@Version : 202607271325-git +##@Version : 202609030524-git # @@Author : Jason Hempstead # @@Contact : git-admin@casjaysdev.pro # @@License : LICENSE.md @@ -20,6 +20,8 @@ # - - - - - - - - - - - - - - - - - - - - - - - - - # shellcheck disable=SC1001,SC1003,SC2001,SC2003,SC2016,SC2031,SC2090,SC2115,SC2120,SC2155,SC2199,SC2229,SC2317,SC2329 # - - - - - - - - - - - - - - - - - - - - - - - - - +VERSION="202609030524-git" +# - - - - - - - - - - - - - - - - - - - - - - - - - # setup debugging - https://www.gnu.org/software/bash/manual/html_node/The-Set-Builtin.html if [ -f "/config/.debug" ] && [ -z "$DEBUGGER_OPTIONS" ]; then export DEBUGGER_OPTIONS="$(<"/config/.debug")" @@ -77,7 +79,7 @@ __rm() { fi return 0 } -__grep_test() { grep -sh "$1" "$2" 2>/dev/null | grep -qwF "${3:-$1}"; } +__grep_test() { grep -sh -- "$1" "$2" 2>/dev/null | grep -qwF -- "${3:-$1}"; } __netstat() { command -v netstat &>/dev/null || { [ "$DEBUGGER" = "on" ] && echo "Warning: netstat command not found" >&2 || true @@ -89,7 +91,7 @@ __cd() { [ -d "$1" ] || mkdir -p "$1" 2>/dev/null || return 1 builtin cd "$1" || return 1 } -__is_in_file() { [ -e "$2" ] && grep -Rsq "$1" "$2" 2>/dev/null; } +__is_in_file() { [ -e "$2" ] && grep -Rsq -- "$1" "$2" 2>/dev/null; } __curl() { curl -q -sfI --max-time 3 -k -o /dev/null "$@" 2>/dev/null || return 10; } __find() { local result @@ -108,7 +110,7 @@ __file_exists_with_content() { [ -n "$1" ] && [ -f "$1" ] && [ -s "$1" ] || retu __sed() { sed -i "s|$1|$2|g" "$3" 2>/dev/null || return 1; } __ps() { command -v ps &>/dev/null || return 10 - ps "$@" 2>/dev/null | sed 's|:||g' | grep -Fw " ${1:-$SERVICE_NAME}$" || return 10 + ps "$@" 2>/dev/null | sed 's|:||g' | grep -Fw -- " ${1:-$SERVICE_NAME}$" || return 10 } __is_dir_empty() { [ -n "$1" ] && [ -d "$1" ] || return 1 @@ -138,7 +140,7 @@ __pgrep() { while [ $count -ge 0 ]; do pgrep -x "$srvc" &>/dev/null && return 0 pgrep -f "$srvc" &>/dev/null && return 0 - ps -eo comm 2>/dev/null | grep -qxF "$srvc" && return 0 + ps -eo comm 2>/dev/null | grep -qxF -- "$srvc" && return 0 [ $count -gt 0 ] && sleep 1 count=$((count - 1)) done @@ -166,7 +168,7 @@ __is_running() { if command -v pgrep &>/dev/null; then pgrep -f "$pat" &>/dev/null else - ps -eo args 2>/dev/null | grep -v grep | grep -Eq "$pat" + ps -eo args 2>/dev/null | grep -v -- grep | grep -Eq -- "$pat" fi } __get_pid() { @@ -205,19 +207,34 @@ __no_exit() { local failed_services="" local failure_count=0 - # only return early if the recorded PID is still alive; a leftover - # pid file from a prior container life (docker restart) would otherwise - # cause us to exit instead of entering the monitor loop. + # only return early if the recorded PID is still alive AND it is actually + # this same monitor loop (not just some unrelated process that happens to + # have been assigned the same number). /run persists across `docker + # restart` (same container filesystem), but the PID namespace resets on + # every restart, so a low PID recorded before the restart can coincidentally + # be reused by an unrelated early-boot process within the new namespace. A + # bare `kill -0` on that number alone would then wrongly report the old + # monitor as still running and `return 0` here without ever exec'ing the + # replacement monitor loop below โ€” silently leaving the container with no + # supervisor loop, so it exits as soon as the caller's own script reaches + # its end. Guarding on the "__no_exit_monitor_loop" marker (embedded in the + # exec'd bash -c command below, so it shows up in that PID's own cmdline) + # confirms the live process is actually this monitor, not a coincidental + # PID-reuse false positive. if [ -f "/run/.no_exit.pid" ]; then local no_exit_pid no_exit_pid=$(<"/run/.no_exit.pid") 2>/dev/null - if [ -n "$no_exit_pid" ] && kill -0 "$no_exit_pid" 2>/dev/null; then + if [ -n "$no_exit_pid" ] && kill -0 "$no_exit_pid" 2>/dev/null \ + && grep -q -- "__no_exit_monitor_loop" "/proc/$no_exit_pid/cmdline" 2>/dev/null; then return 0 fi rm -f /run/.no_exit.pid 2>/dev/null || true fi exec bash -c " + # __no_exit_monitor_loop marker: identifies this process's cmdline as the + # genuine monitor loop, so a future __no_exit call can tell it apart from + # an unrelated process that coincidentally reused this PID after a restart trap 'echo \"Container shutdown requested\"; rm -f /run/.no_exit.pid /run/*.pid; exit 0' TERM INT echo \$\$ > /run/.no_exit.pid failed_services=\"\" @@ -267,7 +284,8 @@ __banner() { } # - - - - - - - - - - - - - - - - - - - - - - - - - __service_banner() { - local icon="${1:-๐Ÿ”ง}" + local icon="${1:-}" + [ -z "$icon" ] && icon="$( [ -z "$NO_COLOR" ] && echo "๐Ÿ”ง" || echo "" )" local message="${2:-Processing}" local service="${3:-service}" local full_message="$message $service" @@ -682,7 +700,7 @@ __file_copy() { __generate_random_uids() { local set_random_uid=$((100 + RANDOM % 900)) while :; do - if grep -shq "x:.*:$set_random_uid:" "/etc/group" && ! grep -shq "x:$set_random_uid:.*:" "/etc/passwd"; then + if grep -shq -- "x:.*:$set_random_uid:" "/etc/group" && ! grep -shq -- "x:$set_random_uid:.*:" "/etc/passwd"; then set_random_uid=$((set_random_uid + 1)) else echo "$set_random_uid" @@ -738,7 +756,7 @@ __fix_permissions() { change_group="${2:-${SERVICE_GROUP:-$change_user}}" [ -n "$RUNAS_USER" ] && [ "$RUNAS_USER" != "root" ] && change_user="$RUNAS_USER" && change_group="$change_user" if [ -n "$change_user" ]; then - if grep -shq "^$change_user:" "/etc/passwd"; then + if grep -shq -- "^$change_user:" "/etc/passwd"; then for permissions in $ADD_APPLICATION_DIRS $APPLICATION_DIRS; do if [ -n "$permissions" ] && [ -e "$permissions" ]; then chown -Rf "$change_user" "$permissions" 2>/dev/null @@ -748,7 +766,7 @@ __fix_permissions() { fi fi if [ -n "$change_group" ]; then - if grep -shq "^$change_group:" "/etc/group"; then + if grep -shq -- "^$change_group:" "/etc/group"; then for permissions in $ADD_APPLICATION_DIRS $APPLICATION_DIRS; do if [ -n "$permissions" ] && [ -e "$permissions" ]; then chgrp -Rf "$change_group" "$permissions" 2>/dev/null @@ -809,7 +827,7 @@ __set_user_group_id() { return 0 fi # Nothing to do if the user does not exist yet - if ! grep -shq "^$set_user:" "/etc/passwd" "/etc/group"; then + if ! grep -shq -- "^$set_user:" "/etc/passwd" "/etc/group"; then return 0 fi set_uid="$(__get_uid "$set_user" || echo "$set_uid")" @@ -852,7 +870,7 @@ __create_service_user() { return 1 fi # Check if user and group already exist - if grep -shq "^$create_user:" "/etc/passwd" && grep -shq "^$create_group:" "/etc/group"; then + if grep -shq -- "^$create_user:" "/etc/passwd" && grep -shq -- "^$create_group:" "/etc/group"; then return 0 fi # Override with RUNAS_USER if specified and not root @@ -898,7 +916,7 @@ __create_service_user() { if ! groupadd --force --system -g "$create_gid" "$create_group" 2>&1 | tee -a "$log_file"; then echo "Error: Failed to create group '$create_group'" >&2 exitStatus=$((exitStatus + 1)) - elif ! grep -shq "^$create_group:" "/etc/group"; then + elif ! grep -shq -- "^$create_group:" "/etc/group"; then echo "Error: Group '$create_group' not found in /etc/group after creation" >&2 exitStatus=$((exitStatus + 1)) fi @@ -906,10 +924,12 @@ __create_service_user() { # Create user if needed (only if group creation succeeded) if [ $exitStatus -eq 0 ] && [ -n "$create_user" ] && ! __check_for_user "$create_user"; then echo "Creating system user '$create_user' with UID $create_uid" - if ! useradd --system --uid "$create_uid" --gid "$create_group" --comment "Account for $create_user" --home-dir "$create_home_dir" --shell /bin/false "$create_user" 2>&1 | tee -a "$log_file"; then + if ! useradd --system --uid "$create_uid" --gid "$create_group" \ + --comment "Account for $create_user" --home-dir "$create_home_dir" \ + --shell /bin/false "$create_user" 2>&1 | tee -a "$log_file"; then echo "Error: Failed to create user '$create_user'" >&2 exitStatus=$((exitStatus + 1)) - elif ! grep -shq "^$create_user:" "/etc/passwd"; then + elif ! grep -shq -- "^$create_user:" "/etc/passwd"; then echo "Error: User '$create_user' not found in /etc/passwd after creation" >&2 exitStatus=$((exitStatus + 1)) fi @@ -933,7 +953,7 @@ __create_service_user() { echo "$create_user ALL=(ALL) NOPASSWD: ALL" >"/etc/sudoers.d/$create_user" 2>/dev/null || echo "Warning: Failed to create sudoers file for '$create_user'" >&2 chmod 0440 "/etc/sudoers.d/$create_user" 2>/dev/null fi - elif [ -f "/etc/sudoers" ] && ! grep -qs "^$create_user " "/etc/sudoers"; then + elif [ -f "/etc/sudoers" ] && ! grep -qs -- "^$create_user " "/etc/sudoers"; then echo "$create_user ALL=(ALL) NOPASSWD: ALL" >>"/etc/sudoers" 2>/dev/null || echo "Warning: Failed to add '$create_user' to sudoers" >&2 fi SERVICE_UID="$create_uid" @@ -1030,7 +1050,7 @@ __start_init_scripts() { touch "$pidFile" name="${init##*/}" service="${name#*-}"; service="${service%.sh}" - [ "$DEBUGGER" = "on" ] && __service_banner "๐Ÿ”ง" "Executing service script:" "${init##*/}" || true + [ "$DEBUGGER" = "on" ] && __service_banner "$( [ -z "$NO_COLOR" ] && echo "๐Ÿ”ง" || echo "" )" "Executing service script:" "${init##*/}" || true # Execute the init script and capture the exit code (subshell isolates exit calls) if ( source "$init" ); then # Check if service was disabled first @@ -1093,7 +1113,7 @@ __start_init_scripts() { else initStatus="1" critical_failures=$((critical_failures + 1)) - __service_banner "โŒ" "Service $service failed to start -" "check logs" + __service_banner "$( [ -z "$NO_COLOR" ] && echo "โŒ" || echo "" )" "Service $service failed to start -" "check logs" fi echo "" fi @@ -1103,12 +1123,24 @@ __start_init_scripts() { # Summary echo "" if [ $critical_failures -gt 0 ]; then - echo "โš ๏ธ Warning: $critical_failures critical service(s) reported failures" + if [ -z "$NO_COLOR" ]; then + echo "โš ๏ธ Warning: $critical_failures critical service(s) reported failures" + else + echo "Warning: $critical_failures critical service(s) reported failures" + fi if [ "$exit_on_failure" = "true" ] && [ $critical_failures -ge 2 ]; then - echo "โŒ Exiting due to multiple critical service failures (threshold: 2)" + if [ -z "$NO_COLOR" ]; then + echo "โŒ Exiting due to multiple critical service failures (threshold: 2)" + else + echo "Exiting due to multiple critical service failures (threshold: 2)" + fi return 1 else - echo "โ„น๏ธ Continuing with $critical_failures failure(s) - container may still be functional" + if [ -z "$NO_COLOR" ]; then + echo "โ„น๏ธ Continuing with $critical_failures failure(s) - container may still be functional" + else + echo "Continuing with $critical_failures failure(s) - container may still be functional" + fi fi else echo "โœ… All service initializations completed successfully" @@ -1516,22 +1548,22 @@ __switch_to_user() { local switch_user="${SERVICE_USER:-$RUNAS_USER}" if [ "$switch_user" = "root" ]; then su_exec="" - su_cmd() { eval "$@" || return 1; } + __su_cmd() { eval "$@" || return 1; } elif command -v gosu &>/dev/null; then su_exec="gosu $switch_user" - su_cmd() { $su_exec "$@" || return 1; } + __su_cmd() { $su_exec "$@" || return 1; } elif command -v runuser &>/dev/null; then su_exec="runuser -u $switch_user" - su_cmd() { $su_exec "$@" || return 1; } + __su_cmd() { $su_exec "$@" || return 1; } elif command -v sudo &>/dev/null; then su_exec="sudo -u $switch_user" - su_cmd() { $su_exec "$@" || return 1; } + __su_cmd() { $su_exec "$@" || return 1; } elif command -v su &>/dev/null; then su_exec="su -s /bin/sh - $switch_user" - su_cmd() { $su_exec -c "$@" || return 1; } + __su_cmd() { $su_exec -c "$@" || return 1; } else su_exec="" - su_cmd() { + __su_cmd() { echo "Can not switch to $switch_user: attempting to run as root" if ! eval "$@"; then return 1 diff --git a/rootfs/usr/local/etc/docker/init.d/05-dockerd.sh b/rootfs/usr/local/etc/docker/init.d/05-dockerd.sh index 337cfec..b32c3ba 100755 --- a/rootfs/usr/local/etc/docker/init.d/05-dockerd.sh +++ b/rootfs/usr/local/etc/docker/init.d/05-dockerd.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash # shellcheck shell=bash # - - - - - - - - - - - - - - - - - - - - - - - - - -##@Version : 202606261600-git +##@Version : 202609030524-git # @@Author : Jason Hempstead # @@Contact : jason@casjaysdev.pro # @@License : LICENSE.md @@ -20,6 +20,8 @@ # - - - - - - - - - - - - - - - - - - - - - - - - - # shellcheck disable=SC1001,SC1003,SC2001,SC2003,SC2016,SC2031,SC2090,SC2115,SC2120,SC2155,SC2199,SC2229,SC2317,SC2329 # - - - - - - - - - - - - - - - - - - - - - - - - - +VERSION="202609030524-git" +# - - - - - - - - - - - - - - - - - - - - - - - - - set -e # - - - - - - - - - - - - - - - - - - - - - - - - - # run trap command on exit @@ -43,7 +45,11 @@ __trap_err_handler() { fi # Critical error - but only fail if service hasn't started yet if [ "$SERVICE_IS_RUNNING" != "yes" ]; then - echo "โŒ Critical error (exit $retVal): $command" >&2 + if [ -z "$NO_COLOR" ]; then + echo "โŒ Critical error (exit $retVal): $command" >&2 + else + echo "Critical error (exit $retVal): $command" >&2 + fi kill -TERM 1 2>/dev/null || exit $retVal fi return 0 @@ -108,7 +114,11 @@ fi if [ -n "$SERVICE_NAME" ] && [ -f "/run/init.d/$SERVICE_NAME.pid" ]; then old_pid=$(<"/run/init.d/$SERVICE_NAME.pid") 2>/dev/null if [ -n "$old_pid" ] && ! kill -0 "$old_pid" 2>/dev/null; then - echo "๐Ÿงน Removing stale PID file for $SERVICE_NAME" + if [ -z "$NO_COLOR" ]; then + echo "๐Ÿงน Removing stale PID file for $SERVICE_NAME" + else + echo "Removing stale PID file for $SERVICE_NAME" + fi rm -f "/run/init.d/$SERVICE_NAME.pid" fi fi @@ -275,7 +285,7 @@ __run_precopy() { ln -sf "$CONF_DIR" "$ETC_DIR" fi # allow custom functions - if builtin type -t __run_precopy_local | grep -q 'function'; then __run_precopy_local; fi + if builtin type -t __run_precopy_local | grep -q -- 'function'; then __run_precopy_local; fi } # - - - - - - - - - - - - - - - - - - - - - - - - - # Custom prerun functions - IE setup WWW_ROOT_DIR @@ -285,7 +295,7 @@ __execute_prerun() { # Define actions/commands # allow custom functions - if builtin type -t __execute_prerun_local | grep -q 'function'; then __execute_prerun_local; fi + if builtin type -t __execute_prerun_local | grep -q -- 'function'; then __execute_prerun_local; fi } # - - - - - - - - - - - - - - - - - - - - - - - - - # Run any pre-execution checks @@ -370,6 +380,17 @@ __run_pre_execute_checks() { echo "Warning: cgroup v2 not available, Docker-in-Docker may have limited functionality" fi + # Remove a stale dockerd pidfile before starting + # /tmp persists across `docker restart` (same container filesystem), but the PID + # namespace is reset on every restart, so a low PID number like the one dockerd + # wrote last time can coincidentally be reused by an unrelated process very early + # in the new namespace. dockerd's own startup check then sees /proc/ exists + # and refuses to start with "process with PID is still running", even though + # it is not actually the previous dockerd. This init script is the sole owner of + # the dockerd lifecycle (enforced separately via SERVICE_PID_FILE), so it is always + # safe to clear docker's own pidfile here before each start attempt. + [ -f "/tmp/docker.pid" ] && rm -f "/tmp/docker.pid" + # Clean up orphaned containers before dockerd starts # This prevents "failed to load container" errors on restart if [ -d "/data/docker/containers" ]; then @@ -392,7 +413,7 @@ __run_pre_execute_checks() { for get_reg in $DOCKER_REGISTRIES; do set_reg+="\"$get_reg\" " done - registry="$(printf '%s\n' "$set_reg" | tr ' ' '\n' | sort -V | grep -v '^$' | tr '\n' ',' | sed 's|,$||g;s| ||g' | grep '^')" + registry="$(printf '%s\n' "$set_reg" | tr ' ' '\n' | sort -V | grep -v -- '^$' | tr '\n' ',' | sed 's|,$||g;s| ||g' | grep -E -- '^')" export registry else unset registry @@ -425,6 +446,7 @@ EOF "experimental": true, "pidfile": "/tmp/docker.pid", "cgroup-parent": "/docker", + "storage-driver": "fuse-overlayfs", "default-address-pools": [ {"base": "172.17.0.0/12", "size": 24}, {"base": "192.168.0.0/16", "size": 24}, @@ -442,6 +464,7 @@ EOF "experimental": true, "pidfile": "/tmp/docker.pid", "cgroup-parent": "/docker", + "storage-driver": "fuse-overlayfs", "default-address-pools": [ {"base": "172.17.0.0/12", "size": 24}, {"base": "192.168.0.0/16", "size": 24}, @@ -463,7 +486,7 @@ EOF __script_exit 1 fi # allow custom functions - if builtin type -t __run_pre_execute_checks_local | grep -q 'function'; then __run_pre_execute_checks_local; fi + if builtin type -t __run_pre_execute_checks_local | grep -q -- 'function'; then __run_pre_execute_checks_local; fi # exit function return $exitStatus } @@ -489,12 +512,12 @@ __update_conf_files() { # - - - - - - - - - - - - - - - - - - - - - - - - - # define actions - symlink "$DATA_DIR" "/var/lib/docker" + __symlink "$DATA_DIR" "/var/lib/docker" chmod 777 "$DATA_DIR" "/var/lib/docker" # Mark config as fully initialised so __run_precopy skips re-seeding on restart touch "$CONF_DIR/.initialized" 2>/dev/null || true # allow custom functions - if builtin type -t __update_conf_files_local | grep -q 'function'; then __update_conf_files_local; fi + if builtin type -t __update_conf_files_local | grep -q -- 'function'; then __update_conf_files_local; fi # exit function return $exitCode } @@ -516,7 +539,7 @@ __pre_execute() { # Lets wait a few seconds before continuing sleep 2 # allow custom functions - if builtin type -t __pre_execute_local | grep -q 'function'; then __pre_execute_local; fi + if builtin type -t __pre_execute_local | grep -q -- 'function'; then __pre_execute_local; fi # exit function return $exitCode } @@ -549,7 +572,7 @@ __post_execute() { # fire-and-forget: backgrounded subshell always succeeds at launch retVal=0 # allow custom functions - if builtin type -t __post_execute_local | grep -q 'function'; then __post_execute_local; fi + if builtin type -t __post_execute_local | grep -q -- 'function'; then __post_execute_local; fi # exit function return $retVal } @@ -561,7 +584,7 @@ __pre_message() { # execute commands # allow custom functions - if builtin type -t __pre_message_local | grep -q 'function'; then __pre_message_local; fi + if builtin type -t __pre_message_local | grep -q -- 'function'; then __pre_message_local; fi # exit function return $exitCode } @@ -574,7 +597,7 @@ __update_ssl_conf() { # execute commands # allow custom functions - if builtin type -t __update_ssl_conf_local | grep -q 'function'; then __update_ssl_conf_local; fi + if builtin type -t __update_ssl_conf_local | grep -q -- 'function'; then __update_ssl_conf_local; fi # set exitCode return $exitCode } @@ -696,7 +719,7 @@ __run_start_script() { __log_debug "Using $su_exec" | tee -a -p "/data/logs/init.txt" fi __log_info "$message" | tee -a -p "/data/logs/init.txt" - su_cmd touch "$SERVICE_PID_FILE" + __su_cmd touch "$SERVICE_PID_FILE" # W14: invalidate cached START_SCRIPT if key variables changed local _script_hash_src="$cmd $args $SERVICE_USER $RESET_ENV $su_exec" local _script_hash diff --git a/rootfs/usr/local/etc/docker/init.d/08-gitea.sh b/rootfs/usr/local/etc/docker/init.d/08-gitea.sh index b5a925b..28ae53f 100755 --- a/rootfs/usr/local/etc/docker/init.d/08-gitea.sh +++ b/rootfs/usr/local/etc/docker/init.d/08-gitea.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash # shellcheck shell=bash # - - - - - - - - - - - - - - - - - - - - - - - - - -##@Version : 202606261600-git +##@Version : 202609030601-git # @@Author : Jason Hempstead # @@Contact : jason@casjaysdev.pro # @@License : LICENSE.md @@ -20,6 +20,7 @@ # - - - - - - - - - - - - - - - - - - - - - - - - - # shellcheck disable=SC1001,SC1003,SC2001,SC2003,SC2016,SC2031,SC2090,SC2115,SC2120,SC2155,SC2199,SC2229,SC2317,SC2329 # - - - - - - - - - - - - - - - - - - - - - - - - - +VERSION="202609030601-git" set -e # - - - - - - - - - - - - - - - - - - - - - - - - - # run trap command on exit @@ -43,7 +44,11 @@ __trap_err_handler() { fi # Critical error - but only fail if service hasn't started yet if [ "$SERVICE_IS_RUNNING" != "yes" ]; then - echo "โŒ Critical error (exit $retVal): $command" >&2 + if [ -z "$NO_COLOR" ]; then + echo "โŒ Critical error (exit $retVal): $command" >&2 + else + echo "Critical error (exit $retVal): $command" >&2 + fi kill -TERM 1 2>/dev/null || exit $retVal fi return 0 @@ -108,7 +113,11 @@ fi if [ -n "$SERVICE_NAME" ] && [ -f "/run/init.d/$SERVICE_NAME.pid" ]; then old_pid=$(<"/run/init.d/$SERVICE_NAME.pid") 2>/dev/null if [ -n "$old_pid" ] && ! kill -0 "$old_pid" 2>/dev/null; then - echo "๐Ÿงน Removing stale PID file for $SERVICE_NAME" + if [ -z "$NO_COLOR" ]; then + echo "๐Ÿงน Removing stale PID file for $SERVICE_NAME" + else + echo "Removing stale PID file for $SERVICE_NAME" + fi rm -f "/run/init.d/$SERVICE_NAME.pid" fi fi @@ -320,7 +329,7 @@ __run_precopy() { ln -sf "$CONF_DIR" "$ETC_DIR" fi # allow custom functions - if builtin type -t __run_precopy_local | grep -q 'function'; then __run_precopy_local; fi + if builtin type -t __run_precopy_local | grep -q -- 'function'; then __run_precopy_local; fi } # - - - - - - - - - - - - - - - - - - - - - - - - - # Custom prerun functions - IE setup WWW_ROOT_DIR @@ -330,7 +339,7 @@ __execute_prerun() { # Define actions/commands # allow custom functions - if builtin type -t __execute_prerun_local | grep -q 'function'; then __execute_prerun_local; fi + if builtin type -t __execute_prerun_local | grep -q -- 'function'; then __execute_prerun_local; fi } # - - - - - - - - - - - - - - - - - - - - - - - - - # Run any pre-execution checks @@ -356,7 +365,7 @@ __run_pre_execute_checks() { __script_exit 1 fi # allow custom functions - if builtin type -t __run_pre_execute_checks_local | grep -q 'function'; then __run_pre_execute_checks_local; fi + if builtin type -t __run_pre_execute_checks_local | grep -q -- 'function'; then __run_pre_execute_checks_local; fi # exit function return $exitStatus } @@ -441,7 +450,7 @@ __update_conf_files() { touch "$CONF_DIR/.initialized" 2>/dev/null || true # allow custom functions - if builtin type -t __update_conf_files_local | grep -q 'function'; then __update_conf_files_local; fi + if builtin type -t __update_conf_files_local | grep -q -- 'function'; then __update_conf_files_local; fi # exit function return $exitCode } @@ -463,7 +472,7 @@ __pre_execute() { # Lets wait a few seconds before continuing sleep 2 # allow custom functions - if builtin type -t __pre_execute_local | grep -q 'function'; then __pre_execute_local; fi + if builtin type -t __pre_execute_local | grep -q -- 'function'; then __pre_execute_local; fi # exit function return $exitCode } @@ -496,7 +505,7 @@ __post_execute() { # fire-and-forget: backgrounded subshell always succeeds at launch retVal=0 # allow custom functions - if builtin type -t __post_execute_local | grep -q 'function'; then __post_execute_local; fi + if builtin type -t __post_execute_local | grep -q -- 'function'; then __post_execute_local; fi # exit function return $retVal } @@ -508,7 +517,7 @@ __pre_message() { # execute commands # allow custom functions - if builtin type -t __pre_message_local | grep -q 'function'; then __pre_message_local; fi + if builtin type -t __pre_message_local | grep -q -- 'function'; then __pre_message_local; fi # exit function return $exitCode } @@ -521,7 +530,7 @@ __update_ssl_conf() { # execute commands # allow custom functions - if builtin type -t __update_ssl_conf_local | grep -q 'function'; then __update_ssl_conf_local; fi + if builtin type -t __update_ssl_conf_local | grep -q -- 'function'; then __update_ssl_conf_local; fi # set exitCode return $exitCode } @@ -643,7 +652,7 @@ __run_start_script() { __log_debug "Using $su_exec" | tee -a -p "/data/logs/init.txt" fi __log_info "$message" | tee -a -p "/data/logs/init.txt" - su_cmd touch "$SERVICE_PID_FILE" + __su_cmd touch "$SERVICE_PID_FILE" # W14: invalidate cached START_SCRIPT if key variables changed local _script_hash_src="$cmd $args $SERVICE_USER $RESET_ENV $su_exec" local _script_hash diff --git a/rootfs/usr/local/etc/docker/init.d/zz-act_runner.sh b/rootfs/usr/local/etc/docker/init.d/zz-act_runner.sh index cfab7b9..89bca85 100755 --- a/rootfs/usr/local/etc/docker/init.d/zz-act_runner.sh +++ b/rootfs/usr/local/etc/docker/init.d/zz-act_runner.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash # shellcheck shell=bash # - - - - - - - - - - - - - - - - - - - - - - - - - -##@Version : 202608031200-git +##@Version : 202609030534-git # @@Author : Jason Hempstead # @@Contact : jason@casjaysdev.pro # @@License : LICENSE.md @@ -20,7 +20,7 @@ # - - - - - - - - - - - - - - - - - - - - - - - - - # shellcheck disable=SC1001,SC1003,SC2001,SC2003,SC2016,SC2031,SC2090,SC2115,SC2120,SC2155,SC2199,SC2229,SC2317,SC2329 # - - - - - - - - - - - - - - - - - - - - - - - - - -VERSION="202608031200-git" +VERSION="202609030534-git" set -e # - - - - - - - - - - - - - - - - - - - - - - - - - # run trap command on exit @@ -44,7 +44,11 @@ __trap_err_handler() { fi # Critical error - but only fail if service hasn't started yet if [ "$SERVICE_IS_RUNNING" != "yes" ]; then - echo "โŒ Critical error (exit $retVal): $command" >&2 + if [ -z "$NO_COLOR" ]; then + echo "โŒ Critical error (exit $retVal): $command" >&2 + else + echo "Critical error (exit $retVal): $command" >&2 + fi kill -TERM 1 2>/dev/null || exit $retVal fi return 0 @@ -109,7 +113,11 @@ fi if [ -n "$SERVICE_NAME" ] && [ -f "/run/init.d/$SERVICE_NAME.pid" ]; then old_pid=$(<"/run/init.d/$SERVICE_NAME.pid") 2>/dev/null if [ -n "$old_pid" ] && ! kill -0 "$old_pid" 2>/dev/null; then - echo "๐Ÿงน Removing stale PID file for $SERVICE_NAME" + if [ -z "$NO_COLOR" ]; then + echo "๐Ÿงน Removing stale PID file for $SERVICE_NAME" + else + echo "Removing stale PID file for $SERVICE_NAME" + fi rm -f "/run/init.d/$SERVICE_NAME.pid" fi fi @@ -132,7 +140,10 @@ __gen_auth_token() { if [ -z "$auth_token" ] && [ -n "$gitea_bin" ] && [ -n "$conf_file" ]; then # Only attempt token generation if gitea is fully installed (INSTALL_LOCK = true) if grep -qiE -- 'INSTALL_LOCK\s*=\s*true' "$conf_file" 2>/dev/null; then - auth_token="$(gosu $user $gitea_bin --config "$conf_file" --work-path /data/gitea --custom-path /config/gitea/custom actions generate-runner-token 2>/dev/null | grep -oE -- '[A-Za-z0-9]{20,}' | tail -n1)" + auth_token="$( gosu $user $gitea_bin --config "$conf_file" \ + --work-path /data/gitea --custom-path /config/gitea/custom \ + actions generate-runner-token 2>/dev/null | \ + grep -oE -- '[A-Za-z0-9]{20,}' | tail -n1 )" fi fi if [ -n "$auth_token" ]; then @@ -317,7 +328,10 @@ RUNNER_LABELS+="act_runner:docker://catthehacker/ubuntu:full-latest," RUNNER_LABELS+="ubuntu-latest:docker://catthehacker/ubuntu:full-latest" unset _HOST_ARCH _ARCH_LABEL # - - - - - - - - - - - - - - - - - - - - - - - - - -RUNNER_IP_ADDRESS="${RUNNER_IP_ADDRESS:-$IP4_ADDRESS}" +# act_runner registers against gitea in the same container/network namespace, so use +# loopback rather than the detected external IP4_ADDRESS (which can be transient/wrong +# under Docker-in-Docker networking and caused "no route to host" registration failures) +RUNNER_IP_ADDRESS="${RUNNER_IP_ADDRESS:-127.0.0.1}" RUNNER_CONFIG_DEFAULT="${RUNNER_CONFIG_DEFAULT:-$CONF_DIR/default_config.yaml}" RUNNER_DEFAULT_HOME="${RUNNER_DEFAULT_HOME:-$CONF_DIR/gitea}" RUNNER_CONFIG_NAME="${RUNNER_CONFIG_NAME:-act_runner.yaml}" @@ -416,11 +430,9 @@ __run_pre_execute_checks() { __replace "REPLACE_RUNNER_CACHE_HOST" "$RUNNER_CACHE_HOST" "$RUNNER_DEFAULT_HOME/$RUNNER_CONFIG_NAME" __replace "REPLACE_RUNNER_CACHE_PORT" "$RUNNER_CACHE_PORT" "$RUNNER_DEFAULT_HOME/$RUNNER_CONFIG_NAME" __replace "REPLACE_RUNNER_CACHE_SECRET" "$RUNNER_CACHE_SECRET" "$RUNNER_DEFAULT_HOME/$RUNNER_CONFIG_NAME" - if [ ! -f "$RUNNER_DEFAULT_HOME/runners" ] && [ -n "$SYS_AUTH_TOKEN" ]; then - echo "creating gitea runner in $RUNNER_DEFAULT_HOME and registering with http://$INSTANCE_HOSTNAME" - act_runner register --config "$RUNNER_DEFAULT_HOME/$RUNNER_CONFIG_NAME" --labels "$RUNNER_LABELS" --name "gitea" --instance "http://$RUNNER_IP_ADDRESS:$GITEA_PORT" --token "$SYS_AUTH_TOKEN" --no-interactive >>"$RUNNER_LOG_FILE" 2>&1 & - echo $! >"$RUN_DIR/act_runner.gitea.pid" - fi + # Legacy single "gitea"-named runner registration removed: start-runners + # (invoked from __post_execute) now owns all runner registration/count via + # RUNNERS_START, and registering a second runner here duplicated it fi exitStatus="${exitStatus:-0}" chown -Rf "$SERVICE_USER":"$SERVICE_GROUP" "$CONF_DIR" "$ETC_DIR" "$DATA_DIR" 2>/dev/null @@ -518,29 +530,25 @@ __post_execute() { ( # show message __banner "$postMessageST" - # commands to execute - if [ -f "$RUNNER_DEFAULT_HOME/runners" ] && [ -f "$RUNNER_DEFAULT_HOME/$RUNNER_CONFIG_NAME" ]; then - act_runner daemon --config "$RUNNER_DEFAULT_HOME/$RUNNER_CONFIG_NAME" >>"$RUNNER_DAEMON_LOG" 2>/dev/stderr & - pid=$! - sleep 5 - if ps ax | awk '{print $1}' | grep -v -- 'grep' | grep -q -- "$pid$"; then - echo "$(date)" >"$CONF_DIR/.runner" - echo "$pid" >"$RUN_DIR/act_runner.gitea.pid" - echo "Runner: gitea has been started with pid: $pid" | tee -a -p "$LOG_DIR/init.txt" - else - echo "Runner: gitea has failed to start" >/dev/stderr - [ -f "$RUN_DIR/act_runner.gitea.pid" ] && rm -f "$RUN_DIR/act_runner.gitea.pid" - fi - unset pid - fi + # Legacy single "gitea"-named runner daemon start removed: start-runners + # (below) now owns all runner registration/daemon startup via RUNNERS_START # if [ -f "$CACHE_CONFIG_FILE" ]; then mkdir -p "$DATA_DIR/cache" __replace "REPLACE_RUNNER_CACHE_DIR" "$DATA_DIR/cache" "$CACHE_CONFIG_FILE" __replace "REPLACE_RUNNER_CACHE_PORT" "$RUNNER_CACHE_PORT" "$CACHE_CONFIG_FILE" __replace "REPLACE_RUNNER_CACHE_SECRET" "$RUNNER_CACHE_SECRET" "$CACHE_CONFIG_FILE" - act_runner cache-server --config "$CACHE_CONFIG_FILE" 2>>/dev/stderr >>"$CACHE_LOG_FILE" & + # stdout/stderr are redirected to a real file here (not inherited from the + # __post_execute pipe) because cache-server is a long-running process that + # never exits; if it inherited the pipe's write end, the tee reading it + # would never see EOF and __run_start_script would hang forever (same + # fd-leak class as the start-runners fix below) + act_runner cache-server --config "$CACHE_CONFIG_FILE" >>"$CACHE_LOG_FILE" 2>&1 & execPid=$! + # disown so this long-running background job is fully detached from this + # subshell's job table; otherwise bash can block waiting on it when this + # subshell (itself the left side of the __post_execute pipe) reaches its end + disown "$execPid" 2>/dev/null || true sleep 5 if ps ax | awk '{print $1}' | grep -v -- 'grep' | grep -q -- "$execPid$"; then echo "Cache server has been started and is listening on $RUNNER_CACHE_PORT" @@ -549,7 +557,17 @@ __post_execute() { fi unset pid fi - [ -x "/usr/local/bin/start-runners" ] && /usr/local/bin/start-runners & + # stdout/stderr are redirected to a real file here (not inherited from the + # __post_execute pipe) because start-runners execs long-running act_runner + # daemons that never exit; if they inherited the pipe's write end, the + # tee reading it would never see EOF and __run_start_script would hang forever + if [ -x "/usr/local/bin/start-runners" ]; then + /usr/local/bin/start-runners >>"$LOG_DIR/runners.log" 2>&1 & + # disown so this long-running background job is fully detached from this + # subshell's job table; otherwise bash can block waiting on it when this + # subshell (itself the left side of the __post_execute pipe) reaches its end + disown "$!" 2>/dev/null || true + fi # show exit message __banner "$postMessageEnd: Status $retVal" ) 2>"/dev/stderr" | tee -p -a "/data/logs/init.txt" & @@ -703,7 +721,7 @@ __run_start_script() { __log_debug "Using $su_exec" | tee -a -p "/data/logs/init.txt" fi __log_info "$message" | tee -a -p "/data/logs/init.txt" - su_cmd touch "$SERVICE_PID_FILE" + __su_cmd touch "$SERVICE_PID_FILE" # W14: invalidate cached START_SCRIPT if key variables changed local _script_hash_src="$cmd $args $SERVICE_USER $RESET_ENV $su_exec" local _script_hash @@ -1027,7 +1045,8 @@ if [ -n "$EXEC_CMD_BIN" ]; then fi fi # - - - - - - - - - - - - - - - - - - - - - - - - - -# start the post execute function in background -__post_execute 2>"/dev/stderr" | tee -p -a "/data/logs/init.txt" & +# EXEC_CMD_BIN is empty for this service, so __run_start_script already invoked +# __post_execute internally (its empty-cmd branch); calling it again here would +# duplicate runner registration/daemon startup # - - - - - - - - - - - - - - - - - - - - - - - - - __script_exit $SERVICE_EXIT_CODE