diff --git a/README.md b/README.md index e58cd4b..f63aa5e 100644 --- a/README.md +++ b/README.md @@ -136,14 +136,35 @@ ports: -### 方式四:Linux 一键安装 +### 方式四:Linux 安装脚本 + +Linux 下有两个脚本,按需二选一: + +| | `scripts/install.sh`(一键安装 + 系统服务) | `scripts/setup.sh`(只安装构建) | +|---|---|---| +| 适合 | 想开箱即用、开机自启的服务器 | 想自己决定怎么常驻(screen / tmux / pm2 / 自写服务)的用户,或 macOS | +| Node.js | 没有或版本过低时**自动安装 Node 22 LTS**(apt / yum / pacman) | **不会安装**,需先自行装好 Node 22.12+ | +| 系统依赖 | 自动安装构建工具(和 FFmpeg,作为内置 FFmpeg 的后备) | 不安装,只提示 | +| 安装位置 | 构建后复制到 `/opt/tsmusicbot`(重装时保留 `data/`) | 就在当前项目目录 | +| 系统服务 | 自动配置 systemd 服务 `tsmusicbot` 并开机自启 | **不配置服务**,完成后自己 `npm start` | +| 需要 root | 是(`sudo`) | 否 | + +两者共用同一套安装逻辑:`install.sh` 会调用 `setup.sh` 完成依赖安装、国内网络镜像切换、原生模块校验和构建,然后再复制文件、配置服务。 + +**一键安装 + systemd 服务:** ```bash chmod +x scripts/install.sh sudo ./scripts/install.sh +# 之后:systemctl status|restart|stop tsmusicbot,日志:journalctl -u tsmusicbot -f ``` -自动安装 Node.js 和依赖,配置 systemd 服务,支持开机自启。 +**只安装构建(不装 Node、不配服务):** + +```bash +bash scripts/setup.sh +npm start +``` ## 更新升级 @@ -495,6 +516,7 @@ teamspeak-music-bot/ ├── scripts/ # 部署脚本 │ ├── setup.bat # Windows 首次安装 │ ├── start.bat # Windows 启动脚本 +│ ├── setup.sh # Linux/macOS 首次安装(只安装构建) │ ├── install.sh # Linux 一键安装 + systemd 服务 │ └── docker/ # Docker 部署文件 │ ├── Dockerfile diff --git a/scripts/install.sh b/scripts/install.sh index 4715d15..9a944cb 100644 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -1,6 +1,16 @@ #!/usr/bin/env bash set -euo pipefail +# +# TSMusicBot Installer (Linux, systemd) +# - Installs system packages and Node.js 22 LTS +# - Runs scripts/setup.sh to install dependencies, verify native binaries and build +# - Copies the build to /opt/tsmusicbot and registers a systemd service (auto-start on boot) +# +# Only want to build and run it yourself (no Node install, no service)? +# Use scripts/setup.sh instead — see README「Linux 安装脚本」. +# + echo "╔══════════════════════════════════════╗" echo "║ TSMusicBot Installer ║" echo "╚══════════════════════════════════════╝" @@ -11,6 +21,9 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" INSTALL_DIR="/opt/tsmusicbot" SERVICE_NAME="tsmusicbot" +# Node LTS line to install when a supported Node is missing. Keep in sync with +# package.json "engines" and the floor check in setup.sh (#152). +NODE_LTS_MAJOR=22 # Verify we're in a valid project directory if [ ! -f "$PROJECT_DIR/package.json" ]; then @@ -28,42 +41,66 @@ else exit 1 fi -echo "[1/6] Installing system dependencies..." +# Supported: 22.12+ or 24+ (odd majors are excluded by better-sqlite3 and vitest). +node_supported() { + command -v node &> /dev/null && + node -e 'const v=process.versions.node.split(".").map(Number); process.exit((v[0]===22&&v[1]>=12)||v[0]>=24?0:1)' +} + +echo "[1/5] Installing system dependencies..." case $OS in ubuntu|debian) sudo apt-get update -qq - sudo apt-get install -y -qq curl build-essential python3 + sudo apt-get install -y -qq curl ca-certificates build-essential python3 ffmpeg ;; - centos|rhel|fedora) + centos|rhel|fedora|rocky|almalinux) sudo yum install -y curl gcc gcc-c++ make python3 ;; arch|manjaro) - sudo pacman -S --noconfirm curl base-devel python + sudo pacman -S --noconfirm --needed curl base-devel python ffmpeg ;; *) - echo "Unsupported OS: $OS. Please install Node.js 20, build tools, and FFmpeg manually." + echo "Unsupported OS: $OS. Please install Node.js ${NODE_LTS_MAJOR}.12+ and build tools manually." ;; esac -echo "[2/6] Installing Node.js 20 LTS..." -if ! command -v node &> /dev/null || [[ $(node -v | cut -d. -f1 | tr -d 'v') -lt 20 ]]; then - curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash - - sudo apt-get install -y -qq nodejs 2>/dev/null || sudo yum install -y nodejs 2>/dev/null -fi -echo "Node.js $(node -v) installed" - -echo "[3/6] Installing dependencies..." -cd "$PROJECT_DIR" -npm install -if [ -d "$PROJECT_DIR/web/package.json" ] || [ -f "$PROJECT_DIR/web/package.json" ]; then - (cd "$PROJECT_DIR/web" && npm install) +echo "[2/5] Installing Node.js ${NODE_LTS_MAJOR} LTS..." +if node_supported; then + echo "Node.js $(node -v) already installed" +else + case $OS in + ubuntu|debian) + curl -fsSL "https://deb.nodesource.com/setup_${NODE_LTS_MAJOR}.x" | sudo -E bash - + sudo apt-get install -y -qq nodejs + ;; + centos|rhel|fedora|rocky|almalinux) + curl -fsSL "https://rpm.nodesource.com/setup_${NODE_LTS_MAJOR}.x" | sudo bash - + sudo yum install -y nodejs + ;; + arch|manjaro) + sudo pacman -S --noconfirm --needed nodejs npm + ;; + esac + if ! node_supported; then + echo "Error: Node.js 22.12+ (or 24+) is required, found: $(node -v 2>/dev/null || echo none)." + echo "Install it from https://nodejs.org/ (or https://nodejs.cn/) and re-run this script." + exit 1 + fi + echo "Node.js $(node -v) installed" fi -echo "[4/6] Building project..." -npm run build +echo "[3/5] Installing dependencies and building (scripts/setup.sh)..." +bash "$SCRIPT_DIR/setup.sh" -echo "[5/6] Copying to $INSTALL_DIR..." +echo "[4/5] Copying to $INSTALL_DIR..." +# Stop a running copy before replacing its files (re-install / upgrade). +if systemctl is-active --quiet "$SERVICE_NAME" 2>/dev/null; then + sudo systemctl stop "$SERVICE_NAME" +fi sudo mkdir -p "$INSTALL_DIR" +# Replace build output wholesale so files removed upstream don't linger. +# data/ (config, database, cookies) is never touched. +sudo rm -rf "$INSTALL_DIR/dist" "$INSTALL_DIR/node_modules" "$INSTALL_DIR/web/dist" sudo cp -r "$PROJECT_DIR/dist" "$INSTALL_DIR/" sudo cp -r "$PROJECT_DIR/node_modules" "$INSTALL_DIR/" sudo cp "$PROJECT_DIR/package.json" "$INSTALL_DIR/" @@ -72,13 +109,18 @@ if [ -d "$PROJECT_DIR/web/dist" ]; then sudo mkdir -p "$INSTALL_DIR/web" sudo cp -r "$PROJECT_DIR/web/dist" "$INSTALL_DIR/web/" fi +# yt-dlp is looked up in bin/ next to dist/ before falling back to PATH +if [ -d "$PROJECT_DIR/bin" ]; then + sudo cp -r "$PROJECT_DIR/bin" "$INSTALL_DIR/" +fi # Copy scripts for future use sudo mkdir -p "$INSTALL_DIR/scripts" sudo cp -r "$PROJECT_DIR/scripts/"* "$INSTALL_DIR/scripts/" 2>/dev/null || true # Create data directory sudo mkdir -p "$INSTALL_DIR/data" -echo "[6/6] Creating systemd service..." +echo "[5/5] Creating systemd service..." +NODE_BIN="$(command -v node)" sudo tee /etc/systemd/system/${SERVICE_NAME}.service > /dev/null </dev/null; then - echo "[ERROR] Node.js not found. Please install Node.js 20+ from https://nodejs.org" + echo "[ERROR] Node.js not found. Please install Node.js 22.12+ LTS from https://nodejs.org" echo " or https://nodejs.cn/ (China mirror)." exit 1 fi