安装php7.4.33的shell脚本

保存文件:deploy_php7.sh

执行:chmod +x deploy_php7.sh

执行:./deploy_php7.sh

bash 复制代码
#!/bin/bash

# PHP 7.4.33自动化部署脚本 for CentOS 7
# 日期:$(date +%Y-%m-%d)
# 如果中途失败,请根据失败步骤,注释一运行步骤,继续部署下一步的步骤

set -e  # 遇到错误时退出脚本

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
MAGENTA='\033[0;35m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color

# 日志函数
log_info() {
    echo -e "${GREEN}[INFO]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"
}

log_warn() {
    echo -e "${YELLOW}[WARN]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"
}

log_error() {
    echo -e "${RED}[ERROR]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"
}

log_step() {
    echo -e "${BLUE}[STEP]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"
}

log_debug() {
    if [ "$DEBUG" = "true" ]; then
        echo -e "${CYAN}[DEBUG]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"
    fi
}

# 检查是否以root用户运行
check_root() {
    if [[ $EUID -ne 0 ]]; then
        log_error "此脚本必须以root用户运行"
        exit 1
    fi
}

# 检查CentOS版本
check_centos_version() {
    if ! grep -q "CentOS Linux release 7" /etc/redhat-release; then
        log_error "此脚本仅支持CentOS 7"
        exit 1
    fi
}

# 配置参数
PHP_VERSION="7.4.33"
PHP_TAR="php-${PHP_VERSION}.tar.gz"
# https://windows.php.net/downloads/releases/archives/php-7.4.33-src.zip
# https://www.php.net/distributions/php-7.4.33.tar.gz
PHP_DOWNLOAD_URL="https://www.php.net/distributions/${PHP_TAR}"

INSTALL_DIR="/usr/local/php7"
CONF_DIR="${INSTALL_DIR}/etc"
LOG_DIR="/var/log/php"
NGINX_HTML="/usr/share/nginx/html"
TMP_DIR="/tmp/php_build"
PHP_USER="www"
PHP_GROUP="www"
PHP_FPM_PORT="9000"

# PHP依赖库版本
LIBXML_VERSION="2.9.12"
SQLITE_VERSION="3380500"
ONIGURUMA_VERSION="6.9.8"
LIBZIP_VERSION="1.10.1"

# 编译选项
PHP_COMPILE_OPTIONS="
--prefix=${INSTALL_DIR}
--with-config-file-path=${CONF_DIR}
--with-config-file-scan-dir=${CONF_DIR}/php.d
--enable-fpm
--with-fpm-user=${PHP_USER}
--with-fpm-group=${PHP_GROUP}
--enable-mysqlnd
--with-mysqli=mysqlnd
--with-pdo-mysql=mysqlnd
--with-pdo-sqlite
--with-sqlite3
--with-openssl
--with-curl
--with-zlib
--with-bz2
--with-gettext
--with-readline
--with-xmlrpc
--with-libxml-dir
--with-jpeg
--with-freetype
--with-webp
--enable-gd
--with-avif
--with-xpm
--enable-exif
--enable-zip
--enable-bcmath
--enable-calendar
--enable-ftp
--enable-mbstring
--enable-intl
--enable-shmop
--enable-soap
--enable-sockets
--enable-sysvmsg
--enable-sysvsem
--enable-sysvshm
--with-pear
--with-mhash
--with-pcre-regex
--with-pcre-jit
--with-iconv
--enable-pcntl
--enable-opcache
--with-openssl-dir
--with-system-ciphers
--with-password-argon2
--with-sodium
--enable-maintainer-zts
"

# 创建目录
create_directories() {
    log_step "创建必要的目录..."
    
    mkdir -p ${INSTALL_DIR}
    mkdir -p ${CONF_DIR}/php.d
    mkdir -p ${LOG_DIR}/{fpm,cli}
    mkdir -p ${TMP_DIR}
    mkdir -p /var/run/php-fpm
    mkdir -p /var/lib/php/{session,wsdlcache}
    
    # 设置权限
    chmod 777 ${LOG_DIR}
    chmod 777 /var/run/php-fpm
    chmod 777 /var/lib/php
    
    log_info "目录创建完成"
}

# 创建PHP运行用户
create_php_user() {
    log_step "创建PHP运行用户..."
    
    if ! id -u ${PHP_USER} >/dev/null 2>&1; then
        groupadd ${PHP_GROUP}
        useradd -r -g ${PHP_GROUP} -s /sbin/nologin ${PHP_USER}
        log_info "已创建用户: ${PHP_USER}:${PHP_GROUP}"
    else
        log_info "用户 ${PHP_USER} 已存在"
    fi
    
    # 设置目录权限
    chown -R ${PHP_USER}:${PHP_GROUP} ${LOG_DIR}
    chown -R ${PHP_USER}:${PHP_GROUP} /var/run/php-fpm
    chown -R ${PHP_USER}:${PHP_GROUP} /var/lib/php
    
    log_info "用户权限设置完成"
}

# 更健壮的依赖安装方式
install_dependencies() {
   log_step "安装系统依赖..."
    
    # 启用EPEL仓库
    yum install -y epel-release
    
    # 安装开发工具
    yum groupinstall -y "Development Tools"
    yum install -y python-devel python3-devel
    
    # 检查是否已有MySQL安装
    local has_mysql_installed=false
    if [ -d "/usr/local/mysql" ] || rpm -qa | grep -i mysql | grep -v lib; then
        has_mysql_installed=true
        log_warn "检测到已安装的MySQL,跳过可能冲突的MySQL包安装"
    fi
    
    # 安装基础依赖(排除MySQL相关包以保护现有安装)
    local packages=(
        wget curl git gcc gcc-c++ make autoconf automake libtool pkgconfig
        libxml2-devel openssl-devel curl-devel libjpeg-devel libpng-devel
        freetype-devel libwebp-devel libXpm-devel libavif-devel libicu-devel
        libxslt-devel bzip2-devel readline-devel sqlite-devel oniguruma-devel
        libzip-devel gmp-devel libmcrypt-devel mhash-devel enchant-devel
        aspell-devel libedit-devel recode-devel libc-client-devel krb5-devel
        openldap-devel postgresql-devel unixODBC-devel libtidy-devel gd-devel
        libpng libjpeg-turbo freetype libwebp libXpm libicu libxslt bzip2
        sqlite oniguruma libzip gmp libmcrypt mhash enchant aspell libedit
        recode libc-client krb5-workstation openldap postgresql unixODBC
        libtidy libevent-devel ImageMagick-devel ImageMagick libmemcached-devel
        memcached rabbitmq-c-devel librabbitmq-devel geoip-devel libmaxminddb-devel
        yaml-cpp-devel libyaml-devel hiredis-devel re2c libargon2-devel libsodium-devel
    )
    
    # 安装主要依赖包
    yum install -y "${packages[@]}"
    
    # 只有在没有MySQL安装时才安装MySQL兼容库
    if [ "$has_mysql_installed" = false ]; then
        # 先尝试安装 mariadb-libs,如果失败则跳过
        yum install -y mariadb-libs || log_warn "mariadb-libs安装失败,继续执行"
    else
        log_info "跳过MySQL相关库安装以保护现有MySQL安装"
    fi
    
    # 单独安装 net-snmp 相关包(放在最后)
    yum install -y net-snmp-devel net-snmp || true
    
    log_info "系统依赖安装完成"
}

# 下载PHP源码
download_php_source() {
    log_step "下载PHP源码..."
    
    cd ${TMP_DIR}
    
    if [ ! -f "${PHP_TAR}" ]; then
        log_info "下载PHP ${PHP_VERSION}..."
        wget --no-check-certificate ${PHP_DOWNLOAD_URL} -O ${PHP_TAR}
        
        if [ $? -ne 0 ]; then
            log_error "下载PHP失败"
            exit 1
        fi
    else
        log_info "PHP源码包已存在"
    fi
    
    # 解压源码包
    log_info "解压源码包..."
    tar -xzf ${PHP_TAR}
    
    log_info "PHP源码下载完成"
}

# 编译安装依赖库 添加对GD所需库的支持
compile_dependencies() {
    log_step "编译安装PHP依赖库..."
    cd ${TMP_DIR}
    
    # 安装libxml2(如果需要更新版本)
    if [ ! -d "libxml2-${LIBXML_VERSION}" ]; then
        log_info "下载libxml2 ${LIBXML_VERSION}..."
        if [ ! -f "libxml2-${LIBXML_VERSION}.tar.gz" ]; then
            wget http://xmlsoft.org/sources/libxml2-${LIBXML_VERSION}.tar.gz
            else
            log_info "libxml2 ${LIBXML_VERSION}.tar.gz已存在..."
        fi
        tar -xzf libxml2-${LIBXML_VERSION}.tar.gz
        cd libxml2-${LIBXML_VERSION}
        ./configure --prefix=/usr/local/libxml2
        make -j$(nproc)
        make install
        cd ..
    fi
    
    # 安装oniguruma(正则表达式库)
    if [ ! -d "onig-${ONIGURUMA_VERSION}" ]; then
        log_info "下载oniguruma ${ONIGURUMA_VERSION}..."
        if [ ! -f "onig-${ONIGURUMA_VERSION}.tar.gz" ]; then
            wget https://github.com/kkos/oniguruma/releases/download/v${ONIGURUMA_VERSION}/onig-${ONIGURUMA_VERSION}.tar.gz
            else
            log_info "onig-${ONIGURUMA_VERSION}.tar.gz已存在..."
        fi
        tar -xzf onig-${ONIGURUMA_VERSION}.tar.gz
        cd onig-${ONIGURUMA_VERSION}
        ./configure --prefix=/usr/local/oniguruma
        make -j$(nproc)
        make install
        cd ..
    fi
    
    # 安装libzip
    if [ ! -d "libzip-${LIBZIP_VERSION}" ]; then
        log_info "下载libzip ${LIBZIP_VERSION}..."
        if [ ! -f "libzip-${LIBZIP_VERSION}.tar.gz" ]; then
            wget https://libzip.org/download/libzip-${LIBZIP_VERSION}.tar.gz
            else
            log_info "libzip-${LIBZIP_VERSION}.tar.gz已存在..."
        fi
        tar -xzf libzip-${LIBZIP_VERSION}.tar.gz
        cd libzip-${LIBZIP_VERSION}
        mkdir build && cd build
        cmake .. -DCMAKE_INSTALL_PREFIX=/usr/local/libzip
        make -j$(nproc)
        make install
        cd ../..
    fi
    
    # 更新动态库链接
    echo "/usr/local/libxml2/lib" >> /etc/ld.so.conf.d/local.conf
    echo "/usr/local/oniguruma/lib" >> /etc/ld.so.conf.d/local.conf
    echo "/usr/local/libzip/lib" >> /etc/ld.so.conf.d/local.conf
    ldconfig
    
    log_info "依赖库编译安装完成"
}

# 编译安装PHP
compile_php() {
    log_step "编译安装PHP..."
    
    cd ${TMP_DIR}/php-${PHP_VERSION}
    
    # 清理之前的编译
    make clean 2>/dev/null || true
    make distclean 2>/dev/null || true
    
    # 配置PHP
    log_info "配置PHP编译选项..."
    
    # 准备配置参数
    CONFIG_CMD="./configure ${PHP_COMPILE_OPTIONS} \
        --with-libxml-dir=/usr/local/libxml2 \
        --with-onig=/usr/local/oniguruma \
        --with-libzip=/usr/local/libzip \
        --with-webp-dir \
        --with-freetype-dir \
        --with-jpeg-dir \
        --with-png-dir"
    
    log_debug "配置命令: ${CONFIG_CMD}"
    
    # 执行配置
    eval ${CONFIG_CMD}
    
    if [ $? -ne 0 ]; then
        log_error "PHP配置失败"
        exit 1
    fi
    
    # 获取CPU核心数
    CPU_CORES=$(nproc)
    log_info "使用 ${CPU_CORES} 个CPU核心进行编译"
    
    # 编译
    log_info "开始编译PHP..."
    make -j${CPU_CORES}
    
    if [ $? -ne 0 ]; then
        log_error "PHP编译失败"
        exit 1
    fi
    
    # 安装
    log_info "开始安装PHP..."
    make install
    
    if [ $? -ne 0 ]; then
        log_error "PHP安装失败"
        exit 1
    fi
    
    log_info "PHP编译安装完成"
}

# 配置PHP
configure_php() {
    log_step "配置PHP..."
    
    # 复制配置文件
    cp ${TMP_DIR}/php-${PHP_VERSION}/php.ini-production ${CONF_DIR}/php.ini
    cp ${INSTALL_DIR}/etc/php-fpm.conf.default ${CONF_DIR}/php-fpm.conf
    cp ${INSTALL_DIR}/etc/php-fpm.d/www.conf.default ${CONF_DIR}/php-fpm.d/www.conf
    
    # 备份原始配置
    cp ${CONF_DIR}/php.ini ${CONF_DIR}/php.ini.bak
    cp ${CONF_DIR}/php-fpm.conf ${CONF_DIR}/php-fpm.conf.bak
    cp ${CONF_DIR}/php-fpm.d/www.conf ${CONF_DIR}/php-fpm.d/www.conf.bak
    
    # 配置php.ini
    log_info "配置php.ini..."
    
    # 创建优化的php.ini
    cat > ${CONF_DIR}/php.ini << EOF
[PHP]
; PHP配置优化

; 错误处理
error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT
display_errors = Off
display_startup_errors = Off
log_errors = On
error_log = /var/log/php/cli/error.log

; 时区设置
date.timezone = Asia/Shanghai

; 文件上传
upload_max_filesize = 100M
post_max_size = 100M
max_file_uploads = 20

; 内存限制
memory_limit = 256M

; 执行时间
max_execution_time = 300
max_input_time = 300

; 会话设置
session.save_handler = files
session.save_path = "/var/lib/php/session"
session.use_strict_mode = 1
session.cookie_httponly = 1
session.cookie_secure = 1
session.use_only_cookies = 1
session.cookie_lifetime = 0
session.gc_maxlifetime = 1440

; 输出缓冲
output_buffering = 4096

; 路径设置
include_path = ".:/usr/share/pear"

; 禁用危险函数,phpinfo
disable_functions = exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,show_source

; 禁用危险类
disable_classes = 

; 资源限制
max_input_nesting_level = 64
max_input_vars = 1000

; 数据过滤
filter.default = unsafe_raw
filter.default_flags = 

; 性能优化
realpath_cache_size = 4096K
realpath_cache_ttl = 600

; Zend OPcache
[opcache]
opcache.enable=1
opcache.enable_cli=1
opcache.memory_consumption=128
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=10000
opcache.revalidate_freq=2
opcache.fast_shutdown=1
opcache.enable_file_override=1
opcache.validate_timestamps=0
opcache.revalidate_path=0
opcache.save_comments=1
opcache.load_comments=1
opcache.dups_fix=0
opcache.blacklist_filename=${INSTALL_DIR}/etc/php.d/opcache.blacklist

; Xdebug (默认禁用)
;[xdebug]
;zend_extension=xdebug.so
;xdebug.remote_enable=0
;xdebug.profiler_enable=0
;xdebug.remote_host=127.0.0.1
;xdebug.remote_port=9000
;xdebug.remote_handler=dbgp
;xdebug.remote_mode=req
;xdebug.remote_autostart=0
;xdebug.remote_connect_back=0
;xdebug.idekey=PHPSTORM
;xdebug.max_nesting_level=512

; 其他扩展配置
[curl]
[date]
[filter]
[iconv]
[intl]
[json]
[sodium]
[zlib]
; 自定义安装的扩展配置
; extension=redis.so
; extension=imagick.so
; extension_dir = "${INSTALL_DIR}/etc/php.d/*.ini"
EOF

    # 配置php-fpm.conf
    log_info "配置php-fpm.conf..."
    
    cat > ${CONF_DIR}/php-fpm.conf << EOF
[global]
pid = /var/run/php-fpm/php-fpm.pid
error_log = /var/log/php/fpm/error.log
log_level = notice
emergency_restart_threshold = 10
emergency_restart_interval = 1m
process_control_timeout = 10s
daemonize = yes

; 进程管理器设置
process.max = 0
process.priority = 0
rlimit_files = 65535
rlimit_core = 0
events.mechanism = epoll

; 系统日志
syslog.facility = daemon
syslog.ident = php-fpm

; 包含池配置
include = ${INSTALL_DIR}/etc/php-fpm.d/*.conf
EOF

    # 配置www池
    log_info "配置www池..."
    
    cat > ${CONF_DIR}/php-fpm.d/www.conf << EOF
[www]
user = ${PHP_USER}
group = ${PHP_GROUP}

; 监听方式
listen = 127.0.0.1:${PHP_FPM_PORT}
listen.backlog = 65535
listen.allowed_clients = 127.0.0.1

; 进程管理
pm = dynamic
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 35
pm.max_requests = 500
pm.process_idle_timeout = 10s

; 环境变量
env[HOSTNAME] = \$HOSTNAME
env[PATH] = /usr/local/bin:/usr/bin:/bin
env[TMP] = /tmp
env[TMPDIR] = /tmp
env[TEMP] = /tmp

; 请求设置
request_terminate_timeout = 300
request_slowlog_timeout = 10s
slowlog = /var/log/php/fpm/www-slow.log

; 进程设置
rlimit_files = 65535
rlimit_core = 0

; 安全设置
security.limit_extensions = .php .php3 .php4 .php5 .php7

; 性能优化
php_flag[display_errors] = off
php_admin_flag[log_errors] = on
php_admin_value[error_log] = /var/log/php/fpm/www-error.log
php_admin_value[memory_limit] = 256M
php_admin_value[upload_max_filesize] = 100M
php_admin_value[post_max_size] = 100M
php_admin_value[max_execution_time] = 300

; 会话设置
php_value[session.save_handler] = files
php_value[session.save_path]    = /var/lib/php/session
php_value[session.use_strict_mode] = 1
php_value[session.cookie_httponly] = 1
php_value[session.cookie_secure] = 1
php_value[session.use_only_cookies] = 1
EOF

    # 创建opcache黑名单
    cat > ${CONF_DIR}/php.d/opcache.blacklist << EOF
; OPcache黑名单文件
; 格式: 每行一个文件路径或模式

; 测试文件
*/test/*
*/tests/*
*/Testing/*

; 版本控制目录
*/.git/*
*/.svn/*
*/.hg/*

; 临时文件
*/tmp/*
*/temp/*

; 日志文件
*/logs/*
*/log/*

; 缓存文件
*/cache/*
*/caches/*
*/smarty/cache/*
*/smarty/templates_c/*

; 用户上传文件
*/uploads/*
*/attachments/*
EOF

    # 创建环境配置文件
    cat > /etc/profile.d/php.sh << EOF
# PHP环境变量
export PATH=\$PATH:${INSTALL_DIR}/bin:${INSTALL_DIR}/sbin
export PHP_INI_SCAN_DIR=${CONF_DIR}/php.d
EOF

# 或者创建一个测试文件
cat > /usr/share/nginx/html/gd_check.php << 'EOF'
<?php
if (extension_loaded('gd')) {
    echo "GD库已安装\n";
    echo "GD版本: " . gd_info()['GD Version'] . "\n";
    print_r(gd_info());
} else {
    echo "GD库未安装\n";
}
?>
EOF

    # 设置权限
    chown -R ${PHP_USER}:${PHP_GROUP} ${LOG_DIR}
    chown -R ${PHP_USER}:${PHP_GROUP} /var/run/php-fpm
    chown -R ${PHP_USER}:${PHP_GROUP} /var/lib/php
    chmod 755 ${CONF_DIR}/php.d
    
    log_info "PHP配置完成"
}

# 创建systemd服务文件
create_systemd_service() {
    log_step "创建systemd服务文件..."
    
    cat > /lib/systemd/system/php-fpm.service << EOF
[Unit]
Description=PHP FastCGI Process Manager
After=network.target nss-lookup.target

[Service]
# 增加操作权限
PermissionsStartOnly=true
Type=forking
PIDFile=/var/run/php-fpm/php-fpm.pid
ExecStartPre=/usr/bin/mkdir -p /var/run/php-fpm
ExecStartPre=/usr/bin/chmod 777 /var/run/php-fpm
ExecStartPre=/usr/bin/touch /var/run/php-fpm/php-fpm.pid
ExecStartPre=/usr/bin/chmod 777 /var/run/php-fpm/php-fpm.pid
ExecStart=${INSTALL_DIR}/sbin/php-fpm --daemonize --fpm-config ${CONF_DIR}/php-fpm.conf
ExecReload=/bin/kill -USR2 \$MAINPID
ExecStop=/bin/kill -QUIT \$MAINPID
PrivateTmp=true
Restart=on-failure
RestartSec=5s
StartLimitInterval=60s
StartLimitBurst=3
User=${PHP_USER}
Group=${PHP_GROUP}

# Security
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=${LOG_DIR} /var/run/php-fpm /var/lib/php
ReadOnlyPaths=/
PrivateDevices=true
ProtectKernelTunables=true
ProtectKernelModules=true
ProtectControlGroups=true
RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX
RestrictNamespaces=true
RestrictRealtime=true
SystemCallFilter=@system-service
SystemCallErrorNumber=EPERM
LockPersonality=true
MemoryDenyWriteExecute=true

# 资源限制
LimitNOFILE=65535
LimitNPROC=65535

[Install]
WantedBy=multi-user.target
EOF
    
    # 重新加载systemd配置
    systemctl daemon-reload
    log_info "systemd服务文件创建完成"
}

# 安装PHP扩展
install_php_extensions() {
    log_step "安装常用PHP扩展..."
    
    cd ${TMP_DIR}
    
    # 安装Redis扩展(使用Gitee镜像)
    log_info "安装Redis扩展..."
    if [ ! -d "phpredis" ]; then
        # 克隆指定分支(例如 main 分支)
        # git clone -b develop https://gitee.com/mirrors/phpredis.git
        # 或者克隆特定版本
        git clone -b 6.2.0 https://gitee.com/mirrors/phpredis.git
        cd phpredis
        ${INSTALL_DIR}/bin/phpize
        ./configure --with-php-config=${INSTALL_DIR}/bin/php-config
        make -j$(nproc)
        make install
        cd ..
        echo "extension=redis.so" > ${CONF_DIR}/php.d/redis.ini
        chmod 777 ${CONF_DIR}/php.d/redis.ini
        else
        cd phpredis
        ${INSTALL_DIR}/bin/phpize
        ./configure --with-php-config=${INSTALL_DIR}/bin/php-config
        make -j$(nproc)
        make install
        cd ..
        echo "extension=redis.so" > ${CONF_DIR}/php.d/redis.ini
        chmod 777 ${CONF_DIR}/php.d/redis.ini

    fi
    
    # 安装Memcached扩展(使用Gitee镜像)
    # log_info "安装Memcached扩展..."
    # if [ ! -d "php-memcached" ]; then
    #     git clone https://gitee.com/mirrors/php-memcached.git
    #     cd php-memcached
    #     ${INSTALL_DIR}/bin/phpize
    #     ./configure --with-php-config=${INSTALL_DIR}/bin/php-config --with-libmemcached-dir=/usr
    #     make -j$(nproc)
    #     make install
    #     cd ..
    #     echo "extension=memcached.so" > ${CONF_DIR}/php.d/memcached.ini
    #     chmod 777 ${CONF_DIR}/php.d/memcached.ini
    # fi
    
    # 安装MongoDB扩展(使用Gitee镜像)
    # log_info "安装MongoDB扩展..."
    # if [ ! -d "mongo-php-driver" ]; then
    #     git clone https://gitee.com/mirrors/mongo-php-driver.git
    #     cd mongo-php-driver
    #     git submodule sync && git submodule update --init
    #     ${INSTALL_DIR}/bin/phpize
    #     ./configure --with-php-config=${INSTALL_DIR}/bin/php-config
    #     make -j$(nproc)
    #     make install
    #     cd ..
    #     echo "extension=mongodb.so" > ${CONF_DIR}/php.d/mongodb.ini
    #     chmod 777 ${CONF_DIR}/php.d/mongodb.ini
    # fi
    
    # 安装ImageMagick扩展(使用Gitee镜像)
    log_info "安装ImageMagick扩展..."
    if [ ! -d "imagick" ]; then
        git clone https://gitee.com/mirrors/imagick.git
        cd imagick
        ${INSTALL_DIR}/bin/phpize
        ./configure --with-php-config=${INSTALL_DIR}/bin/php-config
        make -j$(nproc)
        make install
        cd ..
        echo "extension=imagick.so" > ${CONF_DIR}/php.d/imagick.ini
        chmod 777 ${CONF_DIR}/php.d/imagick.ini
        else
        cd imagick
        ${INSTALL_DIR}/bin/phpize
        ./configure --with-php-config=${INSTALL_DIR}/bin/php-config
        make -j$(nproc)
        make install
        cd ..
        echo "extension=imagick.so" > ${CONF_DIR}/php.d/imagick.ini
        chmod 777 ${CONF_DIR}/php.d/imagick.ini
    fi
    
    # 安装yaml扩展
    # log_info "安装yaml扩展..."
    # if [ ! -d "pecl-file_formats-yaml" ]; then
    #     git clone https://gitee.com/mirrors/pecl-file_formats-yaml.git
    #     cd pecl-file_formats-yaml
    #     ${INSTALL_DIR}/bin/phpize
    #     ./configure --with-php-config=${INSTALL_DIR}/bin/php-config --with-yaml=/usr
    #     make -j$(nproc)
    #     make install
    #     cd ..
    #     echo "extension=yaml.so" > ${CONF_DIR}/php.d/yaml.ini
    #   chmod 777 ${CONF_DIR}/php.d/yaml.ini
    # fi
    
    log_info "PHP扩展安装完成"
}

# 安装Composer
install_composer() {
    log_step "安装Composer..."
    
    cd ${TMP_DIR}
    
    # 下载Composer
    ${INSTALL_DIR}/bin/php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
    ${INSTALL_DIR}/bin/php -r "if (hash_file('sha384', 'composer-setup.php') === '906a84df04cea2aa72f40b5f787e49f22d4c2f19492ac310e8cba5b96ac8b64115ac402c8cd292b8a03482574915d1a8') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
    ${INSTALL_DIR}/bin/php composer-setup.php --install-dir=/usr/local/bin --filename=composer
    ${INSTALL_DIR}/bin/php -r "unlink('composer-setup.php');"
    
    # 配置Composer
    composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/
    composer config -g secure-http false
    
    log_info "Composer安装完成"
}

# 启动PHP-FPM服务
start_php_fpm() {
    log_step "启动PHP-FPM服务..."
    # 测试配置文件
    ${INSTALL_DIR}/sbin/php-fpm -t
    if [ $? -ne 0 ]; then
        log_error "PHP-FPM配置文件测试失败"
        exit 1
    fi
    log_step "给php-fpm进程相关文件赋予777权限:${LOG_DIR}..."
    chmod -R 777 ${LOG_DIR}/*


    

    # 启动服务
    systemctl start php-fpm
    
    if [ $? -ne 0 ]; then
        log_error "PHP-FPM启动失败"
        journalctl -xe | tail -50
        exit 1
    fi
    
    # 设置开机自启
    systemctl enable php-fpm
    
    # 检查服务状态
    sleep 2
    if systemctl is-active --quiet php-fpm; then
        log_info "PHP-FPM服务运行正常"
    else
        log_error "PHP-FPM服务未运行"
        exit 1
    fi
}

# 设置PHP软链接
setup_php_symlinks() {
    log_info "设置PHP软链接..."

    # 创建全局 PHP 命令链接
    # sudo ln -s ${INSTALL_DIR}/bin/php /usr/bin/php
    # # 创建 phpize 链接
    # sudo ln -s ${INSTALL_DIR}/bin/phpize /usr/bin/phpize
    # # 创建 php-config 链接
    # sudo ln -s ${INSTALL_DIR}/bin/php-config /usr/bin/php-config
    # # 创建 PHP-FPM 链接
    # sudo ln -s ${INSTALL_DIR}/sbin/php-fpm /usr/sbin/php-fpm
    
    for cmd in php phpize php-config; do
        src="${INSTALL_DIR}/bin/$cmd"
        dst="/usr/bin/$cmd"
        
        if [ -f "$src" ]; then
            if [ ! -e "$dst" ] || [ "$(readlink "$dst")" != "$src" ]; then
                echo "创建: $src -> $dst"
                ln -sf "$src" "$dst"
            fi
        fi
    done
    # PHP-FPM
    if [ -f "${INSTALL_DIR}/sbin/php-fpm" ]; then
        ln -sf "${INSTALL_DIR}/sbin/php-fpm" "/usr/sbin/php-fpm"
    fi
}

# 验证安装
# 修改 verify_installation 函数,添加GD库检查
verify_installation() {
    log_step "验证安装..."
    
    # 检查PHP版本
    PHP_VER=$(${INSTALL_DIR}/bin/php -v 2>&1 | head -1)
    log_info "PHP版本: ${PHP_VER}"
    
    # 检查PHP配置
    PHP_CONFIG=$(${INSTALL_DIR}/bin/php --ini 2>&1 | grep "Loaded Configuration File")
    log_info "${PHP_CONFIG}"
    
    # 检查PHP-FPM状态
    PHP_FPM_STATUS=$(systemctl status php-fpm 2>&1 | grep "Active:" | cut -d':' -f2-)
    log_info "PHP-FPM状态: ${PHP_FPM_STATUS}"
    
    # 检查PHP模块
    log_info "已加载的PHP模块:"
    ${INSTALL_DIR}/bin/php -m | grep -E "(^[a-zA-Z])" | sort
    
    # 检查GD库是否正确安装
    if ${INSTALL_DIR}/bin/php -m | grep -q "gd"; then
        log_info "✓ GD库已正确安装"
        # 显示GD库详细信息
        ${INSTALL_DIR}/bin/php -r "if (extension_loaded('gd')) { echo 'GD Version: ' . gd_info()['GD Version'] . PHP_EOL; }"
    else
        log_warn "✗ GD库未安装或未正确加载"
    fi
    
    # 创建测试脚本
    cat > ${NGINX_HTML}/phpinfo.php << 'EOF'
<?php

$client_ip = $_SERVER['REMOTE_ADDR'];
echo "客户端IP: $client_ip" . PHP_EOL;

phpinfo();
EOF
    
    chown ${PHP_USER}:${PHP_GROUP} ${NGINX_HTML}/phpinfo.php
    chmod 644 ${NGINX_HTML}/phpinfo.php
    
    log_info "测试文件已创建: ${NGINX_HTML}/phpinfo.php"
    
    # 测试PHP解析
    log_info "测试PHP解析..."
    if ${INSTALL_DIR}/bin/php -f ${NGINX_HTML}/phpinfo.php > /dev/null 2>&1; then
        log_info "PHP解析测试成功"
    else
        log_warn "PHP解析测试失败"
    fi
}

# 配置防火墙
configure_firewall() {
    log_step "配置防火墙..."
    
    if systemctl is-active --quiet firewalld; then
        log_info "防火墙正在运行"
        # PHP-FPM通常不需要外部端口,仅用于内部通信
    else
        log_warn "防火墙未运行"
    fi
}

# 配置SELinux
configure_selinux() {
    log_step "配置SELinux..."
    
    if command -v sestatus >/dev/null 2>&1 && sestatus | grep -q "enabled"; then
        log_info "SELinux已启用,设置规则..."
        
        # 安装SELinux工具
        yum install -y policycoreutils-python
        
        # 设置PHP相关目录的SELinux上下文
        semanage fcontext -a -t httpd_sys_rw_content_t "${LOG_DIR}(/.*)?"
        semanage fcontext -a -t httpd_sys_rw_content_t "/var/lib/php(/.*)?"
        semanage fcontext -a -t httpd_sys_rw_content_t "/var/run/php-fpm(/.*)?"
        
        restorecon -Rv ${LOG_DIR}
        restorecon -Rv /var/lib/php
        restorecon -Rv /var/run/php-fpm
        
        # 允许PHP-FPM访问网络
        setsebool -P httpd_can_network_connect 1
        
        log_info "SELinux配置完成"
    else
        log_info "SELinux已禁用或未安装"
    fi
}

# 优化系统参数
optimize_system() {
    log_step "优化系统参数..."
    
    # 调整文件描述符限制
    cat >> /etc/security/limits.conf << EOF
* soft nofile 65535
* hard nofile 65535
${PHP_USER} soft nofile 65535
${PHP_USER} hard nofile 65535
EOF
    
    # 调整内核参数
    cat >> /etc/sysctl.conf << EOF
# PHP优化参数
net.core.somaxconn = 32768
net.ipv4.tcp_max_syn_backlog = 262144
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 0
net.ipv4.ip_local_port_range = 20000 65000
fs.file-max = 65535
EOF
    
    # 应用内核参数
    sysctl -p
    
    log_info "系统参数优化完成"
}

# 显示安装信息
show_installation_info() {
    systemctl reload php-fpm
    log_step "==================== PHP安装完成 ===================="
    echo "PHP版本: ${PHP_VERSION}"
    echo "安装目录: ${INSTALL_DIR}"
    echo "配置目录: ${CONF_DIR}"
    echo "日志目录: ${LOG_DIR}"
    echo "运行用户: ${PHP_USER}:${PHP_GROUP}"
    echo "PHP-FPM端口: ${PHP_FPM_PORT}"
    echo "服务状态: $(systemctl is-active php-fpm)"
    echo "开机自启: $(systemctl is-enabled php-fpm)"
    echo ""
    echo "配置文件:"
    echo "  php.ini: ${CONF_DIR}/php.ini"
    echo "  php-fpm.conf: ${CONF_DIR}/php-fpm.conf"
    echo "  www.conf: ${CONF_DIR}/php-fpm.d/www.conf"
    echo "  扩展配置: ${CONF_DIR}/php.d/"
    echo ""
    echo "常用命令:"
    echo "  启动: systemctl start php-fpm"
    echo "  停止: systemctl stop php-fpm"
    echo "  重启: systemctl restart php-fpm"
    echo "  重载: systemctl reload php-fpm"
    echo "  状态: systemctl status php-fpm"
    echo "  测试: ${INSTALL_DIR}/sbin/php-fpm -t"
    echo "  版本: ${INSTALL_DIR}/bin/php -v"
    echo "  模块: ${INSTALL_DIR}/bin/php -m"
    echo ""
    echo "环境变量:"
    echo "  PHP路径已添加到系统PATH"
    echo "  Composer已安装: /usr/local/bin/composer"
    echo ""
    echo "日志文件:"
    echo "  PHP-FPM错误日志: ${LOG_DIR}/fpm/error.log"
    echo "  PHP-FPM慢日志: ${LOG_DIR}/fpm/www-slow.log"
    echo "  PHP CLI错误日志: ${LOG_DIR}/cli/error.log"
    echo ""
    echo "测试脚本: ${NGINX_HTML}/phpinfo.php (仅限本地访问)"
    log_step "======================================================"
}

# 清理临时文件
cleanup() {
    log_step "清理临时文件..."
    
    if [ -d "${TMP_DIR}" ]; then
        rm -rf ${TMP_DIR}
        log_info "已清理临时目录: ${TMP_DIR}"
    fi
    
    # 清理yum缓存
    yum clean all
    
    log_info "清理完成"
}

# 主函数
main() {
    log_step "开始安装PHP ${PHP_VERSION}"
    
    # 执行安装步骤
    check_root
    check_centos_version
    create_directories
    create_php_user
    install_dependencies
    download_php_source
    compile_dependencies
    compile_php
    configure_php
    install_php_extensions
    create_systemd_service
    configure_firewall
    #统一安装SELinux,有独立的安装步骤
    # configure_selinux
    optimize_system
    start_php_fpm
    setup_php_symlinks
    # install_composer
    verify_installation
    show_installation_info
    # cleanup
    log_step "PHP ${PHP_VERSION} 安装完成!"
}

# 执行主函数
main "$@"
相关推荐
阿海5742 小时前
卸载php的shell脚本
开发语言·php
JienDa2 小时前
JienDa聊PHP:从Laravel到ThinkPHP的现代Web开发实践
前端·php·laravel
catchadmin3 小时前
PHP 8.5 容器化实战指南
开发语言·php
bleach-5 小时前
buuctf系列解题思路祥讲--[ZJCTF 2019]NiZhuanSiWei1——文件包含漏洞和伪协议的利用
安全·web安全·网络安全·php
2501_941982057 小时前
复杂消息格式自动化:图片、视频和自定义卡片的消息体构造
开发语言·php
阿海5748 小时前
卸载redis7.2.4的shell脚本
linux·redis·shell
aml258__8 小时前
一、Cisco(OSPF邻居认证机制实验:明文与加密MD5对比)251211
网络·php·路由器·思科·ospf·端口认证·明文/md5
catchadmin21 小时前
用 Laravel 官方 AI 工具提升开发效率 效率提示数倍
人工智能·php·laravel
小白勇闯网安圈1 天前
file_include、easyphp、ics-05
网络安全·php·web