Fix standalone bootstrap: move to after function definition
When run directly (sudo bash services/foo.sh), bash executes the bootstrap block before reaching the install_* function definition below it, causing "command not found". Moving the bootstrap to the end of each file ensures the function is defined by the time the bootstrap calls it. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01D8ckUJQtj1pH8jtAddBDZs
This commit is contained in:
+32
-32
@@ -29,38 +29,6 @@
|
|||||||
# automatically when run with sudo (required for setup.sh anyway).
|
# automatically when run with sudo (required for setup.sh anyway).
|
||||||
# Without the fix: bwrap: setting up uid map: Permission denied
|
# Without the fix: bwrap: setting up uid map: Permission denied
|
||||||
|
|
||||||
# ── Standalone bootstrap ──────────────────────────────────────────────────────
|
|
||||||
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
|
||||||
[[ "$(id -u)" == "0" ]] || { echo "Run with sudo: sudo bash $0"; exit 1; }
|
|
||||||
|
|
||||||
_SELF_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
||||||
_COMMON="$_SELF_DIR/../lib/common.sh"
|
|
||||||
|
|
||||||
if [[ -f "$_COMMON" ]]; then
|
|
||||||
source "$_COMMON"
|
|
||||||
else
|
|
||||||
log_info() { echo -e "\033[0;34m[INFO]\033[0m $*"; }
|
|
||||||
log_success() { echo -e "\033[0;32m[OK]\033[0m $*"; }
|
|
||||||
log_warning() { echo -e "\033[1;33m[WARN]\033[0m $*"; }
|
|
||||||
log_error() { echo -e "\033[0;31m[ERROR]\033[0m $*" >&2; }
|
|
||||||
|
|
||||||
prompt_yn() {
|
|
||||||
local _q="$1" _def="$2" _var="$3" _r
|
|
||||||
[[ "${UNATTENDED:-false}" == "true" ]] && { eval "$_var='$_def'"; return; }
|
|
||||||
read -r -p " $_q " _r
|
|
||||||
eval "$_var='${_r:-$_def}'"
|
|
||||||
}
|
|
||||||
|
|
||||||
ACTUAL_USER="${SUDO_USER:-$USER}"
|
|
||||||
ACTUAL_HOME=$(eval echo "~$ACTUAL_USER")
|
|
||||||
DRY_RUN="${DRY_RUN:-false}"
|
|
||||||
UNATTENDED="${UNATTENDED:-false}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
install_kyber_launcher
|
|
||||||
exit $?
|
|
||||||
fi
|
|
||||||
|
|
||||||
# ── Registration ──────────────────────────────────────────────────────────────
|
# ── Registration ──────────────────────────────────────────────────────────────
|
||||||
register_service kyber-launcher gaming "Kyber Launcher — native Linux AppImage for SWBF2 (2017) multiplayer (requires discrete GPU)"
|
register_service kyber-launcher gaming "Kyber Launcher — native Linux AppImage for SWBF2 (2017) multiplayer (requires discrete GPU)"
|
||||||
|
|
||||||
@@ -229,3 +197,35 @@ EOF
|
|||||||
echo " Troubleshooting — 'Origin Error: language not entitled':"
|
echo " Troubleshooting — 'Origin Error: language not entitled':"
|
||||||
echo " See README.md Gaming section for the registry fix."
|
echo " See README.md Gaming section for the registry fix."
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# ── Standalone bootstrap ──────────────────────────────────────────────────────
|
||||||
|
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
||||||
|
[[ "$(id -u)" == "0" ]] || { echo "Run with sudo: sudo bash $0"; exit 1; }
|
||||||
|
|
||||||
|
_SELF_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
_COMMON="$_SELF_DIR/../lib/common.sh"
|
||||||
|
|
||||||
|
if [[ -f "$_COMMON" ]]; then
|
||||||
|
source "$_COMMON"
|
||||||
|
else
|
||||||
|
log_info() { echo -e "\033[0;34m[INFO]\033[0m $*"; }
|
||||||
|
log_success() { echo -e "\033[0;32m[OK]\033[0m $*"; }
|
||||||
|
log_warning() { echo -e "\033[1;33m[WARN]\033[0m $*"; }
|
||||||
|
log_error() { echo -e "\033[0;31m[ERROR]\033[0m $*" >&2; }
|
||||||
|
|
||||||
|
prompt_yn() {
|
||||||
|
local _q="$1" _def="$2" _var="$3" _r
|
||||||
|
[[ "${UNATTENDED:-false}" == "true" ]] && { eval "$_var='$_def'"; return; }
|
||||||
|
read -r -p " $_q " _r
|
||||||
|
eval "$_var='${_r:-$_def}'"
|
||||||
|
}
|
||||||
|
|
||||||
|
ACTUAL_USER="${SUDO_USER:-$USER}"
|
||||||
|
ACTUAL_HOME=$(eval echo "~$ACTUAL_USER")
|
||||||
|
DRY_RUN="${DRY_RUN:-false}"
|
||||||
|
UNATTENDED="${UNATTENDED:-false}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
install_kyber_launcher
|
||||||
|
exit $?
|
||||||
|
fi
|
||||||
|
|||||||
+59
-60
@@ -19,66 +19,6 @@
|
|||||||
# Map rotation is left blank by default; edit ~/docker/kyber-server/.env after install
|
# Map rotation is left blank by default; edit ~/docker/kyber-server/.env after install
|
||||||
# and set KYBER_MAP_ROTATION to a base64-encoded rotation string (use the Kyber client
|
# and set KYBER_MAP_ROTATION to a base64-encoded rotation string (use the Kyber client
|
||||||
# HOST tab to build a rotation, then base64-encode it).
|
# HOST tab to build a rotation, then base64-encode it).
|
||||||
|
|
||||||
# ── Standalone bootstrap ──────────────────────────────────────────────────────
|
|
||||||
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
|
||||||
[[ "$(id -u)" == "0" ]] || { echo "Run with sudo: sudo bash $0"; exit 1; }
|
|
||||||
|
|
||||||
_SELF_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
||||||
_COMMON="$_SELF_DIR/../lib/common.sh"
|
|
||||||
|
|
||||||
if [[ -f "$_COMMON" ]]; then
|
|
||||||
source "$_COMMON"
|
|
||||||
else
|
|
||||||
log_info() { echo -e "\033[0;34m[INFO]\033[0m $*"; }
|
|
||||||
log_success() { echo -e "\033[0;32m[OK]\033[0m $*"; }
|
|
||||||
log_warning() { echo -e "\033[1;33m[WARN]\033[0m $*"; }
|
|
||||||
log_error() { echo -e "\033[0;31m[ERROR]\033[0m $*" >&2; }
|
|
||||||
|
|
||||||
require_docker() {
|
|
||||||
command -v docker &>/dev/null || {
|
|
||||||
log_error "Docker not found. Install it first:"
|
|
||||||
log_error " curl -fsSL https://get.docker.com | sudo sh"
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
docker compose version &>/dev/null || {
|
|
||||||
log_error "Docker Compose plugin missing:"
|
|
||||||
log_error " sudo apt-get install -y docker-compose-plugin"
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ensure_docker_dir_ownership() {
|
|
||||||
chown -R "$ACTUAL_USER:$ACTUAL_USER" "$@" 2>/dev/null || true
|
|
||||||
}
|
|
||||||
|
|
||||||
prompt_text() {
|
|
||||||
local _q="$1" _def="$2" _var="$3" _r
|
|
||||||
[[ "${UNATTENDED:-false}" == "true" ]] && { eval "$_var='$_def'"; return; }
|
|
||||||
read -r -p " $_q " _r
|
|
||||||
eval "$_var='${_r:-$_def}'"
|
|
||||||
}
|
|
||||||
|
|
||||||
prompt_yn() {
|
|
||||||
local _q="$1" _def="$2" _var="$3" _r
|
|
||||||
[[ "${UNATTENDED:-false}" == "true" ]] && { eval "$_var='$_def'"; return; }
|
|
||||||
read -r -p " $_q " _r
|
|
||||||
eval "$_var='${_r:-$_def}'"
|
|
||||||
}
|
|
||||||
|
|
||||||
generate_password() { tr -dc 'A-Za-z0-9' </dev/urandom | head -c "${1:-32}"; }
|
|
||||||
|
|
||||||
ACTUAL_USER="${SUDO_USER:-$USER}"
|
|
||||||
ACTUAL_HOME=$(eval echo "~$ACTUAL_USER")
|
|
||||||
DOCKER_DIR="$ACTUAL_HOME/docker"
|
|
||||||
DRY_RUN="${DRY_RUN:-false}"
|
|
||||||
UNATTENDED="${UNATTENDED:-false}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
install_kyber_server
|
|
||||||
exit $?
|
|
||||||
fi
|
|
||||||
|
|
||||||
# ── Registration ──────────────────────────────────────────────────────────────
|
# ── Registration ──────────────────────────────────────────────────────────────
|
||||||
register_service kyber-server gaming "Kyber dedicated server for SWBF2 (2017) — headless, no GPU required"
|
register_service kyber-server gaming "Kyber dedicated server for SWBF2 (2017) — headless, no GPU required"
|
||||||
|
|
||||||
@@ -414,3 +354,62 @@ MD
|
|||||||
echo "Edit $DIR/.env to set map rotation or update credentials."
|
echo "Edit $DIR/.env to set map rotation or update credentials."
|
||||||
echo "Token refresh: re-run this installer or update KYBER_TOKEN in .env manually."
|
echo "Token refresh: re-run this installer or update KYBER_TOKEN in .env manually."
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# ── Standalone bootstrap ──────────────────────────────────────────────────────
|
||||||
|
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
||||||
|
[[ "$(id -u)" == "0" ]] || { echo "Run with sudo: sudo bash $0"; exit 1; }
|
||||||
|
|
||||||
|
_SELF_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
_COMMON="$_SELF_DIR/../lib/common.sh"
|
||||||
|
|
||||||
|
if [[ -f "$_COMMON" ]]; then
|
||||||
|
source "$_COMMON"
|
||||||
|
else
|
||||||
|
log_info() { echo -e "\033[0;34m[INFO]\033[0m $*"; }
|
||||||
|
log_success() { echo -e "\033[0;32m[OK]\033[0m $*"; }
|
||||||
|
log_warning() { echo -e "\033[1;33m[WARN]\033[0m $*"; }
|
||||||
|
log_error() { echo -e "\033[0;31m[ERROR]\033[0m $*" >&2; }
|
||||||
|
|
||||||
|
require_docker() {
|
||||||
|
command -v docker &>/dev/null || {
|
||||||
|
log_error "Docker not found. Install it first:"
|
||||||
|
log_error " curl -fsSL https://get.docker.com | sudo sh"
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
docker compose version &>/dev/null || {
|
||||||
|
log_error "Docker Compose plugin missing:"
|
||||||
|
log_error " sudo apt-get install -y docker-compose-plugin"
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ensure_docker_dir_ownership() {
|
||||||
|
chown -R "$ACTUAL_USER:$ACTUAL_USER" "$@" 2>/dev/null || true
|
||||||
|
}
|
||||||
|
|
||||||
|
prompt_text() {
|
||||||
|
local _q="$1" _def="$2" _var="$3" _r
|
||||||
|
[[ "${UNATTENDED:-false}" == "true" ]] && { eval "$_var='$_def'"; return; }
|
||||||
|
read -r -p " $_q " _r
|
||||||
|
eval "$_var='${_r:-$_def}'"
|
||||||
|
}
|
||||||
|
|
||||||
|
prompt_yn() {
|
||||||
|
local _q="$1" _def="$2" _var="$3" _r
|
||||||
|
[[ "${UNATTENDED:-false}" == "true" ]] && { eval "$_var='$_def'"; return; }
|
||||||
|
read -r -p " $_q " _r
|
||||||
|
eval "$_var='${_r:-$_def}'"
|
||||||
|
}
|
||||||
|
|
||||||
|
generate_password() { tr -dc 'A-Za-z0-9' </dev/urandom | head -c "${1:-32}"; }
|
||||||
|
|
||||||
|
ACTUAL_USER="${SUDO_USER:-$USER}"
|
||||||
|
ACTUAL_HOME=$(eval echo "~$ACTUAL_USER")
|
||||||
|
DOCKER_DIR="$ACTUAL_HOME/docker"
|
||||||
|
DRY_RUN="${DRY_RUN:-false}"
|
||||||
|
UNATTENDED="${UNATTENDED:-false}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
install_kyber_server
|
||||||
|
exit $?
|
||||||
|
fi
|
||||||
|
|||||||
+46
-47
@@ -30,53 +30,6 @@
|
|||||||
# This script pre-configures a "Kyber SWBF2" app entry in Sunshine so
|
# This script pre-configures a "Kyber SWBF2" app entry in Sunshine so
|
||||||
# Moonlight shows it as a launchable app. The Kyber AppImage must already
|
# Moonlight shows it as a launchable app. The Kyber AppImage must already
|
||||||
# be installed (run setup-kyber-linux.sh first).
|
# be installed (run setup-kyber-linux.sh first).
|
||||||
|
|
||||||
# ── Standalone bootstrap ──────────────────────────────────────────────────
|
|
||||||
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
|
||||||
[[ "$(id -u)" == "0" ]] || { echo "Run with sudo: sudo bash $0"; exit 1; }
|
|
||||||
|
|
||||||
_SELF_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
||||||
_COMMON="$_SELF_DIR/../lib/common.sh"
|
|
||||||
|
|
||||||
if [[ -f "$_COMMON" ]]; then
|
|
||||||
source "$_COMMON"
|
|
||||||
else
|
|
||||||
log_info() { echo -e "\033[0;34m[INFO]\033[0m $*"; }
|
|
||||||
log_success() { echo -e "\033[0;32m[OK]\033[0m $*"; }
|
|
||||||
log_warning() { echo -e "\033[1;33m[WARN]\033[0m $*"; }
|
|
||||||
log_error() { echo -e "\033[0;31m[ERROR]\033[0m $*" >&2; }
|
|
||||||
|
|
||||||
require_docker() { return 0; }
|
|
||||||
|
|
||||||
ensure_docker_dir_ownership() {
|
|
||||||
chown -R "$ACTUAL_USER:$ACTUAL_USER" "$@" 2>/dev/null || true
|
|
||||||
}
|
|
||||||
|
|
||||||
prompt_text() {
|
|
||||||
local _q="$1" _def="$2" _var="$3" _r
|
|
||||||
[[ "${UNATTENDED:-false}" == "true" ]] && { eval "$_var='$_def'"; return; }
|
|
||||||
read -r -p " $_q " _r
|
|
||||||
eval "$_var='${_r:-$_def}'"
|
|
||||||
}
|
|
||||||
|
|
||||||
prompt_yn() {
|
|
||||||
local _q="$1" _def="$2" _var="$3" _r
|
|
||||||
[[ "${UNATTENDED:-false}" == "true" ]] && { eval "$_var='$_def'"; return; }
|
|
||||||
read -r -p " $_q " _r
|
|
||||||
eval "$_var='${_r:-$_def}'"
|
|
||||||
}
|
|
||||||
|
|
||||||
ACTUAL_USER="${SUDO_USER:-$USER}"
|
|
||||||
ACTUAL_HOME=$(eval echo "~$ACTUAL_USER")
|
|
||||||
DOCKER_DIR="$ACTUAL_HOME/docker"
|
|
||||||
DRY_RUN="${DRY_RUN:-false}"
|
|
||||||
UNATTENDED="${UNATTENDED:-false}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
install_sunshine
|
|
||||||
exit $?
|
|
||||||
fi
|
|
||||||
|
|
||||||
# ── Registration ──────────────────────────────────────────────────────────
|
# ── Registration ──────────────────────────────────────────────────────────
|
||||||
register_service sunshine homelab "Sunshine game streaming host for Moonlight clients (coexists with Wolf on offset ports)"
|
register_service sunshine homelab "Sunshine game streaming host for Moonlight clients (coexists with Wolf on offset ports)"
|
||||||
|
|
||||||
@@ -391,3 +344,49 @@ MD
|
|||||||
echo "NOTE: Log out and back in (or reboot) for the 'input' group to take effect"
|
echo "NOTE: Log out and back in (or reboot) for the 'input' group to take effect"
|
||||||
echo " (required for controller and mouse input from Moonlight)."
|
echo " (required for controller and mouse input from Moonlight)."
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# ── Standalone bootstrap ──────────────────────────────────────────────────
|
||||||
|
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
||||||
|
[[ "$(id -u)" == "0" ]] || { echo "Run with sudo: sudo bash $0"; exit 1; }
|
||||||
|
|
||||||
|
_SELF_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
_COMMON="$_SELF_DIR/../lib/common.sh"
|
||||||
|
|
||||||
|
if [[ -f "$_COMMON" ]]; then
|
||||||
|
source "$_COMMON"
|
||||||
|
else
|
||||||
|
log_info() { echo -e "\033[0;34m[INFO]\033[0m $*"; }
|
||||||
|
log_success() { echo -e "\033[0;32m[OK]\033[0m $*"; }
|
||||||
|
log_warning() { echo -e "\033[1;33m[WARN]\033[0m $*"; }
|
||||||
|
log_error() { echo -e "\033[0;31m[ERROR]\033[0m $*" >&2; }
|
||||||
|
|
||||||
|
require_docker() { return 0; }
|
||||||
|
|
||||||
|
ensure_docker_dir_ownership() {
|
||||||
|
chown -R "$ACTUAL_USER:$ACTUAL_USER" "$@" 2>/dev/null || true
|
||||||
|
}
|
||||||
|
|
||||||
|
prompt_text() {
|
||||||
|
local _q="$1" _def="$2" _var="$3" _r
|
||||||
|
[[ "${UNATTENDED:-false}" == "true" ]] && { eval "$_var='$_def'"; return; }
|
||||||
|
read -r -p " $_q " _r
|
||||||
|
eval "$_var='${_r:-$_def}'"
|
||||||
|
}
|
||||||
|
|
||||||
|
prompt_yn() {
|
||||||
|
local _q="$1" _def="$2" _var="$3" _r
|
||||||
|
[[ "${UNATTENDED:-false}" == "true" ]] && { eval "$_var='$_def'"; return; }
|
||||||
|
read -r -p " $_q " _r
|
||||||
|
eval "$_var='${_r:-$_def}'"
|
||||||
|
}
|
||||||
|
|
||||||
|
ACTUAL_USER="${SUDO_USER:-$USER}"
|
||||||
|
ACTUAL_HOME=$(eval echo "~$ACTUAL_USER")
|
||||||
|
DOCKER_DIR="$ACTUAL_HOME/docker"
|
||||||
|
DRY_RUN="${DRY_RUN:-false}"
|
||||||
|
UNATTENDED="${UNATTENDED:-false}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
install_sunshine
|
||||||
|
exit $?
|
||||||
|
fi
|
||||||
|
|||||||
Reference in New Issue
Block a user