保存文件: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 "$@"