diff --git a/install_jsite.sh b/install_jsite.sh new file mode 100755 index 0000000..f076e3f --- /dev/null +++ b/install_jsite.sh @@ -0,0 +1,519 @@ +#!/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 "$@" \ No newline at end of file