v1.0.1
- 新增stop后断后还占用 - 新增debug功能
This commit is contained in:
parent
21393566d8
commit
070faeaf29
181
install_server/install_server.sh
Normal file
181
install_server/install_server.sh
Normal file
@ -0,0 +1,181 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -Eeuo pipefail
|
||||||
|
|
||||||
|
STEAM_USER="steam"
|
||||||
|
STEAM_HOME="/home/steam"
|
||||||
|
|
||||||
|
STEAMCMD_DIR="${STEAM_HOME}/steamcmd"
|
||||||
|
ETS2_DIR="${STEAM_HOME}/ets2_sv"
|
||||||
|
ETS2_DOC_DIR="${STEAM_HOME}/ets2_doc"
|
||||||
|
|
||||||
|
ETS2_BIN_DIR="${ETS2_DIR}/bin/linux_x64"
|
||||||
|
SCRIPT_REPO="https://github.com/A-hxin/ets2_server.git"
|
||||||
|
TMP_SCRIPT_DIR="${ETS2_BIN_DIR}/server"
|
||||||
|
|
||||||
|
APP_ID="1948160"
|
||||||
|
|
||||||
|
echo "========================================"
|
||||||
|
echo " ETS2 Dedicated Server 一键部署脚本"
|
||||||
|
echo " System: Ubuntu"
|
||||||
|
echo "========================================"
|
||||||
|
|
||||||
|
if [ "$(id -u)" -ne 0 ]; then
|
||||||
|
echo "请使用 root 权限执行:"
|
||||||
|
echo "sudo bash install_ets2_server.sh"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "一、创建 steam 用户"
|
||||||
|
|
||||||
|
if id "${STEAM_USER}" >/dev/null 2>&1; then
|
||||||
|
echo "用户 ${STEAM_USER} 已存在,跳过创建"
|
||||||
|
else
|
||||||
|
adduser \
|
||||||
|
--system \
|
||||||
|
--shell /bin/bash \
|
||||||
|
--gecos 'Steam Service User' \
|
||||||
|
--group \
|
||||||
|
--disabled-password \
|
||||||
|
--home "${STEAM_HOME}" \
|
||||||
|
"${STEAM_USER}"
|
||||||
|
|
||||||
|
echo "用户 ${STEAM_USER} 创建完成"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "二、创建工作目录"
|
||||||
|
|
||||||
|
mkdir -p "${STEAMCMD_DIR}" "${ETS2_DIR}" "${ETS2_DOC_DIR}"
|
||||||
|
chown -R "${STEAM_USER}:${STEAM_USER}" "${STEAM_HOME}"
|
||||||
|
|
||||||
|
echo "目录创建完成:"
|
||||||
|
echo "${STEAMCMD_DIR}"
|
||||||
|
echo "${ETS2_DIR}"
|
||||||
|
echo "${ETS2_DOC_DIR}"
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "三、安装运行库"
|
||||||
|
|
||||||
|
dpkg --add-architecture i386 || true
|
||||||
|
|
||||||
|
apt update
|
||||||
|
|
||||||
|
apt install -y \
|
||||||
|
curl \
|
||||||
|
ca-certificates \
|
||||||
|
tar \
|
||||||
|
gzip \
|
||||||
|
git \
|
||||||
|
libc6:i386 \
|
||||||
|
libstdc++6:i386 \
|
||||||
|
libgcc-s1:i386 \
|
||||||
|
libx11-6:i386 \
|
||||||
|
libxext6:i386 \
|
||||||
|
libxau6:i386 \
|
||||||
|
libxdmcp6:i386 \
|
||||||
|
libncurses5:i386 \
|
||||||
|
libncursesw5:i386 \
|
||||||
|
libcurl4:i386 \
|
||||||
|
zlib1g:i386 \
|
||||||
|
libbz2-1.0:i386 \
|
||||||
|
libtinfo6:i386
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "四、下载 SteamCMD"
|
||||||
|
|
||||||
|
sudo -u "${STEAM_USER}" bash -c "
|
||||||
|
cd '${STEAMCMD_DIR}' &&
|
||||||
|
curl -sqL 'https://steamcdn-a.akamaihd.net/client/installer/steamcmd_linux.tar.gz' | tar zxvf -
|
||||||
|
"
|
||||||
|
|
||||||
|
chmod +x "${STEAMCMD_DIR}/steamcmd.sh" || true
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "五、安装 / 更新 ETS2 Dedicated Server"
|
||||||
|
|
||||||
|
sudo -u "${STEAM_USER}" bash -c "
|
||||||
|
cd '${STEAMCMD_DIR}' &&
|
||||||
|
'${STEAMCMD_DIR}/steamcmd.sh' \
|
||||||
|
+force_install_dir '${ETS2_DIR}' \
|
||||||
|
+login anonymous \
|
||||||
|
+app_update '${APP_ID}' validate \
|
||||||
|
+quit
|
||||||
|
"
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "六、安装 server.sh 管理脚本"
|
||||||
|
|
||||||
|
mkdir -p "${ETS2_BIN_DIR}"
|
||||||
|
|
||||||
|
rm -rf "${TMP_SCRIPT_DIR}"
|
||||||
|
|
||||||
|
sudo -u "${STEAM_USER}" git clone "${SCRIPT_REPO}" "${TMP_SCRIPT_DIR}"
|
||||||
|
|
||||||
|
if [ -f "${TMP_SCRIPT_DIR}/server.sh" ]; then
|
||||||
|
mv "${TMP_SCRIPT_DIR}/server.sh" "${ETS2_BIN_DIR}/server.sh"
|
||||||
|
chmod +x "${ETS2_BIN_DIR}/server.sh"
|
||||||
|
rm -rf "${TMP_SCRIPT_DIR}"
|
||||||
|
else
|
||||||
|
echo "错误:没有找到 server.sh"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "七、创建必要目录并设置权限"
|
||||||
|
|
||||||
|
mkdir -p "${ETS2_BIN_DIR}/logs"
|
||||||
|
mkdir -p "${ETS2_DOC_DIR}/Euro Truck Simulator 2"
|
||||||
|
|
||||||
|
chown -R "${STEAM_USER}:${STEAM_USER}" "${ETS2_BIN_DIR}"
|
||||||
|
chown -R "${STEAM_USER}:${STEAM_USER}" "${ETS2_DOC_DIR}"
|
||||||
|
|
||||||
|
chmod -R 775 "${ETS2_BIN_DIR}"
|
||||||
|
chmod -R 775 "${ETS2_DOC_DIR}"
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "八、创建快捷命令"
|
||||||
|
|
||||||
|
ln -sfn "${ETS2_BIN_DIR}/server.sh" /usr/local/bin/ets2_sv
|
||||||
|
chmod +x /usr/local/bin/ets2_sv
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "九、是否立即执行一次 server.sh 初始化?"
|
||||||
|
|
||||||
|
if [ -t 0 ]; then
|
||||||
|
read -rp "是否现在执行一次?可能会进入服务器运行状态 [y/N]: " RUN_ONCE
|
||||||
|
case "${RUN_ONCE}" in
|
||||||
|
y|Y|yes|YES)
|
||||||
|
echo "正在以 steam 用户执行 server.sh..."
|
||||||
|
sudo -u "${STEAM_USER}" bash "${ETS2_BIN_DIR}/server.sh"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "已跳过首次执行"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
else
|
||||||
|
echo "非交互环境,跳过首次执行"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "========================================"
|
||||||
|
echo "部署完成"
|
||||||
|
echo
|
||||||
|
echo "服务器目录:"
|
||||||
|
echo "${ETS2_DIR}"
|
||||||
|
echo
|
||||||
|
echo "配置目录:"
|
||||||
|
echo "${ETS2_DOC_DIR}/Euro Truck Simulator 2"
|
||||||
|
echo
|
||||||
|
echo "管理脚本:"
|
||||||
|
echo "${ETS2_BIN_DIR}/server.sh"
|
||||||
|
echo
|
||||||
|
echo "快捷命令:"
|
||||||
|
echo "ets2_sv"
|
||||||
|
echo
|
||||||
|
echo "如需设置 steam 用户密码:"
|
||||||
|
echo "sudo passwd steam"
|
||||||
|
echo
|
||||||
|
echo "如需切换到 steam 用户:"
|
||||||
|
echo "su - steam"
|
||||||
|
echo "========================================"
|
||||||
757
server/server.sh
757
server/server.sh
@ -1 +1,756 @@
|
|||||||
~~~~~111
|
#!/bin/sh
|
||||||
|
# 2026年5月6日 21点21分
|
||||||
|
# 项目地址:https://github.com/A-hxin/ets2_server/
|
||||||
|
|
||||||
|
# ==============================
|
||||||
|
# ETS2 Dedicated Server 管理脚本
|
||||||
|
# ==============================
|
||||||
|
|
||||||
|
# 服务器目录
|
||||||
|
SERVER_HOME="/home/steam/ets2_sv/bin/linux_x64"
|
||||||
|
|
||||||
|
# 官方启动脚本
|
||||||
|
SERVER_LAUNCH="$SERVER_HOME/server_launch.sh"
|
||||||
|
|
||||||
|
# Steam 运行库目录
|
||||||
|
STEAM_PATH="/home/steam/ets2_sv/linux64"
|
||||||
|
|
||||||
|
# SteamCMD 目录
|
||||||
|
STEAMCMD_HOME="/home/steam/steamcmd"
|
||||||
|
|
||||||
|
# ETS2 服务端安装目录
|
||||||
|
ETS2_INSTALL_DIR="/home/steam/ets2_sv"
|
||||||
|
|
||||||
|
# ETS2 Dedicated Server AppID
|
||||||
|
ETS2_APP_ID="1948160"
|
||||||
|
|
||||||
|
# 欧卡文档目录
|
||||||
|
# 实际读取目录:
|
||||||
|
# /home/steam/ets2_doc/Euro Truck Simulator 2
|
||||||
|
export XDG_DATA_HOME="/home/steam/ets2_doc"
|
||||||
|
|
||||||
|
# 设置 LD_LIBRARY_PATH
|
||||||
|
export LD_LIBRARY_PATH="$STEAM_PATH:$SERVER_HOME:${LD_LIBRARY_PATH:-}"
|
||||||
|
|
||||||
|
# 启动参数
|
||||||
|
SERVER_OPTIONS="-nosingle -server server_packages.sii -server_cfg server_config.sii"
|
||||||
|
|
||||||
|
# 实际配置目录
|
||||||
|
ETS2_DOC_HOME="$XDG_DATA_HOME/Euro Truck Simulator 2"
|
||||||
|
|
||||||
|
# 日志根目录
|
||||||
|
LOG_ROOT="$SERVER_HOME/logs"
|
||||||
|
|
||||||
|
# PID 文件
|
||||||
|
PID_FILE="$LOG_ROOT/server.pid"
|
||||||
|
|
||||||
|
# 后台启动器 PID 文件
|
||||||
|
RUNNER_PID_FILE="$LOG_ROOT/runner.pid"
|
||||||
|
|
||||||
|
# 进程组 ID 文件
|
||||||
|
PGID_FILE="$LOG_ROOT/server.pgid"
|
||||||
|
|
||||||
|
# 最新日志软链接
|
||||||
|
LATEST_LOG_LINK="$LOG_ROOT/latest.log"
|
||||||
|
|
||||||
|
# 当前日志路径记录
|
||||||
|
CURRENT_LOG_PATH_FILE="$LOG_ROOT/current_log.path"
|
||||||
|
|
||||||
|
# 日志保留天数
|
||||||
|
LOG_KEEP_DAYS=15
|
||||||
|
|
||||||
|
# 当前运行日志文件
|
||||||
|
SERVER_LOG=""
|
||||||
|
|
||||||
|
show_info() {
|
||||||
|
echo "[INFO] $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
show_ok() {
|
||||||
|
echo "[OK] $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
show_warn() {
|
||||||
|
echo "[WARN] $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
show_error() {
|
||||||
|
echo "[ERROR] $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
prepare_dirs() {
|
||||||
|
mkdir -p "$LOG_ROOT"
|
||||||
|
mkdir -p "$ETS2_DOC_HOME"
|
||||||
|
}
|
||||||
|
|
||||||
|
create_log_file() {
|
||||||
|
LOG_DAY=$(date +"%Y-%m-%d")
|
||||||
|
LOG_TIME=$(date +"%Y%m%d_%H%M%S")
|
||||||
|
|
||||||
|
LOG_DIR="$LOG_ROOT/$LOG_DAY"
|
||||||
|
mkdir -p "$LOG_DIR"
|
||||||
|
|
||||||
|
SERVER_LOG="$LOG_DIR/server_$LOG_TIME.log"
|
||||||
|
|
||||||
|
touch "$SERVER_LOG"
|
||||||
|
ln -sfn "$SERVER_LOG" "$LATEST_LOG_LINK"
|
||||||
|
echo "$SERVER_LOG" > "$CURRENT_LOG_PATH_FILE"
|
||||||
|
|
||||||
|
show_info "本次日志文件: $SERVER_LOG"
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup_old_logs() {
|
||||||
|
if [ -d "$LOG_ROOT" ]; then
|
||||||
|
find "$LOG_ROOT" -mindepth 1 -maxdepth 1 -type d -mtime +"$LOG_KEEP_DAYS" -exec rm -rf {} \; 2>/dev/null
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
check_required_files() {
|
||||||
|
echo "========== ETS2 配置文件检查 =========="
|
||||||
|
echo "当前用户: $(whoami)"
|
||||||
|
echo "SERVER_HOME: $SERVER_HOME"
|
||||||
|
echo "SERVER_LAUNCH: $SERVER_LAUNCH"
|
||||||
|
echo "STEAM_PATH: $STEAM_PATH"
|
||||||
|
echo "XDG_DATA_HOME: $XDG_DATA_HOME"
|
||||||
|
echo "ETS2_DOC_HOME: $ETS2_DOC_HOME"
|
||||||
|
echo "LD_LIBRARY_PATH: $LD_LIBRARY_PATH"
|
||||||
|
echo "SERVER_OPTIONS: $SERVER_OPTIONS"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
if [ -x "$SERVER_LAUNCH" ]; then
|
||||||
|
echo "[OK] server_launch.sh 存在并可执行"
|
||||||
|
else
|
||||||
|
echo "[ERROR] server_launch.sh 不存在或不可执行"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -f "$ETS2_DOC_HOME/server_config.sii" ]; then
|
||||||
|
echo "[OK] server_config.sii 存在"
|
||||||
|
else
|
||||||
|
echo "[WARN] 缺少 server_config.sii"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -f "$ETS2_DOC_HOME/server_packages.sii" ]; then
|
||||||
|
echo "[OK] server_packages.sii 存在"
|
||||||
|
else
|
||||||
|
echo "[ERROR] 缺少 server_packages.sii"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -f "$ETS2_DOC_HOME/server_packages.dat" ]; then
|
||||||
|
echo "[OK] server_packages.dat 存在"
|
||||||
|
else
|
||||||
|
echo "[ERROR] 缺少 server_packages.dat"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "当前配置目录文件:"
|
||||||
|
ls -lah "$ETS2_DOC_HOME" 2>/dev/null
|
||||||
|
echo "======================================="
|
||||||
|
}
|
||||||
|
|
||||||
|
get_server_pid() {
|
||||||
|
pgrep -f "eurotrucks2_server" | head -n 1
|
||||||
|
}
|
||||||
|
|
||||||
|
get_launch_pid() {
|
||||||
|
pgrep -f "server_launch.sh" | head -n 1
|
||||||
|
}
|
||||||
|
|
||||||
|
get_config_port() {
|
||||||
|
KEY="$1"
|
||||||
|
CONFIG_FILE="$ETS2_DOC_HOME/server_config.sii"
|
||||||
|
|
||||||
|
if [ ! -f "$CONFIG_FILE" ]; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
grep -E "^[[:space:]]*$KEY[[:space:]]*:" "$CONFIG_FILE" | \
|
||||||
|
head -n 1 | \
|
||||||
|
sed -E 's/.*:[[:space:]]*([0-9]+).*/\1/'
|
||||||
|
}
|
||||||
|
|
||||||
|
get_connection_port() {
|
||||||
|
PORT=$(get_config_port "connection_dedicated_port")
|
||||||
|
|
||||||
|
if [ -z "$PORT" ]; then
|
||||||
|
PORT="27015"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "$PORT"
|
||||||
|
}
|
||||||
|
|
||||||
|
get_query_port() {
|
||||||
|
PORT=$(get_config_port "query_dedicated_port")
|
||||||
|
|
||||||
|
if [ -z "$PORT" ]; then
|
||||||
|
PORT="27016"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "$PORT"
|
||||||
|
}
|
||||||
|
|
||||||
|
port_in_use() {
|
||||||
|
PORT="$1"
|
||||||
|
|
||||||
|
if [ -z "$PORT" ]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
ss -H -lntup 2>/dev/null | awk -v port=":$PORT" '
|
||||||
|
$5 ~ port"$" {
|
||||||
|
found=1
|
||||||
|
}
|
||||||
|
END {
|
||||||
|
exit !found
|
||||||
|
}
|
||||||
|
'
|
||||||
|
}
|
||||||
|
|
||||||
|
show_port_owner() {
|
||||||
|
PORT="$1"
|
||||||
|
ss -lntup 2>/dev/null | grep -E ":$PORT[[:space:]]|:$PORT$" || true
|
||||||
|
}
|
||||||
|
|
||||||
|
get_port_owner_pids() {
|
||||||
|
PORT="$1"
|
||||||
|
|
||||||
|
ss -H -lntup 2>/dev/null | awk -v port=":$PORT" '
|
||||||
|
$0 ~ port {
|
||||||
|
line=$0
|
||||||
|
while (match(line, /pid=[0-9]+/)) {
|
||||||
|
pid=substr(line, RSTART + 4, RLENGTH - 4)
|
||||||
|
print pid
|
||||||
|
line=substr(line, RSTART + RLENGTH)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
' | sort -u
|
||||||
|
}
|
||||||
|
|
||||||
|
get_ets2_pid_from_ports() {
|
||||||
|
CONN_PORT=$(get_connection_port)
|
||||||
|
QUERY_PORT=$(get_query_port)
|
||||||
|
|
||||||
|
for PORT in "$CONN_PORT" "$QUERY_PORT"; do
|
||||||
|
for P in $(get_port_owner_pids "$PORT"); do
|
||||||
|
CMD=$(ps -p "$P" -o command= 2>/dev/null)
|
||||||
|
|
||||||
|
case "$CMD" in
|
||||||
|
*eurotrucks2_server*)
|
||||||
|
echo "$P"
|
||||||
|
return 0
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
done
|
||||||
|
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
check_ports_available() {
|
||||||
|
CONN_PORT=$(get_connection_port)
|
||||||
|
QUERY_PORT=$(get_query_port)
|
||||||
|
|
||||||
|
echo "========== ETS2 端口检查 =========="
|
||||||
|
echo "connection_dedicated_port: $CONN_PORT"
|
||||||
|
echo "query_dedicated_port: $QUERY_PORT"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
HAS_ERROR=0
|
||||||
|
|
||||||
|
if port_in_use "$CONN_PORT"; then
|
||||||
|
show_error "端口 $CONN_PORT 已被占用"
|
||||||
|
show_port_owner "$CONN_PORT"
|
||||||
|
HAS_ERROR=1
|
||||||
|
else
|
||||||
|
show_ok "端口 $CONN_PORT 可用"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if port_in_use "$QUERY_PORT"; then
|
||||||
|
show_error "端口 $QUERY_PORT 已被占用"
|
||||||
|
show_port_owner "$QUERY_PORT"
|
||||||
|
HAS_ERROR=1
|
||||||
|
else
|
||||||
|
show_ok "端口 $QUERY_PORT 可用"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "=================================="
|
||||||
|
|
||||||
|
if [ "$HAS_ERROR" -ne 0 ]; then
|
||||||
|
echo ""
|
||||||
|
show_error "端口被占用,请先执行:"
|
||||||
|
echo "$0 stop"
|
||||||
|
echo ""
|
||||||
|
echo "如果 stop 后仍占用,执行:"
|
||||||
|
echo "$0 kill"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
show_ports_status() {
|
||||||
|
CONN_PORT=$(get_connection_port)
|
||||||
|
QUERY_PORT=$(get_query_port)
|
||||||
|
|
||||||
|
echo "========== ETS2 端口状态 =========="
|
||||||
|
echo "connection_dedicated_port: $CONN_PORT"
|
||||||
|
show_port_owner "$CONN_PORT"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "query_dedicated_port: $QUERY_PORT"
|
||||||
|
show_port_owner "$QUERY_PORT"
|
||||||
|
echo "=================================="
|
||||||
|
}
|
||||||
|
|
||||||
|
pgid_has_ets2() {
|
||||||
|
TARGET_PGID="$1"
|
||||||
|
|
||||||
|
if [ -z "$TARGET_PGID" ]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
ps -eo pgid=,cmd= | awk -v pgid="$TARGET_PGID" '
|
||||||
|
$1 == pgid && ($0 ~ /eurotrucks2_server/ || $0 ~ /server_launch.sh/ || $0 ~ /script .*server_launch.sh/) {
|
||||||
|
found=1
|
||||||
|
}
|
||||||
|
END {
|
||||||
|
exit !found
|
||||||
|
}
|
||||||
|
'
|
||||||
|
}
|
||||||
|
|
||||||
|
kill_ets2_port_owners() {
|
||||||
|
CONN_PORT=$(get_connection_port)
|
||||||
|
QUERY_PORT=$(get_query_port)
|
||||||
|
|
||||||
|
for PORT in "$CONN_PORT" "$QUERY_PORT"; do
|
||||||
|
for P in $(get_port_owner_pids "$PORT"); do
|
||||||
|
CMD=$(ps -p "$P" -o command= 2>/dev/null)
|
||||||
|
|
||||||
|
case "$CMD" in
|
||||||
|
*eurotrucks2_server*|*server_launch.sh*)
|
||||||
|
show_warn "端口 $PORT 仍被 ETS2 进程占用,强制清理 PID: $P"
|
||||||
|
kill -TERM "$P" 2>/dev/null || true
|
||||||
|
sleep 1
|
||||||
|
kill -KILL "$P" 2>/dev/null || true
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
show_warn "端口 $PORT 被非 ETS2 进程占用,PID: $P"
|
||||||
|
echo "$CMD"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
wait_ports_release() {
|
||||||
|
CONN_PORT=$(get_connection_port)
|
||||||
|
QUERY_PORT=$(get_query_port)
|
||||||
|
|
||||||
|
COUNT=0
|
||||||
|
|
||||||
|
while [ "$COUNT" -lt 10 ]; do
|
||||||
|
if ! port_in_use "$CONN_PORT" && ! port_in_use "$QUERY_PORT"; then
|
||||||
|
show_ok "端口 $CONN_PORT / $QUERY_PORT 已释放。"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
sleep 1
|
||||||
|
COUNT=$((COUNT + 1))
|
||||||
|
done
|
||||||
|
|
||||||
|
show_warn "端口仍未完全释放,尝试按端口兜底清理..."
|
||||||
|
kill_ets2_port_owners
|
||||||
|
|
||||||
|
sleep 2
|
||||||
|
|
||||||
|
if ! port_in_use "$CONN_PORT" && ! port_in_use "$QUERY_PORT"; then
|
||||||
|
show_ok "端口 $CONN_PORT / $QUERY_PORT 已释放。"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
show_error "端口仍被占用:"
|
||||||
|
show_port_owner "$CONN_PORT"
|
||||||
|
show_port_owner "$QUERY_PORT"
|
||||||
|
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
force_cleanup_server() {
|
||||||
|
prepare_dirs
|
||||||
|
|
||||||
|
show_warn "正在清理残留 ETS2 进程..."
|
||||||
|
|
||||||
|
RUNNER_PID=""
|
||||||
|
PGID=""
|
||||||
|
|
||||||
|
if [ -f "$RUNNER_PID_FILE" ]; then
|
||||||
|
RUNNER_PID=$(cat "$RUNNER_PID_FILE")
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -f "$PGID_FILE" ]; then
|
||||||
|
PGID=$(cat "$PGID_FILE")
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$PGID" ]; then
|
||||||
|
if pgid_has_ets2 "$PGID"; then
|
||||||
|
show_warn "正在停止 ETS2 进程组 PGID: $PGID"
|
||||||
|
kill -TERM "-$PGID" 2>/dev/null || true
|
||||||
|
else
|
||||||
|
show_warn "PGID $PGID 不存在或不属于 ETS2,跳过进程组终止"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$RUNNER_PID" ]; then
|
||||||
|
show_warn "正在停止启动器 PID: $RUNNER_PID"
|
||||||
|
kill -TERM "$RUNNER_PID" 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
pkill -TERM -f "eurotrucks2_server" 2>/dev/null || true
|
||||||
|
pkill -TERM -f "server_launch.sh" 2>/dev/null || true
|
||||||
|
pkill -TERM -f "script .*server_launch.sh" 2>/dev/null || true
|
||||||
|
|
||||||
|
sleep 3
|
||||||
|
|
||||||
|
if [ -n "$PGID" ]; then
|
||||||
|
if pgid_has_ets2 "$PGID"; then
|
||||||
|
kill -KILL "-$PGID" 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$RUNNER_PID" ]; then
|
||||||
|
kill -KILL "$RUNNER_PID" 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
pkill -KILL -f "eurotrucks2_server" 2>/dev/null || true
|
||||||
|
pkill -KILL -f "server_launch.sh" 2>/dev/null || true
|
||||||
|
pkill -KILL -f "script .*server_launch.sh" 2>/dev/null || true
|
||||||
|
|
||||||
|
kill_ets2_port_owners
|
||||||
|
|
||||||
|
rm -f "$PID_FILE"
|
||||||
|
rm -f "$RUNNER_PID_FILE"
|
||||||
|
rm -f "$PGID_FILE"
|
||||||
|
|
||||||
|
wait_ports_release || true
|
||||||
|
|
||||||
|
show_ok "残留进程清理完成。"
|
||||||
|
}
|
||||||
|
|
||||||
|
run_server_realtime() {
|
||||||
|
cd "$SERVER_HOME" || exit 1
|
||||||
|
|
||||||
|
if command -v script >/dev/null 2>&1; then
|
||||||
|
script -qefc "$SERVER_LAUNCH $SERVER_OPTIONS" /dev/null
|
||||||
|
elif command -v stdbuf >/dev/null 2>&1; then
|
||||||
|
stdbuf -oL -eL "$SERVER_LAUNCH" $SERVER_OPTIONS
|
||||||
|
else
|
||||||
|
"$SERVER_LAUNCH" $SERVER_OPTIONS
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
start)
|
||||||
|
show_info "正在启动 ETS2 服务器..."
|
||||||
|
|
||||||
|
prepare_dirs
|
||||||
|
cleanup_old_logs
|
||||||
|
|
||||||
|
SERVER_PID=$(get_server_pid)
|
||||||
|
|
||||||
|
if [ -z "$SERVER_PID" ]; then
|
||||||
|
SERVER_PID=$(get_ets2_pid_from_ports)
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$SERVER_PID" ]; then
|
||||||
|
show_warn "ETS2 服务器似乎已经在运行,PID: $SERVER_PID"
|
||||||
|
echo "$SERVER_PID" > "$PID_FILE"
|
||||||
|
|
||||||
|
if [ -f "$CURRENT_LOG_PATH_FILE" ]; then
|
||||||
|
show_info "本次日志: $(cat "$CURRENT_LOG_PATH_FILE")"
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
check_ports_available || exit 1
|
||||||
|
|
||||||
|
create_log_file
|
||||||
|
|
||||||
|
cd "$SERVER_HOME" || exit 1
|
||||||
|
|
||||||
|
setsid sh -c '
|
||||||
|
SERVER_HOME="$1"
|
||||||
|
SERVER_LAUNCH="$2"
|
||||||
|
SERVER_OPTIONS="$3"
|
||||||
|
SERVER_LOG="$4"
|
||||||
|
|
||||||
|
cd "$SERVER_HOME" || exit 1
|
||||||
|
|
||||||
|
if command -v script >/dev/null 2>&1; then
|
||||||
|
script -qefc "$SERVER_LAUNCH $SERVER_OPTIONS" /dev/null
|
||||||
|
elif command -v stdbuf >/dev/null 2>&1; then
|
||||||
|
stdbuf -oL -eL "$SERVER_LAUNCH" $SERVER_OPTIONS
|
||||||
|
else
|
||||||
|
"$SERVER_LAUNCH" $SERVER_OPTIONS
|
||||||
|
fi 2>&1 | awk '"'"'{print strftime("%Y-%m-%d %H:%M:%S"), "-", $0; fflush();}'"'"' >> "$SERVER_LOG"
|
||||||
|
' sh "$SERVER_HOME" "$SERVER_LAUNCH" "$SERVER_OPTIONS" "$SERVER_LOG" >/dev/null 2>&1 &
|
||||||
|
|
||||||
|
RUNNER_PID=$!
|
||||||
|
echo "$RUNNER_PID" > "$RUNNER_PID_FILE"
|
||||||
|
echo "$RUNNER_PID" > "$PGID_FILE"
|
||||||
|
|
||||||
|
show_info "启动器 PID: $RUNNER_PID"
|
||||||
|
show_info "进程组 PGID: $RUNNER_PID"
|
||||||
|
show_info "等待 ETS2 服务端启动,最多等待 60 秒..."
|
||||||
|
|
||||||
|
WAIT_COUNT=0
|
||||||
|
SERVER_PID=""
|
||||||
|
LAUNCH_PID=""
|
||||||
|
|
||||||
|
while [ "$WAIT_COUNT" -lt 60 ]; do
|
||||||
|
SERVER_PID=$(get_server_pid)
|
||||||
|
|
||||||
|
if [ -z "$SERVER_PID" ]; then
|
||||||
|
SERVER_PID=$(get_ets2_pid_from_ports)
|
||||||
|
fi
|
||||||
|
|
||||||
|
LAUNCH_PID=$(get_launch_pid)
|
||||||
|
|
||||||
|
if [ -n "$SERVER_PID" ]; then
|
||||||
|
echo "$SERVER_PID" > "$PID_FILE"
|
||||||
|
show_ok "ETS2 服务器已启动,PID: $SERVER_PID"
|
||||||
|
show_info "最新日志: $LATEST_LOG_LINK"
|
||||||
|
show_info "本次日志: $SERVER_LOG"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$LAUNCH_PID" ]; then
|
||||||
|
show_info "启动脚本仍在运行,PID: $LAUNCH_PID,继续等待..."
|
||||||
|
fi
|
||||||
|
|
||||||
|
if grep -qiE "Failed to init|Server was terminated|couldn't find an open port|Server packages file not found|SteamAPI_Init.*failed|\*\*\* ERROR \*\*\*" "$SERVER_LOG" 2>/dev/null; then
|
||||||
|
show_error "检测到启动错误,准备清理残留进程..."
|
||||||
|
tail -n 100 "$SERVER_LOG"
|
||||||
|
force_cleanup_server
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
WAIT_COUNT=$((WAIT_COUNT + 1))
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
|
||||||
|
SERVER_PID=$(get_server_pid)
|
||||||
|
|
||||||
|
if [ -z "$SERVER_PID" ]; then
|
||||||
|
SERVER_PID=$(get_ets2_pid_from_ports)
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$SERVER_PID" ]; then
|
||||||
|
echo "$SERVER_PID" > "$PID_FILE"
|
||||||
|
show_ok "ETS2 服务器已启动,PID: $SERVER_PID"
|
||||||
|
show_info "最新日志: $LATEST_LOG_LINK"
|
||||||
|
show_info "本次日志: $SERVER_LOG"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
show_error "等待 60 秒后仍未检测到 ETS2 主进程,准备清理残留进程..."
|
||||||
|
tail -n 120 "$SERVER_LOG"
|
||||||
|
force_cleanup_server
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
|
||||||
|
debug)
|
||||||
|
show_info "正在以前台调试模式启动 ETS2 服务器..."
|
||||||
|
show_warn "当前不会后台运行,按 Ctrl+C 可停止服务器。"
|
||||||
|
|
||||||
|
prepare_dirs
|
||||||
|
cleanup_old_logs
|
||||||
|
create_log_file
|
||||||
|
check_required_files
|
||||||
|
|
||||||
|
OLD_PID=$(get_server_pid)
|
||||||
|
|
||||||
|
if [ -z "$OLD_PID" ]; then
|
||||||
|
OLD_PID=$(get_ets2_pid_from_ports)
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$OLD_PID" ]; then
|
||||||
|
show_error "检测到已有 ETS2 服务端进程正在运行,PID: $OLD_PID"
|
||||||
|
echo ""
|
||||||
|
echo "请先执行:"
|
||||||
|
echo "$0 stop"
|
||||||
|
echo ""
|
||||||
|
echo "如果仍然无法释放端口,执行:"
|
||||||
|
echo "$0 kill"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
check_ports_available || exit 1
|
||||||
|
|
||||||
|
trap '
|
||||||
|
echo ""
|
||||||
|
echo "[WARN] 收到中断信号,正在退出 debug 模式..."
|
||||||
|
force_cleanup_server
|
||||||
|
echo "[OK] debug 残留进程已清理。"
|
||||||
|
exit 130
|
||||||
|
' INT TERM HUP
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "========== 开始前台调试 =========="
|
||||||
|
echo "执行命令:"
|
||||||
|
echo "$SERVER_LAUNCH $SERVER_OPTIONS"
|
||||||
|
echo "本次日志:"
|
||||||
|
echo "$SERVER_LOG"
|
||||||
|
echo "=================================="
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
run_server_realtime 2>&1 | \
|
||||||
|
awk '{print strftime("%Y-%m-%d %H:%M:%S"), "-", $0; fflush();}' | \
|
||||||
|
tee -a "$SERVER_LOG"
|
||||||
|
|
||||||
|
trap - INT TERM HUP
|
||||||
|
|
||||||
|
show_warn "debug 模式已退出,正在清理可能残留的 ETS2 进程..."
|
||||||
|
force_cleanup_server
|
||||||
|
;;
|
||||||
|
|
||||||
|
stop)
|
||||||
|
show_info "正在停止 ETS2 服务器..."
|
||||||
|
force_cleanup_server
|
||||||
|
;;
|
||||||
|
|
||||||
|
kill)
|
||||||
|
force_cleanup_server
|
||||||
|
;;
|
||||||
|
|
||||||
|
restart)
|
||||||
|
show_info "正在重启 ETS2 服务器..."
|
||||||
|
"$0" stop
|
||||||
|
sleep 3
|
||||||
|
"$0" start
|
||||||
|
;;
|
||||||
|
|
||||||
|
update)
|
||||||
|
show_info "正在更新 ETS2 专用服务器..."
|
||||||
|
|
||||||
|
SERVER_PID=$(get_server_pid)
|
||||||
|
|
||||||
|
if [ -n "$SERVER_PID" ]; then
|
||||||
|
show_warn "检测到服务器正在运行,先停止服务器..."
|
||||||
|
"$0" stop
|
||||||
|
sleep 3
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p "$STEAMCMD_HOME" "$ETS2_INSTALL_DIR"
|
||||||
|
|
||||||
|
cd "$STEAMCMD_HOME" || exit 1
|
||||||
|
|
||||||
|
show_info "检查 SteamCMD..."
|
||||||
|
|
||||||
|
curl -sqL "https://steamcdn-a.akamaihd.net/client/installer/steamcmd_linux.tar.gz" | tar zxvf -
|
||||||
|
|
||||||
|
chmod +x "$STEAMCMD_HOME/steamcmd.sh"
|
||||||
|
|
||||||
|
show_info "开始更新 ETS2 Dedicated Server..."
|
||||||
|
|
||||||
|
"$STEAMCMD_HOME/steamcmd.sh" \
|
||||||
|
+force_install_dir "$ETS2_INSTALL_DIR" \
|
||||||
|
+login anonymous \
|
||||||
|
+app_update "$ETS2_APP_ID" validate \
|
||||||
|
+quit
|
||||||
|
|
||||||
|
show_ok "ETS2 专用服务器更新完成。"
|
||||||
|
;;
|
||||||
|
|
||||||
|
status)
|
||||||
|
prepare_dirs
|
||||||
|
|
||||||
|
SERVER_PID=$(get_server_pid)
|
||||||
|
|
||||||
|
if [ -z "$SERVER_PID" ]; then
|
||||||
|
SERVER_PID=$(get_ets2_pid_from_ports)
|
||||||
|
fi
|
||||||
|
|
||||||
|
LAUNCH_PID=$(get_launch_pid)
|
||||||
|
|
||||||
|
if [ -n "$SERVER_PID" ]; then
|
||||||
|
show_ok "ETS2 服务器正在运行,PID: $SERVER_PID"
|
||||||
|
|
||||||
|
if [ -n "$LAUNCH_PID" ]; then
|
||||||
|
show_info "启动脚本进程 PID: $LAUNCH_PID"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -f "$CURRENT_LOG_PATH_FILE" ]; then
|
||||||
|
show_info "本次日志: $(cat "$CURRENT_LOG_PATH_FILE")"
|
||||||
|
fi
|
||||||
|
|
||||||
|
show_info "最新日志: $LATEST_LOG_LINK"
|
||||||
|
echo ""
|
||||||
|
show_ports_status
|
||||||
|
else
|
||||||
|
show_warn "ETS2 服务器未运行。"
|
||||||
|
rm -f "$PID_FILE"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
|
||||||
|
log)
|
||||||
|
prepare_dirs
|
||||||
|
|
||||||
|
if [ -L "$LATEST_LOG_LINK" ] || [ -f "$LATEST_LOG_LINK" ]; then
|
||||||
|
tail -n 100 -F "$LATEST_LOG_LINK"
|
||||||
|
else
|
||||||
|
show_warn "暂无最新日志文件。"
|
||||||
|
show_info "请先执行:$0 start 或 $0 debug"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
|
||||||
|
listlog)
|
||||||
|
prepare_dirs
|
||||||
|
|
||||||
|
echo "最近日志文件:"
|
||||||
|
find "$LOG_ROOT" -type f -name "*.log" 2>/dev/null | sort | tail -n 30
|
||||||
|
;;
|
||||||
|
|
||||||
|
cleanlog)
|
||||||
|
prepare_dirs
|
||||||
|
cleanup_old_logs
|
||||||
|
show_ok "已清理超过 $LOG_KEEP_DAYS 天的日志目录。"
|
||||||
|
;;
|
||||||
|
|
||||||
|
check)
|
||||||
|
prepare_dirs
|
||||||
|
check_required_files
|
||||||
|
echo ""
|
||||||
|
check_ports_available || true
|
||||||
|
;;
|
||||||
|
|
||||||
|
ports)
|
||||||
|
prepare_dirs
|
||||||
|
check_ports_available || true
|
||||||
|
;;
|
||||||
|
|
||||||
|
portstatus)
|
||||||
|
prepare_dirs
|
||||||
|
show_ports_status
|
||||||
|
;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
echo "ETS2 服务器管理命令"
|
||||||
|
echo "用法: ets2_sv {start|stop|restart|status|update|debug|log|listlog|cleanlog|check|ports|portstatus|kill}"
|
||||||
|
echo ""
|
||||||
|
echo " start - 后台启动 ETS2 服务器"
|
||||||
|
echo " stop - 停止 ETS2 服务器,并释放端口"
|
||||||
|
echo " restart - 重启 ETS2 服务器"
|
||||||
|
echo " status - 查看 ETS2 服务器状态"
|
||||||
|
echo " update - 更新 ETS2 专用服务器"
|
||||||
|
echo " debug - 前台调试启动,不后台运行,实时输出"
|
||||||
|
echo " log - 实时查看最新日志"
|
||||||
|
echo " listlog - 查看最近日志文件"
|
||||||
|
echo " cleanlog - 清理旧日志"
|
||||||
|
echo " check - 检查配置文件和端口"
|
||||||
|
echo " ports - 检查端口是否可用"
|
||||||
|
echo " portstatus - 查看端口占用详情"
|
||||||
|
echo " kill - 强制清理残留 ETS2 进程"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
Loading…
x
Reference in New Issue
Block a user