#!/usr/bin/env bash # ============================================================================= # SOCKS Manager - 一键部署脚本 # ============================================================================= # 功能: # 1. 安装系统依赖 (python3, pip, gcc, libffi, etc.) # 2. 创建 Python 虚拟环境并安装 pip 依赖 # 3. 生成 .env 配置(随机 SECRET_KEY、管理员密码) # 4. 初始化数据库 & 后台线程 # 5. 生成 gunicorn + systemd 服务文件并启动 # 6. 配置防火墙(firewalld / ufw 自动识别) # # 用法: # bash deploy.sh # 全自动部署 (默认 /opt/socks-manager) # INSTALL_DIR=/opt/sm bash deploy.sh # bash deploy.sh --no-start # 不启动服务 # ADMIN_PASS=mypassword bash deploy.sh # ============================================================================= set -euo pipefail # ---- 配置 ------------------------------------------------------------------- INSTALL_DIR="${INSTALL_DIR:-/opt/socks-manager}" SERVICE_NAME="${SERVICE_NAME:-socks-manager}" SM_HOST="${SM_HOST:-0.0.0.0}" SM_PORT="${SM_PORT:-5000}" SM_WORKERS="${SM_WORKERS:-1}" ADMIN_USER="${ADMIN_USER:-admin}" ADMIN_PASS="${ADMIN_PASS:-admin123}" START_SERVICE=true SKIP_EXISTING=false for arg in "$@"; do case "$arg" in --no-start) START_SERVICE=false ;; --skip-existing) SKIP_EXISTING=true ;; -h|--help) sed -n '2,25p' "$0" exit 0 ;; *) echo "未知参数: $arg" >&2; exit 1 ;; esac done # ---- 工具函数 --------------------------------------------------------------- RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; NC='\033[0m' info() { echo -e "${GREEN}[INFO]${NC} $*"; } warn() { echo -e "${YELLOW}[WARN]${NC} $*"; } error() { echo -e "${RED}[ERROR]${NC} $*" >&2; } must_run_as_root() { if [[ $EUID -ne 0 ]]; then error "此脚本必须以 root 运行 (sudo $0)" exit 1 fi } detect_os() { if [[ -f /etc/os-release ]]; then . /etc/os-release OS_ID="$ID" OS_VER="$VERSION_ID" elif command -v apt-get &>/dev/null; then OS_ID="debian" elif command -v yum &>/dev/null; then OS_ID="centos" else error "无法识别操作系统" exit 1 fi info "操作系统: $OS_ID $OS_VER" } pkg_install() { info "安装系统包: $*" case "$OS_ID" in debian|ubuntu) export DEBIAN_FRONTEND=noninteractive apt-get update -qq apt-get install -y -qq "$@" ;; centos|rhel|rocky|almalinux|ol) yum install -y -q "$@" ;; *) error "不支持的包管理器: $OS_ID" exit 1 ;; esac } # ---- 1. 前置检查 ------------------------------------------------------------ must_run_as_root detect_os info "安装目录: $INSTALL_DIR" info "服务名: $SERVICE_NAME" info "监听: $SM_HOST:$SM_PORT" info "管理员: $ADMIN_USER" # ---- 2. 安装系统依赖 -------------------------------------------------------- SYS_PACKAGES=( python3 python3-pip python3-venv python3-dev gcc libffi-dev libssl-dev curl ) pkg_install "${SYS_PACKAGES[@]}" PYTHON_BIN="$(command -v python3)" PIP_BIN="$(command -v pip3 || command -v pip)" info "Python: $PYTHON_BIN" info "Pip: $PIP_BIN" # ---- 3. 部署项目文件 -------------------------------------------------------- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" if [[ "$SCRIPT_DIR" != "$INSTALL_DIR" ]]; then if [[ -d "$INSTALL_DIR" ]] && $SKIP_EXISTING; then warn "安装目录已存在且 --skip-existing,跳过文件复制" else info "复制项目文件到 $INSTALL_DIR" mkdir -p "$INSTALL_DIR" rsync -a --delete \ --exclude='.git/' \ --exclude='__pycache__/' \ --exclude='*.pyc' \ --exclude='*.db' \ --exclude='backups/' \ --exclude='.env' \ --exclude='gunicorn.pid' \ "$SCRIPT_DIR/" "$INSTALL_DIR/" fi fi cd "$INSTALL_DIR" # 确保运行时目录 mkdir -p backups chmod 700 backups # ---- 4. 虚拟环境 + pip 依赖 ------------------------------------------------ VENV_DIR="$INSTALL_DIR/.venv" if [[ -d "$VENV_DIR" ]] && $SKIP_EXISTING; then warn "虚拟环境已存在且 --skip-existing,跳过依赖安装" else info "创建 Python 虚拟环境: $VENV_DIR" $PYTHON_BIN -m venv "$VENV_DIR" info "升级 pip + 安装 Python 依赖" "$VENV_DIR/bin/pip" install --upgrade pip setuptools wheel "$VENV_DIR/bin/pip" install -r requirements.txt fi PYTHON="$VENV_DIR/bin/python" GUNICORN="$VENV_DIR/bin/gunicorn" # ---- 5. 生成 .env 配置 ------------------------------------------------------ ENV_FILE="$INSTALL_DIR/.env" if [[ ! -f "$ENV_FILE" ]] || ! $SKIP_EXISTING; then info "生成 .env 配置文件" SECRET_KEY="$($PYTHON -c "import secrets; print(secrets.token_urlsafe(48))")" cat > "$ENV_FILE" < "$SERVICE_FILE" </dev/null && ufw status | grep -q "Status: active" 2>/dev/null; then if ! ufw status | grep -q "${port}/tcp"; then ufw allow "${port}/tcp" comment "socks-manager web" >/dev/null info "ufw 已放行 ${port}/tcp (Web 面板)" fi elif command -v firewall-cmd &>/dev/null && firewall-cmd --state &>/dev/null; then if ! firewall-cmd --list-ports | grep -q "${port}/tcp"; then firewall-cmd --permanent --add-port="${port}/tcp" >/dev/null firewall-cmd --reload >/dev/null info "firewalld 已放行 ${port}/tcp (Web 面板)" fi fi } _configure_firewall "$SM_PORT" # ---- 9. 启动服务 ----------------------------------------------------------- if $START_SERVICE; then info "启动 $SERVICE_NAME 服务" systemctl restart "$SERVICE_NAME" sleep 3 if systemctl is-active --quiet "$SERVICE_NAME"; then info "$SERVICE_NAME 服务运行正常 ✓" else error "$SERVICE_NAME 服务启动失败!" echo "---------- journalctl 最后 40 行 ----------" journalctl -u "$SERVICE_NAME" --no-pager -n 40 exit 1 fi # 健康检查 if curl -sf -o /dev/null "http://127.0.0.1:${SM_PORT}/login"; then info "HTTP 健康检查通过 ✓ (http://127.0.0.1:${SM_PORT}/login)" else warn "HTTP 健康检查失败,请检查防火墙或端口配置" fi fi # ---- 10. 输出汇总 ----------------------------------------------------------- echo "" echo "================================================================" echo " SOCKS Manager 部署完成!" echo "================================================================" echo " Web UI: http://<服务器IP>:${SM_PORT}" echo " 账号: ${ADMIN_USER} / ${ADMIN_PASS}" echo " 安装目录: ${INSTALL_DIR}" echo " 服务名: ${SERVICE_NAME}" echo " 配置文件: ${ENV_FILE}" echo "" echo " 常用命令:" echo " systemctl status $SERVICE_NAME # 查看状态" echo " systemctl restart $SERVICE_NAME # 重启服务" echo " journalctl -u $SERVICE_NAME -f # 实时日志" echo "" echo " 提示:" echo " - SOCKS5 代理实例在 Web 面板中创建和管理" echo " - 代理端口需要手动在防火墙放行(面板会提示)" echo " - 登录后请立即修改默认管理员密码" echo "================================================================"