feat: add nethergamesmc core install flow
This commit is contained in:
287
cores/nethergamesmc.sh
Normal file
287
cores/nethergamesmc.sh
Normal file
@@ -0,0 +1,287 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
core_name_nethergamesmc() {
|
||||
echo "NetherGamesMC"
|
||||
}
|
||||
|
||||
core_default_port_nethergamesmc() {
|
||||
echo "19132"
|
||||
}
|
||||
|
||||
core_protocol_nethergamesmc() {
|
||||
echo "udp"
|
||||
}
|
||||
|
||||
core_runtime_nethergamesmc() {
|
||||
echo "php"
|
||||
}
|
||||
|
||||
core_validate_nethergamesmc() {
|
||||
return 0
|
||||
}
|
||||
|
||||
nethergamesmc_get_php_build_release_tag() {
|
||||
local requested_tag="$1"
|
||||
|
||||
if [[ "$requested_tag" == "latest" ]]; then
|
||||
requested_tag="$(http_get "https://api.github.com/repos/NetherGamesMC/php-build-scripts/releases/latest" | jq -r '.tag_name // empty')"
|
||||
if [[ -z "$requested_tag" || "$requested_tag" == "null" ]]; then
|
||||
fail "$(t no_stable_build "NetherGamesMC/php-build-scripts" "latest")"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "$requested_tag"
|
||||
}
|
||||
|
||||
nethergamesmc_resolve_php_platform() {
|
||||
local os
|
||||
local arch
|
||||
os="$(uname -s | tr '[:upper:]' '[:lower:]')"
|
||||
arch="$(uname -m | tr '[:upper:]' '[:lower:]')"
|
||||
|
||||
case "$os" in
|
||||
linux)
|
||||
os="linux"
|
||||
;;
|
||||
darwin)
|
||||
os="macos|darwin"
|
||||
;;
|
||||
*)
|
||||
os="$os"
|
||||
;;
|
||||
esac
|
||||
|
||||
case "$arch" in
|
||||
x86_64|amd64)
|
||||
arch="x86_64|amd64"
|
||||
;;
|
||||
aarch64|arm64)
|
||||
arch="aarch64|arm64"
|
||||
;;
|
||||
*)
|
||||
arch="$arch"
|
||||
;;
|
||||
esac
|
||||
|
||||
echo "$os:$arch"
|
||||
}
|
||||
|
||||
nethergamesmc_get_php_build_asset_url() {
|
||||
local tag="$1"
|
||||
local allow_fallback="${2:-no}"
|
||||
local platform os_regex arch_regex
|
||||
local release_json
|
||||
|
||||
platform="$(nethergamesmc_resolve_php_platform)"
|
||||
os_regex="${platform%%:*}"
|
||||
arch_regex="${platform##*:}"
|
||||
|
||||
release_json="$(http_get "https://api.github.com/repos/NetherGamesMC/php-build-scripts/releases/tags/${tag}")"
|
||||
if [[ "$release_json" == *"\"message\""* && "$release_json" == *"Not Found"* && "$allow_fallback" == "no" ]]; then
|
||||
return 1
|
||||
fi
|
||||
if [[ -z "$release_json" || "$release_json" == "null" ]]; then
|
||||
if [[ "$allow_fallback" == "yes" ]]; then
|
||||
release_json="$(http_get "https://api.github.com/repos/NetherGamesMC/php-build-scripts/releases/latest")"
|
||||
fi
|
||||
fi
|
||||
|
||||
jq -r --arg os "$os_regex" --arg arch "$arch_regex" '
|
||||
(.assets // [])[]
|
||||
| select((.name|test($os;"i")) and (.name|test($arch;"i")) and (.name|test("PM5";"i")) and (.name|test("\\.tar\\.gz$";"i")))
|
||||
| .browser_download_url
|
||||
' <<<"$release_json" | head -n 1
|
||||
}
|
||||
|
||||
nethergamesmc_sha256_file() {
|
||||
if command -v sha256sum >/dev/null 2>&1; then
|
||||
sha256sum "$1" | awk '{print $1}'
|
||||
elif command -v shasum >/dev/null 2>&1; then
|
||||
shasum -a 256 "$1" | awk '{print $1}'
|
||||
else
|
||||
echo ""
|
||||
fi
|
||||
}
|
||||
|
||||
nethergamesmc_ensure_php_runtime() {
|
||||
local build_tag="$1"
|
||||
local php_dir="${SERVER_DIR}/tools/php"
|
||||
local marker="${SERVER_DIR}/.nethergamesmc-php-build"
|
||||
local current_build=""
|
||||
local build_url
|
||||
|
||||
if [[ "${DRY_RUN:-no}" == "yes" ]]; then
|
||||
emit_step "core_runtime" "cache"
|
||||
echo "${php_dir}/bin/php"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [[ -f "$marker" ]]; then
|
||||
current_build="$(cat "$marker" 2>/dev/null || true)"
|
||||
fi
|
||||
|
||||
if [[ "$current_build" == "$build_tag" ]]; then
|
||||
if [[ -x "${php_dir}/bin/php" && -f "${php_dir}/composer.phar" ]]; then
|
||||
emit_step "core_runtime" "cache"
|
||||
echo "${php_dir}/bin/php"
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
||||
build_url="$(nethergamesmc_get_php_build_asset_url "$build_tag" "no")"
|
||||
if [[ -z "$build_url" || "$build_url" == "null" ]]; then
|
||||
fail "$(t no_stable_build "NetherGamesMC/php-build-scripts" "$build_tag")"
|
||||
fi
|
||||
|
||||
emit_step "core_phpbuild_resolve" "$build_tag"
|
||||
emit_step "core_phpbuild_fetch" "$build_url"
|
||||
|
||||
local tmp_dir
|
||||
local tmp_archive
|
||||
tmp_dir="$(mktemp -d)"
|
||||
tmp_archive="${tmp_dir}/php-build-${build_tag}.tar.gz"
|
||||
|
||||
run_cmd curl -fL "$build_url" -o "$tmp_archive"
|
||||
run_cmd mkdir -p "$tmp_dir/extracted"
|
||||
run_cmd tar -xzf "$tmp_archive" -C "$tmp_dir/extracted"
|
||||
|
||||
run_cmd rm -rf "$php_dir"
|
||||
run_cmd mkdir -p "$php_dir"
|
||||
run_cmd cp -a "$tmp_dir/extracted"/. "$php_dir"/
|
||||
run_cmd rm -rf "$tmp_dir"
|
||||
|
||||
local php_bin
|
||||
php_bin="$(find "$php_dir" -type f -name 'php' | head -n 1 || true)"
|
||||
if [[ -z "$php_bin" ]]; then
|
||||
fail "PHP runtime binary not found after extraction"
|
||||
fi
|
||||
|
||||
run_cmd chmod +x "$php_bin"
|
||||
run_cmd mkdir -p "$php_dir/bin"
|
||||
run_cmd ln -sf "$php_bin" "$php_dir/bin/php"
|
||||
|
||||
run_cmd printf '%s\n' "$build_tag" > "$marker"
|
||||
echo "${php_dir}/bin/php"
|
||||
}
|
||||
|
||||
nethergamesmc_fetch_composer() {
|
||||
local php_bin="$1"
|
||||
local composer_path="$2"
|
||||
|
||||
if [[ "${DRY_RUN:-no}" == "yes" ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
emit_step "core_composer" "composer.phar"
|
||||
if [[ -f "$composer_path" ]]; then
|
||||
if "$php_bin" -n "$composer_path" --version >/dev/null 2>&1; then
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
||||
local phar_url="https://getcomposer.org/download/latest-stable/composer.phar"
|
||||
local sha_url="https://getcomposer.org/download/latest-stable/composer.phar.sha256sum"
|
||||
local hash_file="${composer_path}.sha256"
|
||||
|
||||
run_cmd curl -fL "$phar_url" -o "$composer_path"
|
||||
run_cmd curl -fL "$sha_url" -o "$hash_file"
|
||||
|
||||
local expected_sum
|
||||
local actual_sum
|
||||
expected_sum="$(awk '{print $1}' "$hash_file" | head -n 1 || true)"
|
||||
actual_sum="$(nethergamesmc_sha256_file "$composer_path" || true)"
|
||||
if [[ -n "$expected_sum" && -n "$actual_sum" && "$expected_sum" == "$actual_sum" ]]; then
|
||||
run_cmd rm -f "$hash_file"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Fallback to latest release asset when hash check is unavailable or changed
|
||||
run_cmd rm -f "$composer_path" "$hash_file"
|
||||
run_cmd curl -fL "https://github.com/composer/composer/releases/latest/download/composer.phar" -o "$composer_path"
|
||||
}
|
||||
|
||||
nethergamesmc_render_start_script() {
|
||||
local php_bin="$1"
|
||||
|
||||
emit_step "core_render" "nethergamesmc start script"
|
||||
run_cmd bash -c "cat > '$SERVER_DIR/start.sh' <<EOF
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
cd \"\$(dirname \"\$0\")\"
|
||||
exec '${php_bin}' -n server.phar
|
||||
EOF"
|
||||
run_cmd chmod +x "$SERVER_DIR/start.sh"
|
||||
emit_step "chmod_start_script" "$SERVER_DIR/start.sh"
|
||||
}
|
||||
|
||||
nethergamesmc_build_server_phar() {
|
||||
local php_bin="$1"
|
||||
local composer_path="$2"
|
||||
|
||||
if [[ "${DRY_RUN:-no}" == "yes" ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
emit_step "core_repo_clone" "${MC_VERSION:-latest}"
|
||||
emit_step "core_fetch" "PocketMine-MP source"
|
||||
local work_dir="${SERVER_DIR}/.nethergamesmc-work"
|
||||
run_cmd rm -rf "$work_dir"
|
||||
run_cmd mkdir -p "$work_dir"
|
||||
|
||||
if [[ "$MC_VERSION" != "latest" && -n "$MC_VERSION" ]]; then
|
||||
run_cmd git clone --depth 1 --branch "$MC_VERSION" "https://github.com/NetherGamesMC/PocketMine-MP.git" "$work_dir"
|
||||
else
|
||||
run_cmd git clone --depth 1 "https://github.com/NetherGamesMC/PocketMine-MP.git" "$work_dir"
|
||||
fi
|
||||
|
||||
run_cmd cp "$composer_path" "$work_dir/composer.phar"
|
||||
run_cmd bash -lc "cd '$work_dir' && COMPOSER_ALLOW_SUPERUSER=1 COMPOSER_NO_INTERACTION=1 '$php_bin' -n composer.phar install --no-dev --classmap-authoritative --no-ansi --no-progress --quiet"
|
||||
run_cmd bash -lc "cd '$work_dir' && COMPOSER_ALLOW_SUPERUSER=1 COMPOSER_NO_INTERACTION=1 '$php_bin' -n composer.phar make-server --no-dev --classmap-authoritative --no-ansi --no-progress --quiet"
|
||||
|
||||
if [[ ! -f "$work_dir/PocketMine-MP.phar" ]]; then
|
||||
fail "$(t no_stable_build "PocketMine-MP.phar" "PocketMine-MP")"
|
||||
fi
|
||||
|
||||
emit_step "core_fetch" "PocketMine-MP.phar"
|
||||
run_cmd mv "$work_dir/PocketMine-MP.phar" "$SERVER_DIR/server.phar"
|
||||
run_cmd rm -rf "$work_dir"
|
||||
}
|
||||
|
||||
core_install_nethergamesmc() {
|
||||
info "$(t core_install "$(core_name_nethergamesmc)")"
|
||||
emit_step "core_install" "$(core_name_nethergamesmc)"
|
||||
|
||||
local build_tag
|
||||
build_tag="$(nethergamesmc_get_php_build_release_tag "${BUILD:-latest}")"
|
||||
info "PHP build selected: ${build_tag}"
|
||||
local php_bin
|
||||
php_bin="$(nethergamesmc_ensure_php_runtime "$build_tag")"
|
||||
nethergamesmc_fetch_composer "$php_bin" "${php_bin%/bin/php}/composer.phar"
|
||||
|
||||
nethergamesmc_build_server_phar "$php_bin" "${php_bin%/bin/php}/composer.phar"
|
||||
nethergamesmc_render_start_script "$php_bin"
|
||||
emit_step "core_configure" "nethergamesmc build marker"
|
||||
run_cmd printf '%s\n' "$build_tag" > "$SERVER_DIR/.nethergamesmc-build"
|
||||
emit_step "core_configure" "nethergamesmc done"
|
||||
}
|
||||
|
||||
core_post_install_nethergamesmc() {
|
||||
emit_step "core_post" "NetherGamesMC"
|
||||
run_cmd bash -lc "chown -R ${SERVER_USER}:${SERVER_USER} '$SERVER_DIR'"
|
||||
emit_step "core_chown" "NetherGamesMC"
|
||||
open_firewall_port "$SERVER_PORT" "udp"
|
||||
emit_step "core_service" "NetherGamesMC"
|
||||
create_service "$CORE" "$SERVER_DIR" "$SERVICE_MODE" "$SERVER_DIR/start.sh"
|
||||
start_service
|
||||
}
|
||||
|
||||
core_update_nethergamesmc() {
|
||||
info "$(t core_update "$(core_name_nethergamesmc)")"
|
||||
emit_step "core_update" "$(core_name_nethergamesmc)"
|
||||
|
||||
backup_file "$SERVER_DIR/server.phar"
|
||||
backup_file "$SERVER_DIR/start.sh"
|
||||
backup_file "$SERVER_DIR/.nethergamesmc-build"
|
||||
core_install_nethergamesmc
|
||||
emit_step "core_update_done" "NetherGamesMC"
|
||||
}
|
||||
708
install.sh
Normal file
708
install.sh
Normal file
@@ -0,0 +1,708 @@
|
||||
#!/usr/bin/env bash
|
||||
set -Eeuo pipefail
|
||||
|
||||
DEPLOY_VERSION="0.1.0"
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
LIB_DIR="$SCRIPT_DIR/lib"
|
||||
CORE_DIR="$SCRIPT_DIR/cores"
|
||||
|
||||
CORE=""
|
||||
SERVER_DIR=""
|
||||
SERVER_PORT=""
|
||||
MC_VERSION="latest"
|
||||
BUILD="latest"
|
||||
RAM="2G"
|
||||
SERVICE_MODE="tmux-systemd"
|
||||
FIREWALL="yes"
|
||||
SERVER_USER="minecraft"
|
||||
ACCEPT_EULA="no"
|
||||
ACCEPT_LICENSE="no"
|
||||
LOCALE="${LANGUAGE:-${LANG:-en}}"
|
||||
ASSUME_YES="no"
|
||||
BEGINNER_MODE="no"
|
||||
DRY_RUN="no"
|
||||
DEBUG="no"
|
||||
REPORT_URL=""
|
||||
REPORT_TOKEN=""
|
||||
VERSION_REQUEST="no"
|
||||
SELF_UPDATE="no"
|
||||
ALLOW_EXISTING="no"
|
||||
BACKUP_EXISTING="no"
|
||||
FORCE_CLEAN="no"
|
||||
UPDATE_MODE="no"
|
||||
STEP_INDEX=0
|
||||
STEP_TOTAL=30
|
||||
|
||||
CORE_DEFAULT_PORT=""
|
||||
CORE_PROTOCOL=""
|
||||
CORE_RUNTIME=""
|
||||
CORE_NAME=""
|
||||
CORE_SERVICE_NAME=""
|
||||
|
||||
OS_ID=""
|
||||
OS_VERSION=""
|
||||
ARCHITECTURE=""
|
||||
PKG_MANAGER=""
|
||||
INIT_SYSTEM=""
|
||||
|
||||
LOG_DIR="/var/log/astra-deploy"
|
||||
LOG_FILE=""
|
||||
|
||||
if shopt -s nullglob 2>/dev/null; then
|
||||
for lib in "$LIB_DIR"/*.sh; do
|
||||
# shellcheck source=/dev/null
|
||||
. "$lib"
|
||||
done
|
||||
shopt -u nullglob
|
||||
else
|
||||
for lib in "$LIB_DIR"/*.sh; do
|
||||
. "$lib"
|
||||
done
|
||||
fi
|
||||
|
||||
usage() {
|
||||
cat <<EOF
|
||||
AstraDeploy v${DEPLOY_VERSION}
|
||||
|
||||
Usage:
|
||||
curl -fsSL https://deploy.example.com/install.sh | sudo bash -s -- [options]
|
||||
|
||||
Options:
|
||||
--core <pmmp|paper|purpur|velocity|powernukkitx|nethergamesmc>
|
||||
--core-version <latest|version> (legacy alias for mc-version)
|
||||
--dir <path>
|
||||
--port <number>
|
||||
--mc-version <latest|version>
|
||||
--version <latest|version> (legacy alias for mc-version)
|
||||
--build <latest|number>
|
||||
--ram <2G>
|
||||
--service <systemd|tmux-systemd|screen|none>
|
||||
--firewall <yes|no>
|
||||
--user <username>
|
||||
--accept-eula <yes|no>
|
||||
--eula <yes|no> (legacy alias for accept-eula)
|
||||
--accept-license <yes|no>
|
||||
--license <yes|no> (legacy alias for accept-license)
|
||||
--locale <en|ru>
|
||||
--lang <en|ru>
|
||||
--easy, -E
|
||||
--dry-run
|
||||
--yes
|
||||
--non-interactive
|
||||
--allow-existing
|
||||
--backup-existing
|
||||
--force-clean
|
||||
--report-url <url>
|
||||
--report-token <token>
|
||||
--debug
|
||||
--version (legacy mc-version) without value to print tool version
|
||||
--self-update
|
||||
--script-version
|
||||
-V
|
||||
--update
|
||||
--help
|
||||
|
||||
Examples:
|
||||
# Быстрый запуск для нубов (без вопросов):
|
||||
sudo bash install.sh --easy --core paper
|
||||
# Полный non-interactive запуск для автоматизации (бота):
|
||||
sudo bash install.sh --yes --core paper --dir /opt/minecraft/paper --service tmux-systemd --locale ru
|
||||
EOF
|
||||
}
|
||||
|
||||
emit_step() {
|
||||
local step_id="$1"
|
||||
local details="${2:-}"
|
||||
|
||||
STEP_INDEX=$((STEP_INDEX + 1))
|
||||
|
||||
local key="step_${step_id}"
|
||||
local message
|
||||
message="$(t "$key")"
|
||||
if [[ "$message" == "$key" ]]; then
|
||||
message="${step_id}"
|
||||
fi
|
||||
|
||||
if [[ -n "$details" ]]; then
|
||||
message="${message}: ${details}"
|
||||
fi
|
||||
|
||||
info "$(t progress_step "$STEP_INDEX" "$message")"
|
||||
send_report "step" "$message" "$step_id" "$STEP_INDEX" "$STEP_TOTAL"
|
||||
}
|
||||
|
||||
init_step_counter() {
|
||||
if is_java_core "$CORE"; then
|
||||
STEP_TOTAL=80
|
||||
else
|
||||
STEP_TOTAL=60
|
||||
fi
|
||||
|
||||
if [[ "$UPDATE_MODE" == "yes" ]]; then
|
||||
STEP_TOTAL=$((STEP_TOTAL - 6))
|
||||
if (( STEP_TOTAL < 10 )); then
|
||||
STEP_TOTAL=10
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
show_license() {
|
||||
info "$(t license_title)"
|
||||
info "$(t license_intro)"
|
||||
info "$(t license_item_1)"
|
||||
info "$(t license_item_2)"
|
||||
info "$(t license_item_3)"
|
||||
info "$(t license_item_4)"
|
||||
info "$(t license_item_5)"
|
||||
info "$(t license_item_6)"
|
||||
}
|
||||
|
||||
parse_bool() {
|
||||
case "${1,,}" in
|
||||
yes|y|1|true|on) echo yes ;;
|
||||
no|n|0|false|off) echo no ;;
|
||||
*) echo "" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
parse_args() {
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--core)
|
||||
CORE="${2:-}"; shift 2 ;;
|
||||
--core=*)
|
||||
CORE="${1#*=}"; shift ;;
|
||||
--core-version)
|
||||
MC_VERSION="${2:-}"; shift 2 ;;
|
||||
--core-version=*)
|
||||
MC_VERSION="${1#*=}"; shift ;;
|
||||
--dir)
|
||||
SERVER_DIR="${2:-}"; shift 2 ;;
|
||||
--dir=*)
|
||||
SERVER_DIR="${1#*=}"; shift ;;
|
||||
--port)
|
||||
SERVER_PORT="${2:-}"; shift 2 ;;
|
||||
--port=*)
|
||||
SERVER_PORT="${1#*=}"; shift ;;
|
||||
--mc-version)
|
||||
MC_VERSION="${2:-}"; shift 2 ;;
|
||||
--mc-version=*)
|
||||
MC_VERSION="${1#*=}"; shift ;;
|
||||
--version-code)
|
||||
MC_VERSION="${2:-}"; shift 2 ;;
|
||||
--version-code=*)
|
||||
MC_VERSION="${1#*=}"; shift ;;
|
||||
--version)
|
||||
if [[ "${2:-}" == "" || "${2:-}" == --* ]]; then
|
||||
VERSION_REQUEST="yes"
|
||||
shift
|
||||
else
|
||||
MC_VERSION="${2:-}"
|
||||
shift 2
|
||||
fi
|
||||
;;
|
||||
--build)
|
||||
BUILD="${2:-}"; shift 2 ;;
|
||||
--build=*)
|
||||
BUILD="${1#*=}"; shift ;;
|
||||
--ram)
|
||||
RAM="${2:-}"; shift 2 ;;
|
||||
--ram=*)
|
||||
RAM="${1#*=}"; shift ;;
|
||||
--service)
|
||||
SERVICE_MODE="${2:-}"; shift 2 ;;
|
||||
--service=*)
|
||||
SERVICE_MODE="${1#*=}"; shift ;;
|
||||
--firewall)
|
||||
FIREWALL="$(parse_bool "${2:-}")"; shift 2 ;;
|
||||
--firewall=*)
|
||||
FIREWALL="$(parse_bool "${1#*=}")"; shift ;;
|
||||
--user)
|
||||
SERVER_USER="${2:-}"; shift 2 ;;
|
||||
--user=*)
|
||||
SERVER_USER="${1#*=}"; shift ;;
|
||||
--accept-eula)
|
||||
ACCEPT_EULA="$(parse_bool "${2:-}")"; shift 2 ;;
|
||||
--accept-eula=*)
|
||||
ACCEPT_EULA="$(parse_bool "${1#*=}")"; shift ;;
|
||||
--eula)
|
||||
ACCEPT_EULA="$(parse_bool "${2:-}")"; shift 2 ;;
|
||||
--eula=*)
|
||||
ACCEPT_EULA="$(parse_bool "${1#*=}")"; shift ;;
|
||||
--accept-license)
|
||||
ACCEPT_LICENSE="$(parse_bool "${2:-}")"; shift 2 ;;
|
||||
--accept-license=*)
|
||||
ACCEPT_LICENSE="$(parse_bool "${1#*=}")"; shift ;;
|
||||
--license)
|
||||
ACCEPT_LICENSE="$(parse_bool "${2:-}")"; shift 2 ;;
|
||||
--license=*)
|
||||
ACCEPT_LICENSE="$(parse_bool "${1#*=}")"; shift ;;
|
||||
--locale)
|
||||
LOCALE="${2:-}"; shift 2 ;;
|
||||
--locale=*)
|
||||
LOCALE="${1#*=}"; shift ;;
|
||||
--lang)
|
||||
LOCALE="${2:-}"; shift 2 ;;
|
||||
--lang=*)
|
||||
LOCALE="${1#*=}"; shift ;;
|
||||
--easy|--beginner|-E)
|
||||
BEGINNER_MODE="yes"
|
||||
ASSUME_YES="yes"
|
||||
shift
|
||||
;;
|
||||
--dry-run)
|
||||
DRY_RUN="yes"; shift ;;
|
||||
--yes|-y)
|
||||
ASSUME_YES="yes"; shift ;;
|
||||
--non-interactive)
|
||||
ASSUME_YES="yes"; shift ;;
|
||||
--allow-existing)
|
||||
ALLOW_EXISTING="yes"; shift ;;
|
||||
--backup-existing)
|
||||
BACKUP_EXISTING="yes"; shift ;;
|
||||
--force-clean)
|
||||
FORCE_CLEAN="yes"; shift ;;
|
||||
--report-url)
|
||||
REPORT_URL="${2:-}"; shift 2 ;;
|
||||
--report-url=*)
|
||||
REPORT_URL="${1#*=}"; shift ;;
|
||||
--report-token)
|
||||
REPORT_TOKEN="${2:-}"; shift 2 ;;
|
||||
--report-token=*)
|
||||
REPORT_TOKEN="${1#*=}"; shift ;;
|
||||
--debug)
|
||||
DEBUG="yes"; shift ;;
|
||||
--script-version|-V)
|
||||
VERSION_REQUEST="yes"; shift ;;
|
||||
--self-update)
|
||||
SELF_UPDATE="yes"; shift ;;
|
||||
--update)
|
||||
UPDATE_MODE="yes"; shift ;;
|
||||
--help|-h)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
error "$(t unknown_argument "$1")"
|
||||
usage
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ "$FIREWALL" == "" ]]; then
|
||||
FIREWALL="yes"
|
||||
fi
|
||||
}
|
||||
|
||||
init_logger() {
|
||||
local timestamp
|
||||
timestamp="$(date +%F-%H-%M-%S)"
|
||||
mkdir -p "$LOG_DIR"
|
||||
LOG_FILE="$LOG_DIR/install-${timestamp}.log"
|
||||
exec > >(tee -a "$LOG_FILE") 2>&1
|
||||
info "$(t log_title "$DEPLOY_VERSION")"
|
||||
info "$(t log_file "$LOG_FILE")"
|
||||
}
|
||||
|
||||
resolve_core_defaults() {
|
||||
if [[ -z "$CORE" ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
local check_fn="core_default_port_${CORE}"
|
||||
if [[ "$(type -t "$check_fn" 2>/dev/null)" != "function" ]]; then
|
||||
fail "$(t unsupported_core "$CORE" "pmmp,paper,purpur,velocity,powernukkitx,nethergamesmc" "${SCRIPT_DIR}/manifests/cores.json")"
|
||||
fi
|
||||
|
||||
CORE_NAME="$(core_name_${CORE})"
|
||||
CORE_DEFAULT_PORT="$(core_default_port_${CORE})"
|
||||
CORE_PROTOCOL="$(core_protocol_${CORE})"
|
||||
CORE_RUNTIME="$(core_runtime_${CORE})"
|
||||
CORE_SERVICE_NAME="${CORE}_minecraft"
|
||||
|
||||
if [[ -z "$SERVER_PORT" ]]; then
|
||||
SERVER_PORT="$CORE_DEFAULT_PORT"
|
||||
fi
|
||||
}
|
||||
|
||||
ask_value() {
|
||||
local prompt_text="$1"
|
||||
local default_value="$2"
|
||||
local var_name="$3"
|
||||
|
||||
local value=""
|
||||
if [[ -t 0 ]]; then
|
||||
read -r -p "$prompt_text [$default_value]: " value < /dev/tty || true
|
||||
else
|
||||
read -r -p "$prompt_text [$default_value]: " value || true
|
||||
fi
|
||||
if [[ -z "$value" ]]; then
|
||||
value="$default_value"
|
||||
fi
|
||||
printf -v "$var_name" "%s" "$value"
|
||||
}
|
||||
|
||||
ask_yes_no() {
|
||||
local prompt_text="$1"
|
||||
local default_value="$2"
|
||||
local var_name="$3"
|
||||
|
||||
local value=""
|
||||
while true; do
|
||||
if [[ -t 0 ]]; then
|
||||
read -r -p "$prompt_text (yes/no) [$default_value]: " value < /dev/tty || true
|
||||
else
|
||||
read -r -p "$prompt_text (yes/no) [$default_value]: " value || true
|
||||
fi
|
||||
if [[ -z "$value" ]]; then
|
||||
value="$default_value"
|
||||
fi
|
||||
value="$(parse_bool "$value" || true)"
|
||||
if [[ "$value" == "yes" || "$value" == "no" ]]; then
|
||||
printf -v "$var_name" "%s" "$value"
|
||||
return
|
||||
fi
|
||||
warn "$(t prompt_invalid_yes_no)"
|
||||
done
|
||||
}
|
||||
|
||||
apply_noob_defaults() {
|
||||
if [[ -z "$CORE" ]]; then
|
||||
CORE="paper"
|
||||
fi
|
||||
|
||||
if [[ -z "$RAM" ]]; then
|
||||
RAM="2G"
|
||||
fi
|
||||
if [[ -z "$SERVICE_MODE" ]]; then
|
||||
SERVICE_MODE="tmux-systemd"
|
||||
fi
|
||||
if [[ -z "$FIREWALL" ]]; then
|
||||
FIREWALL="yes"
|
||||
fi
|
||||
if [[ -z "$SERVER_USER" ]]; then
|
||||
SERVER_USER="minecraft"
|
||||
fi
|
||||
if [[ -z "$MC_VERSION" ]]; then
|
||||
MC_VERSION="latest"
|
||||
fi
|
||||
if [[ -z "$BUILD" ]]; then
|
||||
BUILD="latest"
|
||||
fi
|
||||
|
||||
resolve_core_defaults
|
||||
|
||||
if [[ -z "$SERVER_DIR" ]]; then
|
||||
SERVER_DIR="/opt/minecraft/$CORE"
|
||||
fi
|
||||
if [[ -z "$SERVER_PORT" ]]; then
|
||||
SERVER_PORT="$CORE_DEFAULT_PORT"
|
||||
fi
|
||||
|
||||
if [[ "$BEGINNER_MODE" == "yes" ]]; then
|
||||
FIREWALL="$(parse_bool "$FIREWALL" || true)"
|
||||
[[ "$FIREWALL" == "" ]] && FIREWALL="yes"
|
||||
ACCEPT_LICENSE="yes"
|
||||
if is_java_core "$CORE"; then
|
||||
ACCEPT_EULA="yes"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
show_noob_plan() {
|
||||
info "$(t easy_plan_title)"
|
||||
info "$(t easy_plan_core "$CORE")"
|
||||
info "$(t easy_plan_dir "$SERVER_DIR")"
|
||||
info "$(t easy_plan_port "$SERVER_PORT")"
|
||||
info "$(t easy_plan_ram "$RAM")"
|
||||
info "$(t easy_plan_service "$SERVICE_MODE")"
|
||||
info "$(t easy_plan_user "$SERVER_USER")"
|
||||
info "$(t easy_plan_firewall "$FIREWALL")"
|
||||
if [[ "$CORE" == "nethergamesmc" ]]; then
|
||||
info "$(t easy_plan_build "$BUILD")"
|
||||
info "$(t easy_plan_mc_version "$MC_VERSION")"
|
||||
fi
|
||||
if is_java_core "$CORE"; then
|
||||
info "$(t easy_plan_eula "$ACCEPT_EULA")"
|
||||
fi
|
||||
}
|
||||
|
||||
interact() {
|
||||
if [[ "$ASSUME_YES" == "yes" ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [[ -z "$CORE" ]]; then
|
||||
ask_value "$(t prompt_core)" "paper" CORE
|
||||
fi
|
||||
|
||||
resolve_core_defaults
|
||||
|
||||
if [[ -z "$SERVER_DIR" ]]; then
|
||||
ask_value "$(t prompt_server_directory)" "/opt/minecraft/$CORE" SERVER_DIR
|
||||
fi
|
||||
|
||||
if [[ -z "$SERVER_PORT" ]]; then
|
||||
ask_value "$(t prompt_server_port)" "$CORE_DEFAULT_PORT" SERVER_PORT
|
||||
fi
|
||||
|
||||
ask_value "$(t prompt_ram)" "$RAM" RAM
|
||||
if [[ "$CORE" == "nethergamesmc" ]]; then
|
||||
ask_value "$(t prompt_php_build)" "${BUILD:-latest}" BUILD
|
||||
ask_value "$(t prompt_pocketmine_version)" "${MC_VERSION:-latest}" MC_VERSION
|
||||
fi
|
||||
ask_value "$(t prompt_service_mode)" "$SERVICE_MODE" SERVICE_MODE
|
||||
ask_value "$(t prompt_open_firewall)" "$FIREWALL" FIREWALL
|
||||
FIREWALL="$(parse_bool "$FIREWALL" || true)"
|
||||
[[ "$FIREWALL" == "" ]] && FIREWALL="yes"
|
||||
ask_value "$(t prompt_install_user)" "$SERVER_USER" SERVER_USER
|
||||
|
||||
if is_java_core "$CORE"; then
|
||||
ask_yes_no "$(t eula_prompt)" "${ACCEPT_EULA}" ACCEPT_EULA
|
||||
fi
|
||||
}
|
||||
|
||||
configure_plan() {
|
||||
if [[ -z "$CORE" ]]; then
|
||||
fail "$(t core_required)"
|
||||
fi
|
||||
|
||||
resolve_core_defaults
|
||||
|
||||
local validate_fn="core_validate_${CORE}"
|
||||
if [[ "$(type -t "$validate_fn" 2>/dev/null)" != "function" ]]; then
|
||||
fail "$(t core_validator_missing "$CORE")"
|
||||
fi
|
||||
"$validate_fn"
|
||||
|
||||
if [[ -z "$SERVER_DIR" ]]; then
|
||||
fail "$(t server_dir_required)"
|
||||
fi
|
||||
if [[ -z "$SERVER_PORT" ]]; then
|
||||
fail "$(t server_port_required)"
|
||||
fi
|
||||
if [[ ! "$SERVER_PORT" =~ ^[0-9]+$ ]]; then
|
||||
fail "$(t port_must_be_numeric)"
|
||||
fi
|
||||
if (( SERVER_PORT < 1 || SERVER_PORT > 65535 )); then
|
||||
fail "$(t port_out_of_range "$SERVER_PORT")"
|
||||
fi
|
||||
|
||||
if [[ "$SERVICE_MODE" != "systemd" && "$SERVICE_MODE" != "tmux-systemd" && "$SERVICE_MODE" != "screen" && "$SERVICE_MODE" != "none" ]]; then
|
||||
fail "$(t invalid_service_mode "$SERVICE_MODE")"
|
||||
fi
|
||||
if [[ "$FIREWALL" != "yes" && "$FIREWALL" != "no" ]]; then
|
||||
fail "$(t invalid_firewall_value "$FIREWALL")"
|
||||
fi
|
||||
}
|
||||
|
||||
validate_license() {
|
||||
if [[ "${ACCEPT_LICENSE,,}" == "yes" ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [[ "$ASSUME_YES" == "yes" ]]; then
|
||||
fail "$(t license_denied)"
|
||||
fi
|
||||
|
||||
show_license
|
||||
ask_yes_no "$(t license_prompt)" "no" ACCEPT_LICENSE
|
||||
if [[ "${ACCEPT_LICENSE,,}" != "yes" ]]; then
|
||||
fail "$(t license_denied)"
|
||||
fi
|
||||
}
|
||||
|
||||
check_existing_directory() {
|
||||
if [[ ! -d "$SERVER_DIR" ]]; then
|
||||
run_cmd mkdir -p "$SERVER_DIR"
|
||||
return
|
||||
fi
|
||||
|
||||
if [[ -z "$(ls -A "$SERVER_DIR" 2>/dev/null)" ]]; then
|
||||
return
|
||||
fi
|
||||
|
||||
if [[ "$FORCE_CLEAN" == "yes" ]]; then
|
||||
run_cmd find "$SERVER_DIR" -mindepth 1 -maxdepth 1 -exec rm -rf -- {} +
|
||||
return
|
||||
fi
|
||||
|
||||
if [[ "$BACKUP_EXISTING" == "yes" ]]; then
|
||||
local backup_dir="${SERVER_DIR}.backup-$(date +%F-%H-%M-%S)"
|
||||
run_cmd cp -a "$SERVER_DIR" "$backup_dir"
|
||||
info "$(t dir_backed_up "$backup_dir")"
|
||||
return
|
||||
fi
|
||||
|
||||
if [[ "$ALLOW_EXISTING" == "yes" ]]; then
|
||||
return
|
||||
fi
|
||||
|
||||
if [[ "$ASSUME_YES" == "yes" ]]; then
|
||||
fail "$(t dir_not_empty_auto "$SERVER_DIR")"
|
||||
fi
|
||||
|
||||
warn "$(t dir_not_empty "$SERVER_DIR")"
|
||||
while true; do
|
||||
local action
|
||||
if [[ -t 0 ]]; then
|
||||
read -r -p "$(t dir_not_empty_actions)" action < /dev/tty || true
|
||||
else
|
||||
read -r -p "$(t dir_not_empty_actions)" action || true
|
||||
fi
|
||||
case "$action" in
|
||||
1) fail "$(t action_cancelled_by_user)";;
|
||||
2) return;;
|
||||
3)
|
||||
local backup_dir="${SERVER_DIR}.backup-$(date +%F-%H-%M-%S)"
|
||||
run_cmd cp -a "$SERVER_DIR" "$backup_dir"
|
||||
info "$(t dir_backed_up "$backup_dir")"
|
||||
return
|
||||
;;
|
||||
4)
|
||||
run_cmd find "$SERVER_DIR" -mindepth 1 -maxdepth 1 -exec rm -rf -- {} +
|
||||
return
|
||||
;;
|
||||
*)
|
||||
warn "$(t dir_invalid_option)"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
backup_file() {
|
||||
local path="$1"
|
||||
|
||||
if [[ ! -e "$path" ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
local backup_path="${path}.backup-$(date +%F-%H-%M-%S)"
|
||||
run_cmd cp -a "$path" "$backup_path"
|
||||
info "$(t file_backed_up "$path" "$backup_path")"
|
||||
}
|
||||
|
||||
preflight() {
|
||||
emit_step "preflight_begin"
|
||||
emit_step "preflight_validate_root"
|
||||
validate_root_usage
|
||||
emit_step "preflight_detect"
|
||||
emit_step "preflight_detect_os"
|
||||
detect_system
|
||||
emit_step "preflight_validate_support"
|
||||
validate_core_support
|
||||
if [[ "$UPDATE_MODE" == "yes" ]]; then
|
||||
emit_step "preflight_update_mode_check"
|
||||
if [[ ! -d "$SERVER_DIR" ]]; then
|
||||
fail "$(t update_requires_existing_dir)"
|
||||
fi
|
||||
if [[ -z "$(ls -A "$SERVER_DIR" 2>/dev/null)" ]]; then
|
||||
fail "$(t update_requires_non_empty_dir)"
|
||||
fi
|
||||
fi
|
||||
|
||||
emit_step "preflight_validate_plan"
|
||||
configure_plan
|
||||
emit_step "preflight_validate_licenses"
|
||||
validate_license
|
||||
validate_eula
|
||||
|
||||
emit_step "preflight_validate_port"
|
||||
if is_java_core "$CORE"; then
|
||||
validate_port "$SERVER_PORT" "tcp"
|
||||
else
|
||||
validate_port "$SERVER_PORT" "udp"
|
||||
fi
|
||||
|
||||
emit_step "preflight_directory"
|
||||
if [[ "$UPDATE_MODE" == "no" ]]; then
|
||||
check_existing_directory
|
||||
fi
|
||||
|
||||
emit_step "preflight_packages"
|
||||
install_base_packages
|
||||
|
||||
if is_java_core "$CORE"; then
|
||||
emit_step "preflight_java"
|
||||
install_java_21
|
||||
fi
|
||||
|
||||
emit_step "preflight_user"
|
||||
create_minecraft_user "$SERVER_USER"
|
||||
prepare_server_dir "$SERVER_DIR" "$SERVER_USER"
|
||||
}
|
||||
|
||||
install_core() {
|
||||
emit_step "install_core" "$CORE"
|
||||
|
||||
local install_fn="core_install_${CORE}"
|
||||
local post_fn="core_post_install_${CORE}"
|
||||
local update_fn="core_update_${CORE}"
|
||||
|
||||
if [[ "$UPDATE_MODE" == "yes" && "$(type -t "$update_fn" 2>/dev/null)" == "function" ]]; then
|
||||
stop_service_if_running "${CORE_SERVICE_NAME}"
|
||||
emit_step "update_core" "$CORE"
|
||||
"$update_fn"
|
||||
else
|
||||
emit_step "deploy_core" "$CORE"
|
||||
"$install_fn"
|
||||
fi
|
||||
|
||||
if [[ ! "$(type -t "$post_fn" 2>/dev/null)" == "function" ]]; then
|
||||
fail "$(t post_install_callback_missing "$CORE")"
|
||||
fi
|
||||
"$post_fn"
|
||||
}
|
||||
|
||||
finalize() {
|
||||
info "$(t install_completed "$CORE_NAME")"
|
||||
info "$(t result_server_dir "$SERVER_DIR")"
|
||||
info "$(t result_service_mode "${SERVICE_MODE_ACTIVE:-none}")"
|
||||
info "$(t result_service_name "${SERVICE_NAME:-${CORE}_minecraft}")"
|
||||
info "$(t result_log_file "$LOG_FILE")"
|
||||
send_report "success" "$(t install_finished)"
|
||||
}
|
||||
|
||||
main() {
|
||||
for core_file in "$CORE_DIR"/*.sh; do
|
||||
. "$core_file"
|
||||
done
|
||||
|
||||
load_locale
|
||||
parse_args "$@"
|
||||
|
||||
if [[ "$VERSION_REQUEST" == "yes" ]]; then
|
||||
echo "AstraDeploy v$DEPLOY_VERSION"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
load_locale
|
||||
validate_root_usage
|
||||
|
||||
init_logger
|
||||
trap 'rollback_on_error "$?" "$BASH_COMMAND"' ERR
|
||||
send_report "started" "Deployment started"
|
||||
|
||||
if [[ "$SELF_UPDATE" == "yes" ]]; then
|
||||
warn "$(t self_update_not_implemented)"
|
||||
fi
|
||||
|
||||
emit_step "parse_complete"
|
||||
interact
|
||||
emit_step "prepare_defaults"
|
||||
apply_noob_defaults
|
||||
if [[ "$BEGINNER_MODE" == "yes" ]]; then
|
||||
show_noob_plan
|
||||
fi
|
||||
init_step_counter
|
||||
emit_step "preflight_start"
|
||||
preflight
|
||||
emit_step "install_start"
|
||||
install_core
|
||||
emit_step "finalize"
|
||||
finalize
|
||||
}
|
||||
|
||||
main "$@"
|
||||
73
lib/validation.sh
Normal file
73
lib/validation.sh
Normal file
@@ -0,0 +1,73 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
validate_root_usage() {
|
||||
if [[ "$(id -u)" -ne 0 ]]; then
|
||||
fail "$(t root_required)"
|
||||
fi
|
||||
}
|
||||
|
||||
validate_core_support() {
|
||||
local supported_cores="pmmp,paper,purpur,velocity,powernukkitx,nethergamesmc"
|
||||
local supported_os="ubuntu,debian"
|
||||
local planned_os="arch,fedora,rocky,almalinux"
|
||||
|
||||
case "$CORE" in
|
||||
pmmp|paper|purpur|velocity|powernukkitx|nethergamesmc)
|
||||
;;
|
||||
*)
|
||||
fail "$(t unsupported_core "$CORE" "$supported_cores" "${SCRIPT_DIR}/manifests/cores.json")"
|
||||
;;
|
||||
esac
|
||||
|
||||
case "$OS_ID" in
|
||||
ubuntu|debian)
|
||||
return 0
|
||||
;;
|
||||
arch|fedora|rocky|almalinux)
|
||||
warn "$(t os_coreplanned "$OS_ID" "${SCRIPT_DIR}/manifests/os-support.json")"
|
||||
;;
|
||||
*)
|
||||
fail "$(t unsupported_os "$OS_ID" "$supported_os" "$planned_os" "${SCRIPT_DIR}/manifests/os-support.json")"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
validate_eula() {
|
||||
if ! is_java_core "$CORE"; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [[ "${ACCEPT_EULA,,}" != "yes" ]]; then
|
||||
fail "$(t eula_denied)"
|
||||
fi
|
||||
}
|
||||
|
||||
validate_port() {
|
||||
local port="$1"
|
||||
local protocol="$2"
|
||||
|
||||
if ! command -v ss >/dev/null 2>&1; then
|
||||
if command -v lsof >/dev/null 2>&1; then
|
||||
if [[ "$protocol" == "tcp" ]]; then
|
||||
if lsof -iTCP:"$port" -sTCP:LISTEN -n -P >/dev/null 2>&1; then
|
||||
fail "$(t tcp_port_in_use "$port")"
|
||||
fi
|
||||
else
|
||||
if lsof -iUDP:"$port" -n -P >/dev/null 2>&1; then
|
||||
fail "$(t udp_port_in_use "$port")"
|
||||
fi
|
||||
fi
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ "$protocol" == "tcp" ]]; then
|
||||
if ss -ltn | awk '{print $4}' | grep -q ":${port}$"; then
|
||||
fail "$(t tcp_port_in_use "$port")"
|
||||
fi
|
||||
else
|
||||
if ss -lun | awk '{print $5}' | grep -q ":${port}$"; then
|
||||
fail "$(t udp_port_in_use "$port")"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
157
locales/en.sh
Normal file
157
locales/en.sh
Normal file
@@ -0,0 +1,157 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
locale_msg_unknown_argument() { echo "Unknown argument: $1"; }
|
||||
locale_msg_self_update_not_implemented() { echo "Self-update is not implemented in v0.1.0"; }
|
||||
|
||||
locale_msg_license_title() { echo "AstraDeploy License Agreement"; }
|
||||
locale_msg_license_intro() { echo "Important conditions for running this installer."; }
|
||||
locale_msg_license_item_1() { echo "- Installer executes privileged actions via root/sudo."; }
|
||||
locale_msg_license_item_2() { echo "- The script may modify system packages, services, firewall, user and files."; }
|
||||
locale_msg_license_item_3() { echo "- Backup important data before updating or replacing server files."; }
|
||||
locale_msg_license_item_4() { echo "- You are responsible for core licensing and server data."; }
|
||||
locale_msg_license_item_5() { echo "- AstraDeploy does not store your data and is not liable for any data loss."; }
|
||||
locale_msg_license_item_6() { echo "- Agreement: AstraDeploy is provided \"as is\" without warranties, and you use it at your own risk."; }
|
||||
locale_msg_log_title() { echo "AstraDeploy v$1"; }
|
||||
locale_msg_log_file() { echo "Log file: $1"; }
|
||||
locale_msg_license_prompt() { echo "Continue installation after accepting terms?"; }
|
||||
locale_msg_license_denied() { echo "Installation stopped: terms not accepted."; }
|
||||
locale_msg_eula_prompt() { echo "Accept Minecraft EULA for Java cores (Paper/Purpur/Velocity/PowerNukkitX)?"; }
|
||||
locale_msg_eula_denied() { echo "Java installation cannot continue without EULA acceptance."; }
|
||||
locale_msg_progress_step() { echo "Step $1: $2"; }
|
||||
locale_msg_step_parse_complete() { echo "Arguments parsed"; }
|
||||
locale_msg_step_prepare_defaults() { echo "Applying plan defaults"; }
|
||||
locale_msg_step_preflight_start() { echo "Starting preflight checks"; }
|
||||
locale_msg_step_install_start() { echo "Starting install"; }
|
||||
locale_msg_step_finalize() { echo "Finalizing"; }
|
||||
locale_msg_step_preflight_begin() { echo "Start preflight"; }
|
||||
locale_msg_step_preflight_detect() { echo "Detecting OS and package manager"; }
|
||||
locale_msg_step_preflight_update_mode_check() { echo "Checking update mode constraints"; }
|
||||
locale_msg_step_preflight_validate_plan() { echo "Validating installation plan"; }
|
||||
locale_msg_step_preflight_validate_licenses() { echo "Validating license agreements"; }
|
||||
locale_msg_step_preflight_validate_port() { echo "Checking port availability"; }
|
||||
locale_msg_step_preflight_directory() { echo "Preparing server directory"; }
|
||||
locale_msg_step_preflight_packages() { echo "Installing base packages"; }
|
||||
locale_msg_step_preflight_java() { echo "Installing Java components"; }
|
||||
locale_msg_step_preflight_user() { echo "Preparing service user"; }
|
||||
locale_msg_step_preflight_validate_root() { echo "Checking root privileges"; }
|
||||
locale_msg_step_preflight_detect_os() { echo "Detecting OS details"; }
|
||||
locale_msg_step_preflight_validate_support() { echo "Checking support matrix"; }
|
||||
locale_msg_step_install_core() { echo "Installing core"; }
|
||||
locale_msg_step_update_core() { echo "Updating core"; }
|
||||
locale_msg_step_deploy_core() { echo "Deploying core"; }
|
||||
locale_msg_step_packages_start() { echo "Installing dependencies"; }
|
||||
locale_msg_step_packages_dry_run() { echo "Dependencies dry-run"; }
|
||||
locale_msg_step_packages_index() { echo "Refreshing package index"; }
|
||||
locale_msg_step_download_start() { echo "Downloading artifact"; }
|
||||
locale_msg_step_download_completed() { echo "Artifact downloaded"; }
|
||||
locale_msg_step_download_swap() { echo "Swapping updated artifact"; }
|
||||
locale_msg_step_firewall_start() { echo "Configuring firewall"; }
|
||||
locale_msg_step_firewall_done() { echo "Firewall configured"; }
|
||||
locale_msg_step_firewall_manual() { echo "Firewall not auto-configured"; }
|
||||
locale_msg_step_java_install() { echo "Installing Java runtime"; }
|
||||
locale_msg_step_render_start_script() { echo "Generating start script"; }
|
||||
locale_msg_step_chmod_start_script() { echo "Adjusting start script permissions"; }
|
||||
locale_msg_step_user_create() { echo "Creating service user"; }
|
||||
locale_msg_step_user_exists() { echo "Service user already exists"; }
|
||||
locale_msg_step_prepare_dir() { echo "Creating server directory"; }
|
||||
locale_msg_step_permission_fix() { echo "Applying ownership and permissions"; }
|
||||
locale_msg_step_service_stop() { echo "Stopping existing service"; }
|
||||
locale_msg_step_service_create() { echo "Creating service unit"; }
|
||||
locale_msg_step_service_reload_enable() { echo "Enabling service"; }
|
||||
locale_msg_step_service_start() { echo "Starting server service"; }
|
||||
locale_msg_step_core_install() { echo "Core installation start"; }
|
||||
locale_msg_step_core_resolve_channel() { echo "Resolving distribution channel"; }
|
||||
locale_msg_step_core_resolve_download() { echo "Resolving download source"; }
|
||||
locale_msg_step_core_fetch() { echo "Fetching core files"; }
|
||||
locale_msg_step_core_render() { echo "Rendering core startup files"; }
|
||||
locale_msg_step_core_phpbuild_resolve() { echo "Resolving PHP build"; }
|
||||
locale_msg_step_core_phpbuild_fetch() { echo "Downloading PHP build archive"; }
|
||||
locale_msg_step_core_runtime() { echo "Preparing PHP runtime"; }
|
||||
locale_msg_step_core_composer() { echo "Preparing Composer"; }
|
||||
locale_msg_step_core_repo_clone() { echo "Cloning PocketMine-MP source"; }
|
||||
locale_msg_step_core_configure() { echo "Writing core config files"; }
|
||||
locale_msg_step_core_post() { echo "Core post-setup"; }
|
||||
locale_msg_step_core_service() { echo "Preparing service start"; }
|
||||
locale_msg_step_core_chown() { echo "Adjusting file ownership"; }
|
||||
locale_msg_step_core_backup() { echo "Backing up existing files"; }
|
||||
locale_msg_step_core_update_done() { echo "Core update completed"; }
|
||||
|
||||
locale_msg_core_required() { echo "Core is required. Use --core."; }
|
||||
locale_msg_core_validator_missing() { echo "Core validator missing for $1"; }
|
||||
locale_msg_server_dir_required() { echo "Server directory is required."; }
|
||||
locale_msg_server_port_required() { echo "Server port is required."; }
|
||||
locale_msg_port_must_be_numeric() { echo "Port must be numeric."; }
|
||||
locale_msg_port_out_of_range() { echo "Port out of range: $1"; }
|
||||
locale_msg_invalid_service_mode() { echo "Invalid service mode: $1"; }
|
||||
locale_msg_invalid_firewall_value() { echo "Invalid --firewall value: $1"; }
|
||||
|
||||
locale_msg_prompt_core() { echo "Core (pmmp|paper|purpur|velocity|powernukkitx|nethergamesmc)"; }
|
||||
locale_msg_prompt_server_directory() { echo "Server directory"; }
|
||||
locale_msg_prompt_server_port() { echo "Server port"; }
|
||||
locale_msg_prompt_ram() { echo "RAM"; }
|
||||
locale_msg_prompt_php_build() { echo "PHP build tag (latest|tag)"; }
|
||||
locale_msg_prompt_pocketmine_version() { echo "PocketMine-MCPE version/tag (latest|tag)"; }
|
||||
locale_msg_prompt_service_mode() { echo "Service mode"; }
|
||||
locale_msg_prompt_open_firewall() { echo "Open firewall (yes/no)"; }
|
||||
locale_msg_prompt_install_user() { echo "Install user"; }
|
||||
locale_msg_prompt_invalid_yes_no() { echo "Invalid answer: use yes/no"; }
|
||||
locale_msg_easy_plan_title() { echo "Easy mode enabled. Plan:"; }
|
||||
locale_msg_easy_plan_core() { echo "Core: $1"; }
|
||||
locale_msg_easy_plan_dir() { echo "Directory: $1"; }
|
||||
locale_msg_easy_plan_port() { echo "Port: $1"; }
|
||||
locale_msg_easy_plan_ram() { echo "RAM: $1"; }
|
||||
locale_msg_easy_plan_service() { echo "Service: $1"; }
|
||||
locale_msg_easy_plan_user() { echo "Service user: $1"; }
|
||||
locale_msg_easy_plan_firewall() { echo "Firewall: $1"; }
|
||||
locale_msg_easy_plan_build() { echo "PHP build: $1"; }
|
||||
locale_msg_easy_plan_mc_version() { echo "PocketMine-MCPE tag: $1"; }
|
||||
locale_msg_easy_plan_eula() { echo "EULA: $1"; }
|
||||
|
||||
locale_msg_dir_not_empty_auto() { echo "Directory '$1' is not empty. Add --allow-existing, --backup-existing or --force-clean."; }
|
||||
locale_msg_dir_not_empty() { echo "Directory '$1' is not empty"; }
|
||||
locale_msg_dir_not_empty_actions() { echo "1) cancel, 2) use existing, 3) backup existing, 4) force clean: "; }
|
||||
locale_msg_dir_backed_up() { echo "Existing server backed up to $1"; }
|
||||
locale_msg_action_cancelled_by_user() { echo "Installation cancelled by user"; }
|
||||
locale_msg_dir_invalid_option() { echo "Invalid option"; }
|
||||
locale_msg_backed_up_file() { echo "Backed up existing file: $1 -> $2"; }
|
||||
locale_msg_file_backed_up() { echo "Backed up existing file: $1 -> $2"; }
|
||||
locale_msg_post_install_callback_missing() { echo "Post-install callback missing for core $1"; }
|
||||
locale_msg_install_completed() { echo "Installation completed for $1"; }
|
||||
locale_msg_result_server_dir() { echo "Server directory: $1"; }
|
||||
locale_msg_result_service_mode() { echo "Service mode: $1"; }
|
||||
locale_msg_result_service_name() { echo "Service name: $1"; }
|
||||
locale_msg_result_log_file() { echo "Log file: $1"; }
|
||||
locale_msg_install_finished() { echo "Installation finished"; }
|
||||
locale_msg_core_install() { echo "Installing $1..."; }
|
||||
locale_msg_core_update() { echo "Updating $1..."; }
|
||||
locale_msg_core_name_java_core() { echo "Java core $1"; }
|
||||
locale_msg_no_stable_build() { echo "No stable build found for ${1} ${2}"; }
|
||||
locale_msg_detect_os_failed() { echo "Cannot detect OS: /etc/os-release not found"; }
|
||||
locale_msg_no_package_manager() { echo "No supported package manager found"; }
|
||||
locale_msg_java_already_available() { echo "Java ${1} already available"; }
|
||||
locale_msg_installing_java_21() { echo "Installing Java 21"; }
|
||||
locale_msg_installing_base_packages() { echo "Installing base packages"; }
|
||||
locale_msg_dry_run_install() { echo "[dry-run] apt/yum/dnf/pacman install: $1"; }
|
||||
locale_msg_package_manager_unsupported() { echo "Package manager ${1} is not supported"; }
|
||||
locale_msg_firewall_skip() { echo "Firewall step skipped"; }
|
||||
locale_msg_firewall_manual_open() { echo "No supported firewall manager found. Open port manually: $1/$2"; }
|
||||
locale_msg_report_dry_run() { echo "Skipping report in dry-run: $1"; }
|
||||
locale_msg_report_failed() { echo "Report callback failed and was ignored"; }
|
||||
locale_msg_deployment_failed() { echo "Deployment failed (code $1) at: $2"; }
|
||||
locale_msg_rollback_starts() { echo "Rollback starts. Server directory is intentionally preserved: $1"; }
|
||||
locale_msg_see_log() { echo "See log: $1"; }
|
||||
locale_msg_service_create_skipped() { echo "Skipping service creation (mode=$1, init=$2)"; }
|
||||
locale_msg_service_start_skipped() { echo "Service start skipped (mode: $1)"; }
|
||||
locale_msg_refuse_root_user() { echo "Refusing to use root as server user"; }
|
||||
locale_msg_creating_user() { echo "Creating user $1"; }
|
||||
locale_msg_dry_run_useradd() { echo "[dry-run] useradd -r -m -s /bin/bash $1"; }
|
||||
|
||||
locale_msg_update_requires_existing_dir() { echo "Update mode requires existing directory."; }
|
||||
locale_msg_update_requires_non_empty_dir() { echo "Update mode requires non-empty server directory."; }
|
||||
|
||||
locale_msg_root_required() { echo "Run this script as root (example: sudo bash install.sh ...)"; }
|
||||
locale_msg_unsupported_core() { echo "Unsupported core '$1'. Supported now: $2. Full matrix in $3"; }
|
||||
locale_msg_os_coreplanned() { echo "OS '$1' is planned for v1.1 (manifest: $2). Proceeding best-effort."; }
|
||||
locale_msg_unsupported_os() { echo "Unsupported OS '$1'. Supported now: $2. Planned in future: $3. See $4"; }
|
||||
locale_msg_tcp_port_in_use() { echo "TCP port $1 is already in use."; }
|
||||
locale_msg_udp_port_in_use() { echo "UDP port $1 is already in use."; }
|
||||
157
locales/ru.sh
Normal file
157
locales/ru.sh
Normal file
@@ -0,0 +1,157 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
locale_msg_unknown_argument() { echo "Неизвестный аргумент: $1"; }
|
||||
locale_msg_self_update_not_implemented() { echo "Self-update пока не реализован в v0.1.0"; }
|
||||
|
||||
locale_msg_license_title() { echo "Лицензионное соглашение AstraDeploy"; }
|
||||
locale_msg_license_intro() { echo "Ниже приведены важные условия запуска утилиты."; }
|
||||
locale_msg_license_item_1() { echo "- Утилита выполняет команды с повышенными привилегиями (root/sudo)."; }
|
||||
locale_msg_license_item_2() { echo "- Утилита может изменять систему: пакеты, службы, firewall, пользователя и файлы."; }
|
||||
locale_msg_license_item_3() { echo "- Перед обновлением или заменой файлов рекомендуется сделать резервную копию."; }
|
||||
locale_msg_license_item_4() { echo "- Ответственность за лицензии ядра и данные сервера лежит на вас."; }
|
||||
locale_msg_license_item_5() { echo "- AstraDeploy не хранит и не отвечает за ваши данные и их потерю."; }
|
||||
locale_msg_license_item_6() { echo "- Соглашение: AstraDeploy поставляется «как есть», без каких-либо гарантий, и вы используете его на свой риск."; }
|
||||
locale_msg_log_title() { echo "AstraDeploy v$1"; }
|
||||
locale_msg_log_file() { echo "Файл журнала: $1"; }
|
||||
locale_msg_license_prompt() { echo "Продолжить установку после принятия условий?"; }
|
||||
locale_msg_license_denied() { echo "Установка остановлена: условия не приняты."; }
|
||||
locale_msg_eula_prompt() { echo "Подтверждаете принятие Minecraft EULA для Java ядер (Paper/Purpur/Velocity/PowerNukkitX)?"; }
|
||||
locale_msg_eula_denied() { echo "Без принятия EULA установка Java-сервера невозможна."; }
|
||||
locale_msg_progress_step() { echo "Шаг $1: $2"; }
|
||||
locale_msg_step_parse_complete() { echo "Аргументы обработаны"; }
|
||||
locale_msg_step_prepare_defaults() { echo "Применены параметры по умолчанию"; }
|
||||
locale_msg_step_preflight_start() { echo "Запуск предварительных проверок"; }
|
||||
locale_msg_step_install_start() { echo "Начало установки"; }
|
||||
locale_msg_step_finalize() { echo "Завершение"; }
|
||||
locale_msg_step_preflight_begin() { echo "Старт preflight"; }
|
||||
locale_msg_step_preflight_detect() { echo "Определение ОС и менеджера пакетов"; }
|
||||
locale_msg_step_preflight_update_mode_check() { echo "Проверка параметров режима обновления"; }
|
||||
locale_msg_step_preflight_validate_plan() { echo "Проверка плана установки"; }
|
||||
locale_msg_step_preflight_validate_licenses() { echo "Проверка соглашений"; }
|
||||
locale_msg_step_preflight_validate_port() { echo "Проверка свободного порта"; }
|
||||
locale_msg_step_preflight_directory() { echo "Подготовка каталога сервера"; }
|
||||
locale_msg_step_preflight_packages() { echo "Установка базовых пакетов"; }
|
||||
locale_msg_step_preflight_java() { echo "Подготовка компонентов Java"; }
|
||||
locale_msg_step_preflight_user() { echo "Подготовка пользователя сервиса"; }
|
||||
locale_msg_step_preflight_validate_root() { echo "Проверка запуска от root"; }
|
||||
locale_msg_step_preflight_detect_os() { echo "Определение параметров ОС"; }
|
||||
locale_msg_step_preflight_validate_support() { echo "Проверка матрицы поддерживаемых версий"; }
|
||||
locale_msg_step_install_core() { echo "Установка ядра"; }
|
||||
locale_msg_step_update_core() { echo "Обновление ядра"; }
|
||||
locale_msg_step_deploy_core() { echo "Развёртывание ядра"; }
|
||||
locale_msg_step_packages_start() { echo "Установка зависимостей"; }
|
||||
locale_msg_step_packages_dry_run() { echo "Симуляция установки зависимостей"; }
|
||||
locale_msg_step_packages_index() { echo "Обновление индекса пакетов"; }
|
||||
locale_msg_step_download_start() { echo "Загрузка артефакта"; }
|
||||
locale_msg_step_download_completed() { echo "Артефакт загружен"; }
|
||||
locale_msg_step_download_swap() { echo "Замена артефакта"; }
|
||||
locale_msg_step_firewall_start() { echo "Настройка firewall"; }
|
||||
locale_msg_step_firewall_done() { echo "Firewall настроен"; }
|
||||
locale_msg_step_firewall_manual() { echo "Firewall не настроен автоматически"; }
|
||||
locale_msg_step_java_install() { echo "Установка Java runtime"; }
|
||||
locale_msg_step_render_start_script() { echo "Генерация стартового скрипта"; }
|
||||
locale_msg_step_chmod_start_script() { echo "Настройка прав скрипта запуска"; }
|
||||
locale_msg_step_user_create() { echo "Создание сервисного пользователя"; }
|
||||
locale_msg_step_user_exists() { echo "Сервисный пользователь уже существует"; }
|
||||
locale_msg_step_prepare_dir() { echo "Создание каталога сервера"; }
|
||||
locale_msg_step_permission_fix() { echo "Применение владельца и прав"; }
|
||||
locale_msg_step_service_stop() { echo "Остановка существующего сервиса"; }
|
||||
locale_msg_step_service_create() { echo "Создание unit-файла"; }
|
||||
locale_msg_step_service_reload_enable() { echo "Активация сервиса"; }
|
||||
locale_msg_step_service_start() { echo "Запуск сервиса сервера"; }
|
||||
locale_msg_step_core_install() { echo "Старт установки ядра"; }
|
||||
locale_msg_step_core_resolve_channel() { echo "Определение канала выпуска"; }
|
||||
locale_msg_step_core_resolve_download() { echo "Поиск источника загрузки"; }
|
||||
locale_msg_step_core_fetch() { echo "Загрузка файлов ядра"; }
|
||||
locale_msg_step_core_render() { echo "Генерация файлов запуска"; }
|
||||
locale_msg_step_core_phpbuild_resolve() { echo "Определение PHP build"; }
|
||||
locale_msg_step_core_phpbuild_fetch() { echo "Загрузка архива PHP build"; }
|
||||
locale_msg_step_core_runtime() { echo "Подготовка PHP runtime"; }
|
||||
locale_msg_step_core_composer() { echo "Подготовка Composer"; }
|
||||
locale_msg_step_core_repo_clone() { echo "Клонирование источника PocketMine-MP"; }
|
||||
locale_msg_step_core_configure() { echo "Запись конфигураций ядра"; }
|
||||
locale_msg_step_core_post() { echo "Пост-настройка ядра"; }
|
||||
locale_msg_step_core_service() { echo "Подготовка запуска сервиса"; }
|
||||
locale_msg_step_core_chown() { echo "Настройка владения файлами"; }
|
||||
locale_msg_step_core_backup() { echo "Резервное копирование файлов"; }
|
||||
locale_msg_step_core_update_done() { echo "Обновление ядра завершено"; }
|
||||
|
||||
locale_msg_core_required() { echo "Необходимо указать ядро через --core."; }
|
||||
locale_msg_core_validator_missing() { echo "Для ядра $1 отсутствует валидатор."; }
|
||||
locale_msg_server_dir_required() { echo "Требуется указать каталог сервера."; }
|
||||
locale_msg_server_port_required() { echo "Требуется указать порт сервера."; }
|
||||
locale_msg_port_must_be_numeric() { echo "Порт должен быть числом."; }
|
||||
locale_msg_port_out_of_range() { echo "Порт вне диапазона: $1"; }
|
||||
locale_msg_invalid_service_mode() { echo "Неподдерживаемый режим сервиса: $1"; }
|
||||
locale_msg_invalid_firewall_value() { echo "Недопустимое значение --firewall: $1"; }
|
||||
|
||||
locale_msg_prompt_core() { echo "Ядро (pmmp|paper|purpur|velocity|powernukkitx|nethergamesmc)"; }
|
||||
locale_msg_prompt_server_directory() { echo "Каталог сервера"; }
|
||||
locale_msg_prompt_server_port() { echo "Порт сервера"; }
|
||||
locale_msg_prompt_ram() { echo "RAM"; }
|
||||
locale_msg_prompt_php_build() { echo "Тег PHP-билда (latest|tag)"; }
|
||||
locale_msg_prompt_pocketmine_version() { echo "Версия/тег PocketMine-MCPE (latest|tag)"; }
|
||||
locale_msg_prompt_service_mode() { echo "Режим сервиса"; }
|
||||
locale_msg_prompt_open_firewall() { echo "Открыть firewall (yes/no)"; }
|
||||
locale_msg_prompt_install_user() { echo "Пользователь для установки"; }
|
||||
locale_msg_prompt_invalid_yes_no() { echo "Неверный ответ: используйте yes/no"; }
|
||||
locale_msg_easy_plan_title() { echo "Режим easy активирован. План установки:"; }
|
||||
locale_msg_easy_plan_core() { echo "Ядро: $1"; }
|
||||
locale_msg_easy_plan_dir() { echo "Каталог: $1"; }
|
||||
locale_msg_easy_plan_port() { echo "Порт: $1"; }
|
||||
locale_msg_easy_plan_ram() { echo "RAM: $1"; }
|
||||
locale_msg_easy_plan_service() { echo "Сервис: $1"; }
|
||||
locale_msg_easy_plan_user() { echo "Пользователь сервиса: $1"; }
|
||||
locale_msg_easy_plan_firewall() { echo "Firewall: $1"; }
|
||||
locale_msg_easy_plan_build() { echo "PHP-билд: $1"; }
|
||||
locale_msg_easy_plan_mc_version() { echo "Версия/тег PocketMine-MCPE: $1"; }
|
||||
locale_msg_easy_plan_eula() { echo "EULA: $1"; }
|
||||
|
||||
locale_msg_dir_not_empty_auto() { echo "Каталог '$1' не пустой. Укажите --allow-existing, --backup-existing или --force-clean."; }
|
||||
locale_msg_dir_not_empty() { echo "Каталог '$1' не пустой"; }
|
||||
locale_msg_dir_not_empty_actions() { echo "1) отмена, 2) использовать существующий, 3) создать backup, 4) очистить: "; }
|
||||
locale_msg_dir_backed_up() { echo "Существующий сервер сохранён как $1"; }
|
||||
locale_msg_action_cancelled_by_user() { echo "Установка отменена пользователем"; }
|
||||
locale_msg_dir_invalid_option() { echo "Неверный вариант"; }
|
||||
locale_msg_backed_up_file() { echo "Файл скопирован: $1 -> $2"; }
|
||||
locale_msg_file_backed_up() { echo "Файл скопирован: $1 -> $2"; }
|
||||
locale_msg_post_install_callback_missing() { echo "Отсутствует шаг пост-установки для ядра $1"; }
|
||||
locale_msg_install_completed() { echo "Установка завершена для $1"; }
|
||||
locale_msg_result_server_dir() { echo "Каталог сервера: $1"; }
|
||||
locale_msg_result_service_mode() { echo "Режим сервиса: $1"; }
|
||||
locale_msg_result_service_name() { echo "Имя сервиса: $1"; }
|
||||
locale_msg_result_log_file() { echo "Файл журнала: $1"; }
|
||||
locale_msg_install_finished() { echo "Установка завершена"; }
|
||||
locale_msg_core_install() { echo "Установка $1..."; }
|
||||
locale_msg_core_update() { echo "Обновление $1..."; }
|
||||
locale_msg_core_name_java_core() { echo "Java ядро $1"; }
|
||||
locale_msg_no_stable_build() { echo "Не найден стабильный build для ${1} ${2}"; }
|
||||
locale_msg_detect_os_failed() { echo "Не удалось определить ОС: файл /etc/os-release отсутствует"; }
|
||||
locale_msg_no_package_manager() { echo "Поддерживаемый менеджер пакетов не найден"; }
|
||||
locale_msg_java_already_available() { echo "Java ${1} уже установлена"; }
|
||||
locale_msg_installing_java_21() { echo "Установка Java 21"; }
|
||||
locale_msg_installing_base_packages() { echo "Установка базовых пакетов"; }
|
||||
locale_msg_dry_run_install() { echo "[dry-run] apt/yum/dnf/pacman install: $1"; }
|
||||
locale_msg_package_manager_unsupported() { echo "Менеджер пакетов ${1} не поддерживается"; }
|
||||
locale_msg_firewall_skip() { echo "Шаг настройки firewall пропущен"; }
|
||||
locale_msg_firewall_manual_open() { echo "Не найден поддерживаемый менеджер firewall. Откройте порт вручную: $1/$2"; }
|
||||
locale_msg_report_dry_run() { echo "Пропуск отправки отчёта в dry-run: $1"; }
|
||||
locale_msg_report_failed() { echo "Не удалось отправить отчет в callback, ошибка проигнорирована"; }
|
||||
locale_msg_deployment_failed() { echo "Установка завершилась ошибкой (код $1) на шаге: $2"; }
|
||||
locale_msg_rollback_starts() { echo "Запущен rollback. Каталог сервера не удаляется: $1"; }
|
||||
locale_msg_see_log() { echo "См. лог: $1"; }
|
||||
locale_msg_service_create_skipped() { echo "Создание сервиса пропущено (mode=$1, init=$2)"; }
|
||||
locale_msg_service_start_skipped() { echo "Запуск сервиса пропущен (mode: $1)"; }
|
||||
locale_msg_refuse_root_user() { echo "Использование root как сервисного пользователя запрещено"; }
|
||||
locale_msg_creating_user() { echo "Создание пользователя $1"; }
|
||||
locale_msg_dry_run_useradd() { echo "[dry-run] useradd -r -m -s /bin/bash $1"; }
|
||||
|
||||
locale_msg_update_requires_existing_dir() { echo "Для обновления нужен существующий каталог сервера."; }
|
||||
locale_msg_update_requires_non_empty_dir() { echo "Для обновления нужен непустой каталог сервера."; }
|
||||
|
||||
locale_msg_root_required() { echo "Запустите скрипт от root (пример: sudo bash install.sh ...)"; }
|
||||
locale_msg_unsupported_core() { echo "Ядро '$1' не поддерживается. Доступны: $2. Полный список: $3"; }
|
||||
locale_msg_os_coreplanned() { echo "ОС '$1' запланирована к поддержке в v1.1 (манифест: $2). Применяется best-effort."; }
|
||||
locale_msg_unsupported_os() { echo "ОС '$1' не поддерживается. Сейчас поддерживается: $2. В планах: $3. См. $4"; }
|
||||
locale_msg_tcp_port_in_use() { echo "TCP порт $1 уже занят."; }
|
||||
locale_msg_udp_port_in_use() { echo "UDP порт $1 уже занят."; }
|
||||
66
manifests/cores.json
Normal file
66
manifests/cores.json
Normal file
@@ -0,0 +1,66 @@
|
||||
{
|
||||
"pmmp": {
|
||||
"name": "PocketMine-MP",
|
||||
"edition": "bedrock",
|
||||
"runtime": "php",
|
||||
"default_port": 19132,
|
||||
"protocol": "udp",
|
||||
"default_dir": "/opt/minecraft/pmmp",
|
||||
"supports_protocols": ["udp"],
|
||||
"supported_services": ["systemd", "tmux-systemd", "none"]
|
||||
},
|
||||
"paper": {
|
||||
"name": "Paper",
|
||||
"edition": "java",
|
||||
"runtime": "java",
|
||||
"java_version": 21,
|
||||
"default_port": 25565,
|
||||
"protocol": "tcp",
|
||||
"default_dir": "/opt/minecraft/paper",
|
||||
"supports_protocols": ["tcp"],
|
||||
"supported_services": ["systemd", "tmux-systemd", "none"]
|
||||
},
|
||||
"purpur": {
|
||||
"name": "Purpur",
|
||||
"edition": "java",
|
||||
"runtime": "java",
|
||||
"java_version": 21,
|
||||
"default_port": 25565,
|
||||
"protocol": "tcp",
|
||||
"default_dir": "/opt/minecraft/purpur",
|
||||
"supports_protocols": ["tcp"],
|
||||
"supported_services": ["systemd", "tmux-systemd", "none"]
|
||||
},
|
||||
"velocity": {
|
||||
"name": "Velocity",
|
||||
"edition": "proxy",
|
||||
"runtime": "java",
|
||||
"java_version": 21,
|
||||
"default_port": 25577,
|
||||
"protocol": "tcp",
|
||||
"default_dir": "/opt/minecraft/velocity",
|
||||
"supports_protocols": ["tcp"],
|
||||
"supported_services": ["systemd", "tmux-systemd", "none"]
|
||||
},
|
||||
"powernukkitx": {
|
||||
"name": "PowerNukkitX",
|
||||
"edition": "bedrock",
|
||||
"runtime": "java",
|
||||
"java_version": 21,
|
||||
"default_port": 19132,
|
||||
"protocol": "udp",
|
||||
"default_dir": "/opt/minecraft/powernukkitx",
|
||||
"supports_protocols": ["udp"],
|
||||
"supported_services": ["systemd", "tmux-systemd", "none"]
|
||||
},
|
||||
"nethergamesmc": {
|
||||
"name": "NetherGamesMC",
|
||||
"edition": "bedrock",
|
||||
"runtime": "php",
|
||||
"default_port": 19132,
|
||||
"protocol": "udp",
|
||||
"default_dir": "/opt/minecraft/nethergamesmc",
|
||||
"supports_protocols": ["udp"],
|
||||
"supported_services": ["systemd", "tmux-systemd", "screen", "none"]
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user