418 lines
11 KiB
Bash
Executable File
418 lines
11 KiB
Bash
Executable File
#!/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 "$@"
|