#!/bin/bash # =============================================== # 1. 基础输出函数 # =============================================== print_logo() { cat << "EOF" ___ ___ _ / _ \ _ __ ___ __ __ _ _ / _ \ __ _ _ __ ___ | | / /_)/| '__| / _ \ \ \/ /| | | | / /_)/ / _` || '_ \ / _ \| | / ___/ | | | (_) | > < | |_| |/ ___/ | (_| || | | || __/| | \/ |_| \___/ /_/\_\ \__, |\/ \__,_||_| |_| \___||_| |___/ EOF } print_message() { # 格式: 绿色中文 | 英文 echo -e "\033[32m$2\033[0m | $1" } # =============================================== # 2. 环境检查函数 # =============================================== # 检查软件是否安装 check_available() { tools=$1 if command -v "$tools" >/dev/null 2>&1; then print_message "$tools Installed!" "$tools 已安装!" else print_message "$tools did not installed!" "$tools 未安装!" fi } # 检查 Web 环境 check_web_environment() { print_message "Checking web environment..." "正在检查 Web 环境..." check_available php check_available php-fpm check_available nginx check_available apache2 check_available mysql check_available redis-cli } # =============================================== # 3. 依赖安装函数 # =============================================== install_composer() { # 检查是否安装了 Composer if ! command -v composer &>/dev/null; then print_message "Composer not found, installing..." "未找到 Composer,正在安装..." EXPECTED_CHECKSUM="$(php -r 'copy("https://composer.github.io/installer.sig", "php://stdout");')" php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" ACTUAL_CHECKSUM="$(php -r "echo hash_file('sha384', 'composer-setup.php');")" if [ "$EXPECTED_CHECKSUM" != "$ACTUAL_CHECKSUM" ]; then >&2 print_message "ERROR: Invalid installer checksum" "错误: 安装程序校验和无效" rm composer-setup.php exit 1 fi php composer-setup.php --quiet rm composer-setup.php mv composer.phar /usr/local/bin/composer else print_message "Composer is already installed." "Composer 已安装。" # 导入 lib_o.sh 的 composer self-update 逻辑 if [[ $(composer -n --version --no-ansi 2>/dev/null | cut -d" " -f3) < 2.2.0 ]]; then print_message "Updating Composer..." "正在更新 Composer..." composer self-update fi fi } # 安装 Node.js 和 NPM (新增函数) install_nodejs_npm() { if command -v node &>/dev/null && command -v npm &>/dev/null; then print_message "Node.js and npm are already installed." "Node.js 和 npm 已安装。" return 0 fi print_message "Node.js or npm not found, attempting installation..." "未找到 Node.js 或 npm,正在尝试安装..." # Node.js LTS 版本 NODE_VERSION=22 if [[ -f /etc/debian_version ]]; then # Debian/Ubuntu (使用 NodeSource 仓库获取 LTS 版本) print_message "Using NodeSource repository for Debian/Ubuntu." "正在使用 NodeSource 仓库 (Debian/Ubuntu)。" curl -fsSL https://deb.nodesource.com/setup_$NODE_VERSION.x | sudo -E bash - sudo apt-get install -y nodejs elif [[ -f /etc/redhat-release ]]; then # RHEL/CentOS/Fedora print_message "Using NodeSource repository for RHEL/CentOS." "正在使用 NodeSource 仓库 (RHEL/CentOS)。" curl -fsSL https://rpm.nodesource.com/setup_$NODE_VERSION.x | sudo bash - sudo yum install -y nodejs elif [[ -f /etc/SuSE-release ]]; then # OpenSUSE/SLES print_message "Unsupported automatic Node.js installation for SUSE/OpenSUSE." "不支持 SUSE/OpenSUSE 的自动 Node.js 安装。" return 1 elif [[ -f /etc/arch-release ]]; then # Arch Linux print_message "Installing Node.js via pacman for Arch Linux." "正在通过 pacman 安装 Node.js (Arch Linux)。" sudo pacman -S --noconfirm nodejs npm elif [[ -f /etc/alpine-release ]]; then # Alpine Linux print_message "Installing Node.js via apk for Alpine Linux." "正在通过 apk 安装 Node.js (Alpine Linux)。" sudo apk add nodejs npm else print_message "Unsupported Linux distribution. Please install Node.js/npm manually." "不支持的 Linux 发行版。请手动安装 Node.js/npm。" return 1 fi if command -v node &>/dev/null && command -v npm &>/dev/null; then print_message "Node.js and npm installation completed!" "Node.js 和 npm 安装完成!" return 0 else print_message "Node.js and npm installation failed! Please check system logs." "Node.js 和 npm 安装失败! 请检查系统日志。" return 1 fi } # 安装 Supervisor install_supervisor() { # 判断系统 if [[ -f /etc/debian_version ]]; then PM=apt-get elif [[ -f /etc/redhat-release ]]; then PM=yum elif [[ -f /etc/SuSE-release ]]; then PM=zypper elif [[ -f /etc/arch-release ]]; then PM=pacman elif [[ -f /etc/alpine-release ]]; then PM=apk else print_message "Unsupported Linux distribution. Please install supervisor manually." "不支持的 Linux 发行版。请手动安装 supervisor。" return 1 fi if command -v supervisorctl >/dev/null; then print_message "Supervisor installed!" "Supervisor 已安装!" else print_message "Supervisor not found, installing..." "未找到 Supervisor,正在安装..." # 安装 Supervisor case $PM in apt-get) sudo apt-get update sudo apt-get install -y supervisor ;; yum) sudo yum install -y epel-release sudo yum install -y supervisor ;; zypper) sudo zypper install -y supervisor ;; apk) sudo apk add supervisor ;; pacman) sudo pacman -S supervisor ;; esac # 激活 case $PM in yum) sudo service supervisord start sudo chkconfig supervisord on ;; *) # 适用于大多数使用 systemd 的系统 sudo systemctl start supervisor.service sudo systemctl enable supervisor.service ;; esac if command -v supervisorctl >/dev/null; then print_message "Supervisor installation completed!" "Supervisor 安装完成!" else print_message "Supervisor installation failed! Please check logs." "Supervisor 安装失败! 请检查日志。" return 1 fi fi return 0 } check_composer() { if [ ! -f "/usr/bin/composer" ]; then curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/bin --filename=composer else if [[ $(composer -n --version --no-ansi 2>/dev/null | cut -d" " -f3) < 2.2.0 ]]; then composer self-update fi fi } # =============================================== # 4. 配置和权限函数 # =============================================== set_permissions() { print_message "Setting Laravel directory permissions (www)..." "正在设置 Laravel 目录权限 (www)..." if [ ! -d "/home/www" ]; then mkdir -p /home/www chown www:www /home/www fi chmod -R 755 storage bootstrap/cache public/assets chown -R www:www storage bootstrap/cache public/assets } # =============================================== # 5. 服务配置函数 # =============================================== set_schedule() { SCHEDULE_CMD="php $(pwd)/artisan schedule:run >> /dev/null 2>&1" # 尝试使用 www 用户的 crontab if command -v crontab >/dev/null && id -u www &>/dev/null; then USER_CRON="www" else # 如果 www 用户不存在,则使用当前用户 USER_CRON=$(whoami) fi if crontab -u $USER_CRON -l 2>/dev/null | grep -q "$SCHEDULE_CMD"; then print_message "Schedule already exists in crontab for user $USER_CRON." "定时任务已存在于用户 $USER_CRON 的 crontab 中。" else # 添加定时任务 (crontab -u $USER_CRON -l 2>/dev/null; echo "* * * * * $SCHEDULE_CMD") | crontab -u $USER_CRON - print_message "Schedule task added to crontab for user $USER_CRON." "定时任务已添加到用户 $USER_CRON 的 crontab。" fi } set_horizon() { # 创建 Horizon 配置文件 (用户使用 www 以匹配权限) if [ ! -f /etc/supervisor/conf.d/horizon.conf ]; then cat > /etc/supervisor/conf.d/horizon.conf <> .env echo "REVERB_APP_ID=$REVERB_APP_ID" >> .env echo "REVERB_APP_KEY=$REVERB_APP_KEY" >> .env echo "REVERB_APP_SECRET=$REVERB_APP_SECRET" >> .env echo "REVERB_SCHEME=http" >> .env echo "REVERB_HOST=" .env echo "REVERB_PATH=" .env echo "VITE_REVERB_APP_KEY=\"\${REVERB_APP_KEY}\"" >> .env echo "VITE_REVERB_HOST=\"\${REVERB_HOST}\"" >> .env echo "VITE_REVERB_PORT=\"\${REVERB_PORT}\"" >> .env echo "VITE_REVERB_SCHEME=\"\${REVERB_SCHEME}\"" >> .env echo "VITE_REVERB_PATH=\"\${REVERB_PATH}\"" >> .env echo "REVERB_SERVER_PATH=\"\${REVERB_PATH}\"" >> .env print_message "Reverb configuration added to .env file." "Reverb 配置已添加到 .env 文件。" else print_message "Reverb configuration already exists in .env file." "Reverb 配置已存在于 .env 文件中。" fi # 创建 Reverb 服务的 supervisor 配置 (用户使用 www 以匹配权限) if [ ! -f "/etc/supervisor/conf.d/reverb.conf" ]; then cat > /etc/supervisor/conf.d/reverb.conf </dev/null || ! command -v npm &>/dev/null; then print_message "Cannot build frontend assets. Node.js/npm is not available." "无法构建前端资源。Node.js/npm 不可用。" return fi print_message "Installing frontend dependencies..." "安装前端依赖..." npm install print_message "Building frontend assets..." "构建前端资源..." npm run build } # =============================================== # 6. 清理函数 # =============================================== update_old_queue() { # 检查旧的队列设置 if crontab -l 2>/dev/null | grep -q "artisan queue:work"; then print_message "Removing old queue worker from crontab..." "正在从 crontab 中移除旧的队列工作者..." crontab -l | grep -v "artisan queue:work" | crontab - fi # 检查旧的队列设置 if crontab -l 2>/dev/null | grep -q "queue.sh"; then print_message "Removing old queue.sh cron job..." "正在移除旧的 queue.sh 定时任务..." crontab -l | grep -v "queue.sh" | crontab - fi set_horizon } clean_files() { print_message "Cleaning up unnecessary files..." "正在清理不必要的文件..." rm -f .gitignore .styleci.yml rm -rf .htaccess 404.html index.html if [ -f .user.ini ]; then # 尝试移除文件锁 if command -v chattr >/dev/null; then chattr -i .user.ini fi rm -f .user.ini print_message "Cleaned up unnecessary files" "不必要的文件已清理。" fi }