519 lines
14 KiB
Bash
Executable File
519 lines
14 KiB
Bash
Executable File
#!/bin/bash
|
||
|
||
# jsite前端自动化部署脚本
|
||
# 基于next.js + traefik开发
|
||
#
|
||
# 后端调用示例:
|
||
# 1. 基本部署: ./install_jsite.sh
|
||
# 2. 指定项目: ./install_jsite.sh -p myproject -r http://git.example.com/myproject
|
||
# 3. 跳过Docker: ./install_jsite.sh --skip-docker
|
||
# 4. 跳过Traefik: ./install_jsite.sh --skip-traefik
|
||
# 5. 强制更新: ./install_jsite.sh --force-update
|
||
# 6. 完整参数: ./install_jsite.sh -p myproject -r http://git.example.com/myproject -n 18 --skip-docker --force-update
|
||
#
|
||
# 返回码:
|
||
# 0 - 成功
|
||
# 1 - 参数错误
|
||
# 2 - 权限错误
|
||
# 3 - 其他错误
|
||
|
||
set -e # 遇到错误时退出
|
||
|
||
# 颜色定义
|
||
RED='\033[0;31m'
|
||
GREEN='\033[0;32m'
|
||
YELLOW='\033[1;33m'
|
||
BLUE='\033[0;34m'
|
||
NC='\033[0m' # No Color
|
||
|
||
# 默认参数
|
||
PROJECT_NAME="jingrow"
|
||
GIT_REPO="http://git.jingrow.com:3000/jsite/jingrow"
|
||
NODE_VERSION="22"
|
||
SKIP_DOCKER=false
|
||
SKIP_TRAEFIK=false
|
||
SKIP_DEPENDENCIES=false
|
||
FORCE_UPDATE=false
|
||
|
||
# .env文件参数
|
||
SITE_URL="http://192.168.2.200:3001"
|
||
REVALIDATE_TOKEN="535bc122f3e364c"
|
||
SITE_NAME="jingrow"
|
||
SERVER_URL="https://admin.jingrow.com"
|
||
API_KEY="535bc122f3e364c"
|
||
API_SECRET="8629a3b12fc1cc2"
|
||
|
||
# 显示帮助信息
|
||
show_help() {
|
||
echo "用法: $0 [选项]"
|
||
echo ""
|
||
echo "选项:"
|
||
echo " -p, --project-name NAME 项目名称 (默认: jingrow)"
|
||
echo " -r, --repo URL Git仓库地址"
|
||
echo " -n, --node-version VERSION Node.js版本 (默认: 22)"
|
||
echo " --skip-docker 跳过Docker安装"
|
||
echo " --skip-traefik 跳过Traefik安装和启动"
|
||
echo " --skip-dependencies 跳过项目依赖安装"
|
||
echo " --force-update 强制更新项目(如果已存在)"
|
||
echo ""
|
||
echo ".env文件配置:"
|
||
echo " --site-url URL 网站URL (默认: http://192.168.2.200:3001)"
|
||
echo " --revalidate-token TOKEN 重新验证令牌 (默认: 535bc122f3e364c)"
|
||
echo " --site-name NAME 站点名称 (默认: jingrow)"
|
||
echo " --server-url URL 服务器URL (默认: https://admin.jingrow.com)"
|
||
echo " --api-key KEY API密钥 (默认: 535bc122f3e364c)"
|
||
echo " --api-secret SECRET API密钥 (默认: 8629a3b12fc1cc2)"
|
||
echo ""
|
||
echo " -h, --help 显示此帮助信息"
|
||
echo ""
|
||
echo "示例:"
|
||
echo " $0 -p myproject -r http://git.example.com/myproject"
|
||
echo " $0 --skip-docker --skip-traefik"
|
||
echo " $0 --force-update"
|
||
echo " $0 --site-url http://example.com --site-name myproject"
|
||
}
|
||
|
||
# 解析命令行参数
|
||
parse_arguments() {
|
||
while [[ $# -gt 0 ]]; do
|
||
case $1 in
|
||
-p|--project-name)
|
||
PROJECT_NAME="$2"
|
||
shift 2
|
||
;;
|
||
-r|--repo)
|
||
GIT_REPO="$2"
|
||
shift 2
|
||
;;
|
||
-n|--node-version)
|
||
NODE_VERSION="$2"
|
||
shift 2
|
||
;;
|
||
--skip-docker)
|
||
SKIP_DOCKER=true
|
||
shift
|
||
;;
|
||
--skip-traefik)
|
||
SKIP_TRAEFIK=true
|
||
shift
|
||
;;
|
||
--skip-dependencies)
|
||
SKIP_DEPENDENCIES=true
|
||
shift
|
||
;;
|
||
--force-update)
|
||
FORCE_UPDATE=true
|
||
shift
|
||
;;
|
||
--site-url)
|
||
SITE_URL="$2"
|
||
shift 2
|
||
;;
|
||
--revalidate-token)
|
||
REVALIDATE_TOKEN="$2"
|
||
shift 2
|
||
;;
|
||
--site-name)
|
||
SITE_NAME="$2"
|
||
shift 2
|
||
;;
|
||
--server-url)
|
||
SERVER_URL="$2"
|
||
shift 2
|
||
;;
|
||
--api-key)
|
||
API_KEY="$2"
|
||
shift 2
|
||
;;
|
||
--api-secret)
|
||
API_SECRET="$2"
|
||
shift 2
|
||
;;
|
||
-h|--help)
|
||
show_help
|
||
exit 0
|
||
;;
|
||
*)
|
||
echo -e "${RED}[ERROR]${NC} 未知参数: $1"
|
||
show_help
|
||
exit 1
|
||
;;
|
||
esac
|
||
done
|
||
}
|
||
|
||
# 日志函数
|
||
log_info() {
|
||
echo -e "${BLUE}[INFO]${NC} $1"
|
||
}
|
||
|
||
log_success() {
|
||
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
||
}
|
||
|
||
log_warning() {
|
||
echo -e "${YELLOW}[WARNING]${NC} $1"
|
||
}
|
||
|
||
log_error() {
|
||
echo -e "${RED}[ERROR]${NC} $1"
|
||
}
|
||
|
||
# 检查是否为root用户
|
||
check_root() {
|
||
if [[ $EUID -eq 0 ]]; then
|
||
log_info "以root用户身份运行脚本"
|
||
else
|
||
log_error "请以root用户身份运行此脚本"
|
||
exit 1
|
||
fi
|
||
}
|
||
|
||
# 1. 创建jingrow用户
|
||
create_jingrow_user() {
|
||
log_info "开始创建jingrow用户..."
|
||
|
||
if id "jingrow" &>/dev/null; then
|
||
log_warning "用户jingrow已存在"
|
||
else
|
||
useradd -m -s /bin/bash jingrow
|
||
log_success "用户jingrow创建成功"
|
||
fi
|
||
|
||
# 确保home目录存在
|
||
if [ ! -d "/home/jingrow" ]; then
|
||
mkdir -p /home/jingrow
|
||
chown jingrow:jingrow /home/jingrow
|
||
log_success "创建/home/jingrow目录"
|
||
fi
|
||
}
|
||
|
||
# 2. 安装nvm和node.js
|
||
install_nodejs() {
|
||
log_info "开始安装nvm和node.js..."
|
||
|
||
# 切换到jingrow用户目录
|
||
cd /home/jingrow
|
||
|
||
# 下载并安装nvm
|
||
if [ ! -d "/home/jingrow/.nvm" ]; then
|
||
log_info "下载并安装nvm..."
|
||
su - jingrow -c "curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash"
|
||
log_success "nvm安装完成"
|
||
else
|
||
log_warning "nvm已存在"
|
||
fi
|
||
|
||
# 加载nvm并安装node.js
|
||
log_info "安装Node.js v$NODE_VERSION..."
|
||
su - jingrow -c "
|
||
export NVM_DIR=\"\$HOME/.nvm\"
|
||
[ -s \"\$NVM_DIR/nvm.sh\" ] && \. \"\$NVM_DIR/nvm.sh\"
|
||
nvm install $NODE_VERSION
|
||
nvm use $NODE_VERSION
|
||
nvm alias default $NODE_VERSION
|
||
"
|
||
|
||
# 验证安装
|
||
NODE_VERSION_OUTPUT=$(su - jingrow -c 'export NVM_DIR="$HOME/.nvm" && [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" && node -v')
|
||
NPM_VERSION=$(su - jingrow -c 'export NVM_DIR="$HOME/.nvm" && [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" && npm -v')
|
||
|
||
log_success "Node.js版本: $NODE_VERSION_OUTPUT"
|
||
log_success "npm版本: $NPM_VERSION"
|
||
}
|
||
|
||
# 3. 克隆jsite项目
|
||
clone_jsite_project() {
|
||
log_info "开始克隆jsite项目: $PROJECT_NAME..."
|
||
|
||
cd /home/jingrow
|
||
|
||
# 创建jsite目录(如果不存在)
|
||
if [ ! -d "/home/jingrow/jsite" ]; then
|
||
mkdir -p /home/jingrow/jsite
|
||
chown jingrow:jingrow /home/jingrow/jsite
|
||
log_success "创建jsite目录"
|
||
fi
|
||
|
||
# 检查项目子目录是否已存在
|
||
if [ -d "/home/jingrow/jsite/$PROJECT_NAME" ]; then
|
||
if [ "$FORCE_UPDATE" = true ]; then
|
||
log_warning "项目目录已存在,强制更新..."
|
||
rm -rf "/home/jingrow/jsite/$PROJECT_NAME"
|
||
cd /home/jingrow/jsite
|
||
su - jingrow -c "cd /home/jingrow/jsite && git clone $GIT_REPO $PROJECT_NAME"
|
||
log_success "jsite/$PROJECT_NAME项目更新完成"
|
||
else
|
||
log_warning "jsite/$PROJECT_NAME目录已存在,跳过克隆"
|
||
fi
|
||
else
|
||
cd /home/jingrow/jsite
|
||
su - jingrow -c "cd /home/jingrow/jsite && git clone $GIT_REPO $PROJECT_NAME"
|
||
log_success "jsite/$PROJECT_NAME项目克隆完成"
|
||
fi
|
||
}
|
||
|
||
# 4. 创建.env文件
|
||
create_env_file() {
|
||
log_info "创建.env文件..."
|
||
|
||
cd /home/jingrow/jsite/$PROJECT_NAME
|
||
|
||
# 检查.env文件是否已存在
|
||
if [ -f "/home/jingrow/jsite/$PROJECT_NAME/.env" ]; then
|
||
if [ "$FORCE_UPDATE" = true ]; then
|
||
log_warning ".env文件已存在,强制更新..."
|
||
else
|
||
log_warning ".env文件已存在,跳过创建"
|
||
return
|
||
fi
|
||
fi
|
||
|
||
# 创建.env文件
|
||
cat > "/home/jingrow/jsite/$PROJECT_NAME/.env" << EOF
|
||
PUBLIC_SITE_URL=$SITE_URL
|
||
|
||
REVALIDATE_TOKEN=$REVALIDATE_TOKEN
|
||
|
||
JINGROW_SITE_NAME=$SITE_NAME
|
||
|
||
JINGROW_SERVER_URL=$SERVER_URL
|
||
JINGROW_API_KEY=$API_KEY
|
||
JINGROW_API_SECRET=$API_SECRET
|
||
EOF
|
||
|
||
# 设置文件权限
|
||
chown jingrow:jingrow "/home/jingrow/jsite/$PROJECT_NAME/.env"
|
||
chmod 600 "/home/jingrow/jsite/$PROJECT_NAME/.env"
|
||
|
||
log_success ".env文件创建完成"
|
||
}
|
||
|
||
# 5. 安装traefik
|
||
install_traefik() {
|
||
log_info "开始安装traefik..."
|
||
|
||
cd /home/jingrow
|
||
|
||
# 创建traefik目录结构
|
||
if [ ! -d "/home/jingrow/traefik" ]; then
|
||
mkdir -p /home/jingrow/traefik/conf.d
|
||
log_success "创建traefik目录结构"
|
||
fi
|
||
|
||
# 创建acme.json文件
|
||
if [ ! -f "/home/jingrow/traefik/acme.json" ]; then
|
||
touch /home/jingrow/traefik/acme.json
|
||
chmod 600 /home/jingrow/traefik/acme.json
|
||
log_success "创建acme.json文件"
|
||
fi
|
||
|
||
# 创建traefik.yml配置文件
|
||
cat > /home/jingrow/traefik/traefik.yml << 'EOF'
|
||
entryPoints:
|
||
web:
|
||
address: ":80"
|
||
websecure:
|
||
address: ":443"
|
||
|
||
api:
|
||
dashboard: true
|
||
insecure: true # 生产环境建议关闭
|
||
|
||
providers:
|
||
docker:
|
||
exposedByDefault: false
|
||
file:
|
||
directory: /etc/traefik/conf.d
|
||
watch: true
|
||
|
||
certificatesResolvers:
|
||
myresolver:
|
||
acme:
|
||
email: support@jingrow.com
|
||
storage: acme.json
|
||
httpChallenge:
|
||
entryPoint: web
|
||
EOF
|
||
log_success "创建traefik.yml配置文件"
|
||
|
||
# 创建docker-compose.yml文件
|
||
cat > /home/jingrow/traefik/docker-compose.yml << 'EOF'
|
||
services:
|
||
traefik:
|
||
# The official v3 Traefik docker image
|
||
image: traefik:v3.4
|
||
container_name: traefik
|
||
restart: always
|
||
# Enables the web UI and tells Traefik to listen to docker
|
||
command: --api.insecure=true --providers.docker
|
||
ports:
|
||
# The HTTP port
|
||
- "80:80"
|
||
- "443:443"
|
||
# The Web UI (enabled by --api.insecure=true)
|
||
- "8080:8080"
|
||
volumes:
|
||
# So that Traefik can listen to the Docker events
|
||
- /var/run/docker.sock:/var/run/docker.sock
|
||
- ./traefik.yml:/etc/traefik/traefik.yml:ro
|
||
- ./conf.d:/etc/traefik/conf.d:ro
|
||
- ./acme.json:/etc/traefik/acme.json
|
||
EOF
|
||
log_success "创建docker-compose.yml文件"
|
||
|
||
# 设置目录权限
|
||
chown -R jingrow:jingrow /home/jingrow/traefik
|
||
log_success "设置traefik目录权限"
|
||
}
|
||
|
||
# 6. 安装Docker(如果未安装)
|
||
install_docker() {
|
||
log_info "检查Docker安装状态..."
|
||
|
||
if command -v docker &> /dev/null; then
|
||
log_warning "Docker已安装"
|
||
else
|
||
log_info "开始安装Docker..."
|
||
|
||
# 更新包索引
|
||
apt-get update
|
||
|
||
# 安装必要的包
|
||
apt-get install -y apt-transport-https ca-certificates curl gnupg lsb-release
|
||
|
||
# 添加Docker官方GPG密钥
|
||
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
|
||
|
||
# 设置稳定版仓库
|
||
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
|
||
|
||
# 更新包索引
|
||
apt-get update
|
||
|
||
# 安装Docker Engine
|
||
apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
|
||
|
||
# 启动Docker服务
|
||
systemctl start docker
|
||
systemctl enable docker
|
||
|
||
log_success "Docker安装完成"
|
||
fi
|
||
|
||
# 将jingrow用户添加到docker组
|
||
usermod -aG docker jingrow
|
||
log_success "将jingrow用户添加到docker组"
|
||
}
|
||
|
||
# 7. 启动traefik
|
||
start_traefik() {
|
||
log_info "启动traefik服务..."
|
||
|
||
cd /home/jingrow/traefik
|
||
|
||
# 使用jingrow用户启动traefik
|
||
su - jingrow -c "cd /home/jingrow/traefik && docker compose up -d"
|
||
|
||
log_success "traefik服务启动完成"
|
||
}
|
||
|
||
# 8. 安装项目依赖
|
||
install_project_dependencies() {
|
||
log_info "安装jsite/$PROJECT_NAME项目依赖..."
|
||
|
||
cd /home/jingrow/jsite/$PROJECT_NAME
|
||
|
||
su - jingrow -c "
|
||
export NVM_DIR=\"\$HOME/.nvm\"
|
||
[ -s \"\$NVM_DIR/nvm.sh\" ] && \. \"\$NVM_DIR/nvm.sh\"
|
||
cd /home/jingrow/jsite/$PROJECT_NAME
|
||
npm install
|
||
"
|
||
|
||
log_success "项目依赖安装完成"
|
||
}
|
||
|
||
# 9. 显示部署信息
|
||
show_deployment_info() {
|
||
log_success "=== 部署完成 ==="
|
||
echo ""
|
||
log_info "部署信息:"
|
||
echo " - 用户: jingrow"
|
||
echo " - jsite目录: /home/jingrow/jsite"
|
||
echo " - 项目目录: /home/jingrow/jsite/$PROJECT_NAME"
|
||
echo " - Traefik目录: /home/jingrow/traefik"
|
||
echo " - Traefik管理界面: http://localhost:8080"
|
||
echo ""
|
||
log_info ".env文件配置:"
|
||
echo " - PUBLIC_SITE_URL: $SITE_URL"
|
||
echo " - JINGROW_SITE_NAME: $SITE_NAME"
|
||
echo " - JINGROW_SERVER_URL: $SERVER_URL"
|
||
echo " - REVALIDATE_TOKEN: $REVALIDATE_TOKEN"
|
||
echo " - JINGROW_API_KEY: $API_KEY"
|
||
echo " - JINGROW_API_SECRET: $API_SECRET"
|
||
echo ""
|
||
log_info "下一步操作:"
|
||
echo " 1. 进入项目目录: cd /home/jingrow/jsite/$PROJECT_NAME"
|
||
echo " 2. 启动开发服务器: npm run dev"
|
||
echo " 3. 访问Traefik管理界面: http://localhost:8080"
|
||
echo ""
|
||
log_warning "注意:请确保防火墙允许80、443、8080端口访问"
|
||
}
|
||
|
||
# 主函数
|
||
main() {
|
||
log_info "开始jsite前端自动化部署..."
|
||
echo ""
|
||
log_info "部署参数:"
|
||
echo " - 项目名称: $PROJECT_NAME"
|
||
echo " - Git仓库: $GIT_REPO"
|
||
echo " - Node.js版本: $NODE_VERSION"
|
||
echo " - 跳过Docker: $SKIP_DOCKER"
|
||
echo " - 跳过Traefik: $SKIP_TRAEFIK"
|
||
echo " - 跳过依赖安装: $SKIP_DEPENDENCIES"
|
||
echo " - 强制更新: $FORCE_UPDATE"
|
||
echo ""
|
||
log_info ".env文件参数:"
|
||
echo " - 网站URL: $SITE_URL"
|
||
echo " - 站点名称: $SITE_NAME"
|
||
echo " - 服务器URL: $SERVER_URL"
|
||
echo " - 重新验证令牌: $REVALIDATE_TOKEN"
|
||
echo " - API密钥: $API_KEY"
|
||
echo " - API密钥: $API_SECRET"
|
||
echo ""
|
||
|
||
check_root
|
||
create_jingrow_user
|
||
|
||
if [ "$SKIP_DOCKER" = false ]; then
|
||
install_docker
|
||
else
|
||
log_warning "跳过Docker安装"
|
||
fi
|
||
|
||
install_nodejs
|
||
clone_jsite_project
|
||
create_env_file
|
||
|
||
if [ "$SKIP_TRAEFIK" = false ]; then
|
||
install_traefik
|
||
start_traefik
|
||
else
|
||
log_warning "跳过Traefik安装和启动"
|
||
fi
|
||
|
||
if [ "$SKIP_DEPENDENCIES" = false ]; then
|
||
install_project_dependencies
|
||
else
|
||
log_warning "跳过项目依赖安装"
|
||
fi
|
||
|
||
show_deployment_info
|
||
|
||
log_success "部署脚本执行完成!"
|
||
}
|
||
|
||
# 执行主函数
|
||
parse_arguments "$@"
|
||
main "$@" |