资讯动态

Nginx+PHP-FPM生产配置实战:性能调优与故障排查

发布时间:2026/10/27 15:16:49 来源:尧图企业网站定制
1. 项目概述为什么PHP Web服务器配置不是“装完就跑”而是运维能力的试金石在Linux运维的实际工作中“配个PHP网站”这句话听起来轻描淡写但真正接手过生产环境的人心里都清楚它从来不是Apache或Nginx敲几行命令、改两个配置文件就能收工的事。我做过不下二十个中小企业的Web服务迁移与重构项目其中超过七成的问题根源不在代码而在于PHP运行时环境与Web服务器的耦合细节——比如某次凌晨三点被电话叫醒只因为客户官网首页显示“502 Bad Gateway”排查两小时才发现是PHP-FPM的pm.max_children设成了10而促销活动期间并发请求瞬间冲到83还有一次上线后用户上传头像失败日志里满屏failed to open stream: Permission denied最后定位到SELinux策略未放行httpd_can_network_connect而开发团队压根没在测试机开SELinux……这些都不是教科书里的“Hello World”而是真实世界里每天发生的、带着温度与压力的运维现场。这个项目标题——“Linux运维-Web服务器的配置与管理(PHP)”——表面看是技术组合实则是一条贯穿系统层、服务层、应用层的完整能力链。它要求你既看得懂/etc/php-fpm.d/www.conf里每个参数背后的内存模型也得理解nginx.conf中fastcgi_pass指向的是Unix socket还是TCP端口更得知道当upload_max_filesize和post_max_size不匹配时PHP解析器连POST数据都收不全。它不是单点技能而是Linux系统资源调度、进程管理、权限控制、网络协议、安全策略、日志分析五大能力的交汇点。适合三类人深度参考刚从培训结业、正卡在“能搭环境但不敢上生产”的新人已会基础命令、但对“为什么这样配”缺乏体系认知的中级运维以及需要快速复现稳定PHP运行栈的DevOps工程师。接下来的内容全部来自我过去十年在不同规模项目中的实操沉淀——没有理论堆砌只有参数怎么调、日志怎么看、坑怎么绕、稳怎么保。2. 整体架构设计与方案选型为什么NginxPHP-FPM是当前生产环境的黄金组合2.1 不是所有Web服务器都适合跑PHPApache mod_php vs NginxPHP-FPM的本质差异很多初学者一上来就用apt install apache2 libapache2-mod-php看似一步到位但这种“模块式”集成在生产环境早已被主流放弃。原因很实在Apache的mod_php是把PHP解释器直接编译进Apache工作进程worker process里每个HTTP请求进来Apache就得fork一个新进程或线程而这个进程里同时承载着HTTP协议解析、静态文件读取、PHP脚本执行三重任务。这意味着——哪怕你只是请求一张logo.pngApache也得加载整个PHP运行时环境白白消耗内存与CPU。我曾用ps aux --sort-%mem | head -10在一个2核4G的VPS上抓过快照开启mod_php后仅5个空闲Apache进程就占了1.2G内存换成NginxPHP-FPM后同样负载下内存占用压到380MB。这不是数字游戏而是直接影响服务器能扛多少并发、扩容成本高不高。NginxPHP-FPM走的是“解耦”路线Nginx专注做它最擅长的事——高性能HTTP请求分发、静态资源缓存、SSL终止、反向代理PHP-FPM则作为独立的FastCGI进程管理器只干一件事接收Nginx转发来的PHP脚本请求执行它再把结果HTML、JSON等吐回去。两者通过Unix socket推荐或TCP端口通信。这种分离让资源调度变得极其清晰你可以单独给PHP-FPM分配内存池pm.max_children、设置慢日志slowlog、启用动态进程管理pm dynamic而Nginx完全不受PHP内存泄漏影响。某次我们为一家电商后台升级旧架构用Apachemod_php每逢大促必OOM切换到NginxPHP-FPM后通过精细调整PHP-FPM的pm.start_servers和pm.min_spare_servers成功将峰值QPS从1200提升到3800且内存波动控制在±5%以内。2.2 PHP-FPM为何不可替代它不只是“PHP的守护进程”很多人把PHP-FPM简单理解为“让PHP支持FastCGI的工具”这严重低估了它的工程价值。PHP-FPM的核心能力远超协议转换——它是一个完整的PHP运行时生命周期管理者。举三个关键点第一进程隔离与资源硬限。PHP-FPM允许你为不同站点甚至同一站点的不同目录定义独立的pool池每个pool可配置专属的user、group、php_admin_value[open_basedir]。这意味着A客户的网站即使被注入恶意脚本也无法读取B客户/var/www/b.com下的配置文件——这是mod_php根本做不到的权限纵深防御。第二精细化的性能调控。pm ondemand模式下PHP-FPM进程只在有请求时启动空闲超时即销毁这对低流量后台服务极友好而pm static则适合高并发、长连接场景避免频繁fork开销。更关键的是request_terminate_timeout和request_slowlog_timeout——前者防止单个脚本无限循环拖垮整个池后者自动记录执行超时的脚本路径与堆栈是性能优化的黄金线索。第三原生监控接口。PHP-FPM内置status页面需Nginx配合location ~ ^/status$返回实时JSON数据active processes、max active processes、listen queue len等待队列长度。我习惯在Zabbix里每10秒抓一次这个接口一旦listen queue len持续5立刻触发告警——这比等用户投诉“网站卡”早至少8分钟。2.3 为什么放弃Apache一个被忽略的现实约束模块生态与维护成本Apache的模块生态.so文件看似丰富但实际运维中痛点极多。比如要启用mod_security做WAF你得手动编译、处理依赖冲突、定期更新规则库而Nginx可通过nginx-module-vts或nginx-plus原生集成监控或用lua-nginx-module嵌入WAF逻辑。更重要的是Apache的配置语法.htaccess允许目录级覆盖这在共享主机时代是优势但在容器化、CI/CD主导的今天却成了安全隐患与部署黑箱——开发提交的.htaccess可能悄悄关闭AllowOverride None导致Nginx配置被绕过。我们某客户就因此被利用.htaccess重写规则将所有请求302跳转到钓鱼页面而安全扫描工具因只检查Nginx主配置完全漏报。Nginx的配置是“全集中、强管控”的所有规则必须显式写在server块内这反而提升了配置审计的确定性。3. 核心配置详解与实操要点从零构建一个抗压、可监控、易排障的PHP运行栈3.1 Nginx核心配置不只是location ~ \.php$而是请求路由的精密手术刀Nginx的PHP支持配置常被简化为三行location ~ \.php$ { fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; include fastcgi_params; }但这在生产环境是危险的。真正的配置必须解决四个问题路径安全、参数透传、静态资源分流、错误兜底。以下是我在线上环境稳定运行三年的精简版模板已脱敏# /etc/nginx/conf.d/php-site.conf server { listen 80; server_name example.com; root /var/www/example.com/public; index index.php; # 【关键1】严格限制PHP脚本执行范围禁止任意路径执行 location ~ ^/index\.php(/|$) { # 【关键2】使用Unix socket而非TCP减少网络开销与端口占用 fastcgi_pass unix:/run/php/php8.1-fpm.sock; fastcgi_split_path_info ^(.\.php)(/.*)$; fastcgi_index index.php; include fastcgi_params; # 【关键3】强制透传真实客户端IP否则PHP $_SERVER[REMOTE_ADDR]全是127.0.0.1 fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; fastcgi_param DOCUMENT_ROOT $realpath_root; fastcgi_param REMOTE_ADDR $remote_addr; # 【关键4】设置超时防止单个慢请求阻塞整个worker fastcgi_read_timeout 60; fastcgi_send_timeout 60; fastcgi_connect_timeout 10; } # 【关键5】所有非PHP请求由Nginx直接处理绝不交给PHP-FPM location / { try_files $uri $uri/ /index.php?$query_string; } # 【关键6】禁止访问敏感文件Nginx层拦截不留给PHP处理 location ~ /\.(env|log|ini|conf|git|svn) { deny all; } }这里每一处“关键”都有血泪教训关键1^/index\.php(/|$)正则确保只有入口文件index.php可执行避免/uploads/evil.php这类上传文件被直接运行。曾有客户被黑客上传一句话木马到/wp-content/uploads/2023/01/shell.php因Nginx配置为location ~ \.php$该文件被直接执行导致数据库全量泄露。关键2Unix socket/run/php/php8.1-fpm.sock比127.0.0.1:9000快约15%且无端口冲突风险。注意socket文件权限PHP-FPM pool配置中listen.owner www-data、listen.group www-data、listen.mode 0660Nginx worker进程用户www-data必须属于该组才能读写。关键3$realpath_root是Nginx 1.19新增变量自动解析符号链接后的绝对路径彻底解决open_basedir误判问题。旧版本可用root /var/www/example.com/public;fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;替代但需确保$document_root与root指令一致。关键4fastcgi_read_timeout必须大于PHP脚本最大预期执行时间如max_execution_time30否则Nginx会在PHP执行完前主动断开连接返回504 Gateway Timeout。提示Nginx配置修改后务必用nginx -t语法检查再systemctl reload nginx热重载。切忌systemctl restart nginx这会导致毫秒级连接中断对高并发API服务是灾难。3.2 PHP-FPM核心参数调优内存、进程、超时的三角平衡术PHP-FPM的配置文件如/etc/php/8.1/fpm/pool.d/www.conf是性能的命脉。默认配置pm dynamic,pm.max_children 5只适合本地开发线上必须重算。调优核心是三个公式1. 内存上限决定pm.max_children单个PHP-FPM进程平均内存占用 ps aux | grep php-fpm: pool www | awk {sum$6} END {print sum/NR}单位KB假设测得为85MB服务器总内存4G预留1G给系统与Nginx则PHP-FPM可用内存≈3G →pm.max_children ≈ 3000 / 85 ≈ 35。但这是理论值必须留20%余量防突发最终设为28。2.pm.start_servers与pm.min_spare_servers的动态平衡pm.start_serverspm.min_spare_servers× 1.5经验值pm.min_spare_servers应略高于日常最低并发如监控显示最低5个活跃进程设为8→pm.start_servers 12。pm.max_spare_servers设为pm.max_children的80%即22避免空闲进程过多浪费内存。3. 超时参数必须与业务强绑定request_terminate_timeout 60s防止单个脚本无限循环如死锁、未设LIMIT的SQL。request_slowlog_timeout 5s记录所有执行5秒的请求日志路径slowlog /var/log/php8.1-fpm-slow.log。catch_workers_output yes捕获echo、var_dump输出到/var/log/php8.1-fpm.log方便调试。以下是精简后的www.conf关键段删除注释后仅12行[www] user www-data group www-data listen /run/php/php8.1-fpm.sock listen.owner www-data listen.group www-data listen.mode 0660 pm dynamic pm.max_children 28 pm.start_servers 12 pm.min_spare_servers 8 pm.max_spare_servers 22 request_terminate_timeout 60s request_slowlog_timeout 5s注意修改后必须systemctl restart php8.1-fpm因为PHP-FPM不支持reload重启会短暂中断建议在低峰期操作并提前通知业务方。3.3 PHP核心配置php.ini安全与功能的底线守卫php.ini不是越改越安全而是“最小必要原则”。我只动五个关键项参数推荐值为什么必须改expose_php OffOff防止HTTP响应头暴露X-Powered-By: PHP/8.1.2减少攻击面display_errors OffOff生产环境绝不能显示错误详情否则mysql_connect()失败会暴露数据库地址密码log_errors OnOn错误必须记录到error_log /var/log/php8.1-error.log便于追踪upload_max_filesizepost_max_size20M22M必须post_max_size upload_max_filesize否则大文件上传直接失败POST数据被截断opcache.enable 11启用OPcachePHP脚本字节码缓存提升30%执行速度opcache.memory_consumption128特别提醒open_basedir不要全局设置应在PHP-FPM pool中按站点配置。例如在/etc/php/8.1/fpm/pool.d/site-a.conf中添加php_admin_value[open_basedir] /var/www/site-a/:/tmp/这表示该站点PHP脚本只能读写/var/www/site-a/和/tmp/目录连/etc/passwd都读不到。某次渗透测试中攻击者通过include($_GET[file])尝试读取/etc/shadow因open_basedir限制返回Warning: open_basedir restriction in effect直接阻断。4. 实操全流程与关键环节实现从系统初始化到上线验证的完整闭环4.1 环境初始化Debian/Ubuntu与CentOS/RHEL的差异化处理不同发行版的包管理与路径差异极大必须区分对待。以下以Debian 12bookworm和Rocky Linux 9为例Debian 12APT源# 1. 更新并安装核心组件 sudo apt update sudo apt upgrade -y sudo apt install -y nginx php8.1-fpm php8.1-cli php8.1-mysql php8.1-curl \ php8.1-gd php8.1-mbstring php8.1-xml php8.1-zip php8.1-opcache # 2. 启用服务并禁用Apache如果存在 sudo systemctl enable nginx php8.1-fpm sudo systemctl start nginx php8.1-fpm sudo systemctl disable apache2 2/dev/null || true # 3. 验证PHP-FPM socket路径Debian系默认在/run/php/ ls -l /run/php/php8.1-fpm.sock # 应显示srw-rw---- 1 www-data www-dataRocky Linux 9DNF源# 1. 启用EPEL与PowerTools仓库 sudo dnf install -y epel-release sudo dnf config-manager --set-enabled crb # 2. 安装PHP 8.1来自remi仓库 sudo dnf install -y https://rpms.remirepo.net/enterprise/remi-release-9.rpm sudo dnf module reset php sudo dnf module enable php:remi-8.1 sudo dnf install -y nginx php-fpm php-cli php-mysqlnd php-curl \ php-gd php-mbstring php-xml php-zip php-opcache # 3. Rocky Linux的socket路径在/opt/remi/php81/root/var/run/php-fpm/ # 需在Nginx配置中改为fastcgi_pass unix:/opt/remi/php81/root/var/run/php-fpm/www.sock;关键区别Debian的PHP包名带版本号php8.1-fpmRocky Linux通过dnf module管理PHP版本socket路径也不同。若混用Nginx会报connect() to unix:/run/php/php8.1-fpm.sock failed (2: No such file or directory)。4.2 创建首个PHP站点手把手验证全链路是否通畅创建一个/var/www/test-php/index.php?php // test-php/index.php echo PHP Version: . PHP_VERSION . \n; echo Web Server: . $_SERVER[SERVER_SOFTWARE] . \n; echo Document Root: . $_SERVER[DOCUMENT_ROOT] . \n; echo Remote IP: . $_SERVER[REMOTE_ADDR] . \n; // 测试数据库连接可选 if (extension_loaded(mysqli)) { echo MySQLi extension loaded.\n; } else { echo MySQLi extension NOT loaded.\n; } // 测试OPcache if (function_exists(opcache_get_status)) { $status opcache_get_status(); echo OPcache enabled, memory used: . round($status[memory_usage][used_memory]/1024/1024, 2) . MB\n; } ?对应Nginx配置/etc/nginx/conf.d/test-php.confserver { listen 8080; server_name localhost; root /var/www/test-php; index index.php; location ~ ^/index\.php(/|$) { fastcgi_pass unix:/run/php/php8.1-fpm.sock; fastcgi_split_path_info ^(.\.php)(/.*)$; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; fastcgi_param DOCUMENT_ROOT $realpath_root; } location / { try_files $uri $uri/ 404; } }验证步骤逐层击穿curl -I http://localhost:8080/→ 检查HTTP状态码是否为200Server头是否为nginxcurl http://localhost:8080/index.php→ 输出PHP版本、Web服务器等信息sudo tail -f /var/log/nginx/error.log→ 刷新页面确认无connect() to unix:... failed错误sudo tail -f /var/log/php8.1-fpm.log→ 查看PHP-FPM是否收到请求有无WARNINGsudo ss -tuln | grep :9000→ 确认PHP-FPM未监听TCP端口我们用socketsudo lsof -U | grep php-fpm→ 确认socket文件被PHP-FPM进程持有。实操心得我习惯在/var/www/test-php/下放一个phpinfo.php内容为?php phpinfo(); ?但上线前必须rm -f phpinfo.php。曾有客户因忘记删除被搜索引擎收录暴露了disable_functions、allow_url_fopen等敏感配置成为攻击者制定绕过策略的关键情报。4.3 上线前必备的五项健康检查一个PHP站点能否上线不取决于“能打开”而取决于“能扛住、能诊断、能恢复”。我坚持执行以下检查1. 并发压力测试ab工具# 模拟50并发请求1000次 ab -n 1000 -c 50 http://localhost:8080/index.php关注指标Requests per second应200、Time per request平均100ms、Failed requests必须为0。若失败率高立即检查PHP-FPMpm.max_children是否不足。2. 日志轮转配置logrotate编辑/etc/logrotate.d/php8.1-fpm/var/log/php8.1-fpm.log /var/log/php8.1-fpm-slow.log { daily missingok rotate 14 compress delaycompress notifempty create 640 www-data www-data sharedscripts postrotate if [ -f /var/run/php/php8.1-fpm.pid ]; then kill -USR1 cat /var/run/php/php8.1-fpm.pid fi endscript }否则日志文件会无限增长某次因未配置php8.1-fpm.log涨到12GBdf -h显示根分区100%服务全挂。3. 监控接口启用PHP-FPM status在PHP-FPM pool配置中添加pm.status_path /status ping.path /ping ping.response pong并在Nginx中映射location /status { fastcgi_pass unix:/run/php/php8.1-fpm.sock; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; allow 127.0.0.1; # 仅本地访问 deny all; }访问curl http://localhost:8080/status?json返回实时JSON可接入Prometheus。4. 安全加固禁用危险函数在php.ini中设置disable_functions exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,show_source注意disable_functions会禁用整个函数族curl_exec禁用后file_get_contents(https://...)仍可用但curl_*系列全失效。某次客户支付回调失败就是因为curl_exec被禁而SDK恰好用了它。5. 备份与回滚预案Nginx配置备份sudo cp /etc/nginx/sites-enabled/* /backup/nginx-conf-$(date %Y%m%d)/PHP-FPM配置备份sudo cp /etc/php/8.1/fpm/pool.d/*.conf /backup/php-fpm-pools-$(date %Y%m%d)/数据库导出脚本每日凌晨执行mysqldump -u user -ppass dbname /backup/db-$(date %Y%m%d).sql最后一步把以上所有操作步骤、配置文件路径、验证命令整理成一份checklist.md放在项目根目录。运维不是靠记忆而是靠可重复的流程。5. 常见问题与排查技巧实录那些让你半夜惊醒的典型故障与解法5.1 “502 Bad Gateway”Nginx与PHP-FPM的通信断点定位法502错误本质是Nginx无法从PHP-FPM拿到响应。排查必须按层级推进不能跳步Step 1确认PHP-FPM进程是否存活sudo systemctl status php8.1-fpm # 看Active: active (running) sudo ps aux | grep php-fpm: master # 看master进程是否存在若进程不存在journalctl -u php8.1-fpm -n 50 --no-pager查启动失败原因常见端口被占、socket路径权限错、配置语法错。Step 2确认socket文件是否存在且可访问ls -l /run/php/php8.1-fpm.sock # 权限应为srw-rw----属主www-data sudo -u www-data ls -l /run/php/php8.1-fpm.sock # 切换到Nginx用户测试可读若权限不对sudo chown www-data:www-data /run/php/php8.1-fpm.sock。Step 3确认Nginx配置中fastcgi_pass路径与PHP-FPM监听路径一致# 查PHP-FPM监听路径 sudo grep listen /etc/php/8.1/fpm/pool.d/www.conf # 查Nginx配置 sudo grep fastcgi_pass /etc/nginx/conf.d/*.conf常见错误PHP-FPM监听127.0.0.1:9000Nginx却配unix:/run/php/...或反之。Step 4抓包验证通信终极手段# 若用TCP端口用tcpdump sudo tcpdump -i lo port 9000 -w php-fpm.pcap # 访问页面后用Wireshark分析是否有SYN包发出但无ACK返回若无任何包说明Nginx根本没尝试连接——问题在Nginx配置或路由若有SYN但无ACK说明PHP-FPM未监听或防火墙拦截。我的速查表systemctl status→ 进程状态ls -l socket→ 文件权限grep listen→ 路径一致性journalctl -u→ 启动日志四步下来95%的502问题定位完毕。5.2 “File not found”Nginx找不到PHP文件的三大元凶用户访问/index.php报404但文件明明存在。原因往往不在文件本身元凶1root指令路径错误Nginx配置中root /var/www/site;但PHP文件在/var/www/site/public/index.php。此时$document_root是/var/www/site而SCRIPT_FILENAME拼成/var/www/site/index.php自然找不到。解法root /var/www/site/public;或在location中用alias。元凶2fastcgi_param SCRIPT_FILENAME未正确拼接错误写法fastcgi_param SCRIPT_FILENAME /var/www/site$fastcgi_script_name;正确写法fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;$realpath_root会自动解析符号链接/var/www/site若是个软链$document_root可能指向错误路径。元凶3SELinux阻止Nginx读取文件仅RHEL/CentOS# 临时关闭SELinux验证 sudo setenforce 0 # 若此时正常说明是SELinux问题 sudo setenforce 1 # 永久放行 sudo setsebool -P httpd_read_user_content 1 sudo semanage fcontext -a -t httpd_sys_content_t /var/www(/.*)? sudo restorecon -Rv /var/www5.3 “上传文件失败”upload_max_filesize之外的隐藏关卡用户说“上传20MB文件失败”你查php.ini发现upload_max_filesize128Mpost_max_size130M一切正常别急还有三道门门1Nginx的client_max_body_sizeNginx默认只允许1MB POST数据必须在http、server或location块中显式设置client_max_body_size 128M;否则Nginx在PHP-FPM之前就返回413 Request Entity Too Large。门2PHP-FPM的request_terminate_timeout大文件上传耗时长若request_terminate_timeout30s上传未完成就被PHP-FPM杀掉。应设为300s5分钟。门3浏览器与中间设备超时某些企业防火墙、代理服务器对长连接有30秒超时限制。解法前端用分片上传如uppy.js后端用$_FILES[file][tmp_name]接收分片再合并。实操心得我写了一个upload-test.php用input typefile上传100MB文件同时开三个终端终端1tail -f /var/log/nginx/error.log终端2tail -f /var/log/php8.1-fpm.log终端3sudo journalctl -u nginx -f三日志联动哪一层报错一目了然。5.4 “慢查询泛滥”如何从PHP慢日志精准定位性能瓶颈PHP-FPM的slowlog是性能优化的罗盘。启用后所有执行5秒的请求会被记录格式如下[23-Oct-2023 14:22:35] [pool www] pid 12345 script_filename /var/www/app/index.php [0x00007f8b1c0a1234] mysqli_query() /var/www/app/db.php:45 [0x00007f8b1c0a5678] get_user_data() /var/www/app/user.php:12 [0x00007f8b1c0a9abc] index() /var/www/app/index.php:8关键信息script_filename哪个PHP文件慢堆栈路径mysqli_query()在db.php:45被调用说明第45行SQL有问题get_user_data()调用链说明是用户数据查询慢。优化三步法抓SQL在db.php:45附近加error_log(SQL: . $sql);看执行的是什么语句EXPLAIN分析EXPLAIN SELECT * FROM users WHERE email xxx看是否用到索引加索引ALTER TABLE users ADD INDEX idx_email (email);注意slowlog日志量巨大建议用logrotate每日切割并用awk /script_filename/ {print $0; getline; print $0} /var/log/php8.1-fpm-slow.log提取慢脚本列表快速聚焦。6. 运维进阶自动化部署、安全加固与长期维护的实战经验6.1 用Ansible实现PHP环境的一键部署附可运行playbook手工配置易错、难复现。我用Ansible管理所有PHP服务器核心playbookphp-stack.yml如下已精简--- - name: Deploy PHP Web Stack hosts: webservers become: yes vars: php_version: 8.1 web_root: /var/www/html site_name: example.com tasks: - name: Install Nginx and PHP packages apt: name: - nginx - php{{ php_version }}-fpm - php{{ php_version }}-mysql - php{{ php_version }}-curl state: present when: ansible_facts[os_family] Debian - name: Configure PHP-FPM pool template: src: templates/www.conf.j2 dest: /etc/php/{{ php_version }}/fpm/pool.d/www.conf notify: Restart PHP-FPM - name: Configure Nginx site template: src: templates/site.conf.j2 dest: /etc/nginx/conf.d/{{ site_name }}.conf notify: Reload Nginx - name: Create web root file: path: {{ web_root }} state: directory owner: www-data group: www-data mode: 0755 - name: Deploy index.php copy: src: files/index.php dest: {{ web_root }}/index.php owner: www-data group: www-data mode: 0644 handlers: - name: Restart PHP-FPM systemd: name: php{{ php_version }}-fpm state: restarted - name: Reload Nginx systemd: name: nginx state: reloaded配套模板templates/www.conf.j2[www] user www-data group www-data listen /run/php/php{{ php_version }}-fpm.sock listen.owner

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑