Files
zsglpt/install.sh
2025-12-15 13:57:25 +08:00

418 lines
11 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
# zsglpt 一键部署脚本
# 用法: curl -sSL https://your-domain/install.sh | bash
# 或: bash install.sh [install|uninstall|ssl|status]
set -e
# ==================== 配置 ====================
APP_NAME="zsglpt"
APP_PORT="51233"
CONTAINER_NAME="knowledge-automation-multiuser"
GIT_REPO="https://git.workyai.cn/237899745/zsglpt.git"
INSTALL_DIR="/opt/$APP_NAME"
# ==================== 颜色 ====================
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
log_info() { echo -e "${GREEN}[INFO]${NC} $1"; }
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
log_error() { echo -e "${RED}[ERROR]${NC} $1"; exit 1; }
log_step() { echo -e "${BLUE}[STEP]${NC} $1"; }
# ==================== 检测环境 ====================
detect_os() {
if [ -f /etc/os-release ]; then
. /etc/os-release
OS=$ID
else
log_error "无法检测操作系统"
fi
}
detect_bt_panel() {
if [ -d "/www/server/panel" ] && [ -f "/etc/init.d/bt" ]; then
BT_PANEL=true
BT_NGINX_VHOST="/www/server/panel/vhost/nginx"
BT_NGINX_BIN="/www/server/nginx/sbin/nginx"
log_info "检测到宝塔面板"
else
BT_PANEL=false
log_info "未检测到宝塔面板,使用系统 nginx"
fi
}
check_root() {
if [ "$EUID" -ne 0 ]; then
log_error "请使用 root 用户运行此脚本"
fi
}
# ==================== 安装依赖 ====================
install_deps() {
log_step "安装依赖..."
if command -v apt &> /dev/null; then
apt update -qq
apt install -y -qq git curl docker.io docker-compose nginx certbot python3-certbot-nginx 2>/dev/null || true
elif command -v yum &> /dev/null; then
yum install -y -q git curl docker docker-compose nginx certbot python3-certbot-nginx 2>/dev/null || true
fi
# 启动 docker
systemctl enable docker 2>/dev/null || true
systemctl start docker 2>/dev/null || true
}
# ==================== 交互式配置 ====================
get_config() {
echo ""
echo -e "${BLUE}========== $APP_NAME 部署配置 ==========${NC}"
echo ""
# 域名
read -p "请输入域名 (例: zsglpt.example.com): " DOMAIN
if [ -z "$DOMAIN" ]; then
log_error "域名不能为空"
fi
# 端口
read -p "请输入服务端口 [默认: $APP_PORT]: " INPUT_PORT
APP_PORT=${INPUT_PORT:-$APP_PORT}
# Git 认证
read -p "Git 用户名 [默认: 237899745]: " GIT_USER
GIT_USER=${GIT_USER:-237899745}
read -sp "Git 密码: " GIT_PASS
echo ""
if [ -z "$GIT_PASS" ]; then
log_error "Git 密码不能为空"
fi
# SSL
read -p "是否配置 SSL? [Y/n]: " SETUP_SSL
SETUP_SSL=${SETUP_SSL:-Y}
if [[ "$SETUP_SSL" =~ ^[Yy]$ ]]; then
read -p "SSL 证书邮箱 (用于 Let's Encrypt): " SSL_EMAIL
SSL_EMAIL=${SSL_EMAIL:-admin@$DOMAIN}
fi
# 确认
echo ""
echo -e "${YELLOW}========== 配置确认 ==========${NC}"
echo "域名: $DOMAIN"
echo "端口: $APP_PORT"
echo "安装目录: $INSTALL_DIR"
echo "SSL: $SETUP_SSL"
echo ""
read -p "确认安装? [Y/n]: " CONFIRM
if [[ ! "$CONFIRM" =~ ^[Yy]?$ ]]; then
log_error "安装已取消"
fi
}
# ==================== 克隆代码 ====================
clone_repo() {
log_step "克隆代码..."
if [ -d "$INSTALL_DIR" ]; then
log_warn "目录已存在,更新代码..."
cd "$INSTALL_DIR"
git fetch origin
git reset --hard origin/master
else
GIT_URL="https://${GIT_USER}:${GIT_PASS}@git.workyai.cn/237899745/zsglpt.git"
git clone "$GIT_URL" "$INSTALL_DIR"
cd "$INSTALL_DIR"
fi
# 保存配置
cat > "$INSTALL_DIR/.deploy_config" << EOF
DOMAIN=$DOMAIN
APP_PORT=$APP_PORT
GIT_USER=$GIT_USER
SSL_EMAIL=$SSL_EMAIL
INSTALL_TIME=$(date '+%Y-%m-%d %H:%M:%S')
EOF
}
# ==================== Docker 部署 ====================
deploy_docker() {
log_step "部署 Docker 容器..."
cd "$INSTALL_DIR"
# 修改 docker-compose 端口映射
if [ -f docker-compose.yml ]; then
sed -i "s/51232:51233/${APP_PORT}:51233/g" docker-compose.yml
fi
# 构建并启动
docker-compose down 2>/dev/null || true
docker-compose up -d --build
log_info "等待容器启动..."
sleep 8
if docker ps | grep -q "$CONTAINER_NAME"; then
log_info "容器启动成功"
else
log_error "容器启动失败,请检查日志: docker logs $CONTAINER_NAME"
fi
}
# ==================== Nginx 配置 ====================
setup_nginx() {
log_step "配置 Nginx..."
if $BT_PANEL; then
NGINX_CONF="$BT_NGINX_VHOST/${DOMAIN}.conf"
NGINX_CMD="$BT_NGINX_BIN"
else
NGINX_CONF="/etc/nginx/sites-available/${DOMAIN}.conf"
NGINX_CMD="nginx"
fi
# 生成配置
cat > "$NGINX_CONF" << EOF
# $APP_NAME - $DOMAIN
# 由 install.sh 自动生成,请勿手动修改
server {
listen 80;
server_name $DOMAIN;
location / {
proxy_pass http://127.0.0.1:$APP_PORT;
proxy_http_version 1.1;
proxy_set_header Upgrade \$http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host \$host;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto \$scheme;
proxy_read_timeout 86400;
proxy_send_timeout 86400;
}
}
EOF
# 非宝塔环境需要创建软链接
if ! $BT_PANEL; then
ln -sf "$NGINX_CONF" "/etc/nginx/sites-enabled/${DOMAIN}.conf" 2>/dev/null || true
fi
# 测试并重载
$NGINX_CMD -t && $NGINX_CMD -s reload
log_info "Nginx 配置完成"
}
# ==================== SSL 配置 ====================
setup_ssl() {
if [[ ! "$SETUP_SSL" =~ ^[Yy]$ ]]; then
return
fi
log_step "配置 SSL 证书..."
if $BT_PANEL; then
# 宝塔面板使用 acme.sh
if [ -f "/root/.acme.sh/acme.sh" ]; then
/root/.acme.sh/acme.sh --issue -d "$DOMAIN" --webroot "$INSTALL_DIR/static" --force || true
# 更新 nginx 配置
NGINX_CONF="$BT_NGINX_VHOST/${DOMAIN}.conf"
cat > "$NGINX_CONF" << EOF
# $APP_NAME - $DOMAIN (SSL)
# 由 install.sh 自动生成
server {
listen 80;
server_name $DOMAIN;
return 301 https://\$host\$request_uri;
}
server {
listen 443 ssl http2;
server_name $DOMAIN;
ssl_certificate /root/.acme.sh/${DOMAIN}_ecc/fullchain.cer;
ssl_certificate_key /root/.acme.sh/${DOMAIN}_ecc/${DOMAIN}.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
ssl_prefer_server_ciphers on;
location / {
proxy_pass http://127.0.0.1:$APP_PORT;
proxy_http_version 1.1;
proxy_set_header Upgrade \$http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host \$host;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto \$scheme;
proxy_read_timeout 86400;
}
}
EOF
$BT_NGINX_BIN -t && $BT_NGINX_BIN -s reload
else
log_warn "未找到 acme.sh请在宝塔面板手动配置 SSL"
fi
else
# 使用 certbot
certbot --nginx -d "$DOMAIN" --non-interactive --agree-tos -m "$SSL_EMAIL" || log_warn "SSL 配置失败,请手动配置"
fi
log_info "SSL 配置完成"
}
# ==================== 卸载 ====================
uninstall() {
echo -e "${RED}========== 卸载 $APP_NAME ==========${NC}"
# 读取配置
if [ -f "$INSTALL_DIR/.deploy_config" ]; then
source "$INSTALL_DIR/.deploy_config"
else
read -p "请输入域名: " DOMAIN
fi
read -p "确认卸载 $APP_NAME? 数据将被删除! [y/N]: " CONFIRM
if [[ ! "$CONFIRM" =~ ^[Yy]$ ]]; then
log_info "卸载已取消"
exit 0
fi
log_step "停止容器..."
cd "$INSTALL_DIR" 2>/dev/null && docker-compose down 2>/dev/null || true
docker rm -f "$CONTAINER_NAME" 2>/dev/null || true
log_step "删除 Nginx 配置..."
detect_bt_panel
if $BT_PANEL; then
rm -f "$BT_NGINX_VHOST/${DOMAIN}.conf"
$BT_NGINX_BIN -s reload 2>/dev/null || true
else
rm -f "/etc/nginx/sites-available/${DOMAIN}.conf"
rm -f "/etc/nginx/sites-enabled/${DOMAIN}.conf"
nginx -s reload 2>/dev/null || true
fi
# 备份数据
if [ -d "$INSTALL_DIR/data" ]; then
BACKUP_DIR="/root/${APP_NAME}_backup_$(date +%Y%m%d_%H%M%S)"
log_step "备份数据到 $BACKUP_DIR..."
mkdir -p "$BACKUP_DIR"
cp -r "$INSTALL_DIR/data" "$BACKUP_DIR/"
fi
log_step "删除安装目录..."
rm -rf "$INSTALL_DIR"
log_info "卸载完成!"
[ -d "$BACKUP_DIR" ] && log_info "数据已备份到: $BACKUP_DIR"
}
# ==================== 状态检查 ====================
status() {
echo -e "${BLUE}========== $APP_NAME 状态 ==========${NC}"
if [ -f "$INSTALL_DIR/.deploy_config" ]; then
source "$INSTALL_DIR/.deploy_config"
echo "域名: $DOMAIN"
echo "端口: $APP_PORT"
echo "安装时间: $INSTALL_TIME"
fi
echo ""
echo "容器状态:"
docker ps -a | grep "$CONTAINER_NAME" || echo "容器未运行"
echo ""
echo "最近日志:"
docker logs --tail 10 "$CONTAINER_NAME" 2>/dev/null || echo "无日志"
}
# ==================== 更新 ====================
update() {
log_step "更新 $APP_NAME..."
if [ ! -d "$INSTALL_DIR" ]; then
log_error "未找到安装目录,请先安装"
fi
cd "$INSTALL_DIR"
# 备份数据库
if [ -f "data/app_data.db" ]; then
cp "data/app_data.db" "data/app_data.db.$(date +%Y%m%d_%H%M%S).bak"
fi
# 拉取代码
git fetch origin
git reset --hard origin/master
# 重建容器
docker-compose down
docker-compose up -d --build
log_info "更新完成!"
}
# ==================== 主函数 ====================
main() {
check_root
detect_os
detect_bt_panel
case "${1:-install}" in
install)
install_deps
get_config
clone_repo
deploy_docker
setup_nginx
setup_ssl
echo ""
echo -e "${GREEN}========== 安装完成 ==========${NC}"
echo "访问地址: http://$DOMAIN"
[[ "$SETUP_SSL" =~ ^[Yy]$ ]] && echo "HTTPS: https://$DOMAIN"
echo ""
;;
uninstall)
uninstall
;;
update)
update
;;
status)
status
;;
ssl)
if [ -f "$INSTALL_DIR/.deploy_config" ]; then
source "$INSTALL_DIR/.deploy_config"
fi
SETUP_SSL=Y
setup_ssl
;;
*)
echo "用法: $0 [install|uninstall|update|status|ssl]"
echo ""
echo " install - 安装部署 (默认)"
echo " uninstall - 卸载并备份数据"
echo " update - 更新到最新版本"
echo " status - 查看运行状态"
echo " ssl - 配置/更新 SSL 证书"
;;
esac
}
main "$@"