#!/bin/bash # 目标机(Debian 13)上一键部署:ktv 用户/目录 → 安装代码 → 写配置 → 装 systemd 单元 → 启动自检 # 以 root 运行:bash deploy-root.sh set -euo pipefail # ⚠️ su -c 继承的 PATH 不含 /usr/sbin(useradd/ss 等都在那儿) export PATH="$PATH:/usr/sbin:/sbin" SRC="${SRC:-/home/zijun/ktv-src}" # 已由 zijun 用户上传的代码目录 DST=/opt/ktv-source LIB=/var/lib/ktv-source ETC=/etc/ktv-source CFG="$ETC/server-config.json" # ⚠️ 服务运行身份可配:数据落在 FUSE/云盘挂载(如 /home//…)时必须用该目录属主 # (FUSE 挂载只认挂载参数里的 uid),否则会出现"只读数据库 / 打不开数据库"。 SVC_USER="${SVC_USER:-ktv}" echo "── 1/6 用户与目录(身份=$SVC_USER;已存在的目录不改归属,避免夺权)" if [ "$SVC_USER" = "ktv" ]; then id ktv >/dev/null 2>&1 || useradd --system --home "$LIB" --shell /usr/sbin/nologin ktv fi # install -d 会顺带 chown 已存在的目录 → 这里只在缺失时创建,绝不动现场目录的归属 [ -d "$DST" ] || install -d -o "$SVC_USER" -g "$SVC_USER" -m 0755 "$DST" [ -d "$LIB" ] || install -d -o "$SVC_USER" -g "$SVC_USER" -m 0755 "$LIB" "$LIB/media" "$LIB/media/tmp" [ -d "$LIB/media" ] || install -d -o "$SVC_USER" -g "$SVC_USER" -m 0755 "$LIB/media" "$LIB/media/tmp" [ -d "$ETC" ] || install -d -o "$SVC_USER" -g "$SVC_USER" -m 0750 "$ETC" echo "── 2/6 安装代码(从 $SRC → $DST)" [ -f "$SRC/run.py" ] || { echo "缺少 $SRC/run.py,请先上传代码"; exit 1; } find "$DST" -mindepth 1 -maxdepth 1 -exec rm -rf {} + 2>/dev/null || true cp -a "$SRC/." "$DST/" find "$DST" -name '__pycache__' -type d -prune -exec rm -rf {} + 2>/dev/null || true chown -R "$SVC_USER":"$SVC_USER" "$DST" chmod -R a+rX "$DST" echo "── 3/6 配置(已存在则不覆盖,保留界面里改过的设置)" if [ ! -f "$CFG" ]; then cat > "$CFG" <<'JSON' { "service_host": "0.0.0.0", "service_port": 6677, "admin_host": "0.0.0.0", "admin_port": 6678, "admin_token": "", "data_dir": "/var/lib/ktv-source", "media_dir": "/var/lib/ktv-source/media", "db_path": "/var/lib/ktv-source/server.db", "log_path": "/var/lib/ktv-source/server.log", "public_media_base": "http://192.168.100.232:6677/media", "public_host": "192.168.100.232:6677", "upstream_hosts": ["http://zk.ktv1.top:6677"], "upstream_resolution": "720", "upstream_mac": "800b510bf4fd", "upstream_sn": "2d7bb4a7d7f7", "upstream_request_interval_ms": 300, "muse_login_url": "https://mconn.cherryonline.cn/mls-api/v1/login", "muse_sync_url": "https://mconn.cherryonline.cn/mls-api/v1/sqlite/sync", "muse_device_id": "s00e04b021b2d", "muse_music_file_type": 214, "muse_auto_sync_hours": 24, "concurrency": 10, "download_batch": 200, "download_order": "hot", "download_order_desc": true, "verify_md5": false, "min_file_bytes": 6291456, "max_attempts": 3, "retry_backoff_sec": 20, "timeout_sec": 60, "user_agent": "MaidongKTV/1.2" } JSON chown "$SVC_USER":"$SVC_USER" "$CFG" chmod 640 "$CFG" fi echo "── 4/6 systemd 单元" # ⚠️ 已存在的单元不覆盖:现场可能改过 User/ProtectHome/ReadWritePaths(例如数据目录在 FUSE 挂载上) if [ ! -f /etc/systemd/system/ktv-source.service ]; then install -m 644 "$DST/deploy/ktv-source.service" /etc/systemd/system/ktv-source.service echo " 已安装默认单元" else echo " 单元已存在,保留现场配置(如需重置请手动删除后重跑)" fi systemctl daemon-reload systemctl enable ktv-source >/dev/null 2>&1 || true systemctl restart ktv-source sleep 2 echo "── 5/6 服务状态" systemctl is-active ktv-source || { journalctl -u ktv-source -n 30 --no-pager; exit 1; } ss -lntp 2>/dev/null | grep -E ':(6677|6678)' || echo " ⚠️ 没看到监听端口" echo "── 6/6 本机自检" curl -s -m 5 http://127.0.0.1:6677/healthz || true; echo curl -s -m 5 -X POST -d 'action=get_config&device_id=deploy-test' http://127.0.0.1:6677/api.php || true; echo curl -s -m 5 'http://127.0.0.1:6677/i.php?appid=x&mac=800b510bf4fd_2d7bb4a7d7f7&sn=2d7bb4a7d7f7&time=1&ver=2.0&vn=4.1.3.03281430&sign=x' || true; echo curl -s -m 5 http://127.0.0.1:6678/api/stats | head -c 300 || true; echo echo "── 完成。管理界面: http://192.168.100.232:6678/ 服务接口: http://192.168.100.232:6677/"