Linux LNMP故障排查方法
LNMP(Linux+NGINX+MySQL+PHP)架构下,故障排查需遵循从现象到根源的系统化流程,覆盖问题定位、日志分析、服务状态、资源配置等多个维度,以下是具体步骤:
首先收集用户反馈和系统告警,确定故障的具体表现(如网站无法访问、返回502/500错误、页面加载缓慢、数据库连接失败等),并记录故障发生时间、受影响的服务模块(如前端页面、API接口、数据库操作)及用户操作路径,为后续排查提供精准方向。
使用top(实时显示进程资源占用)、htop(增强版top,支持颜色和快捷键)、vmstat 1(每秒刷新系统整体状态,包括CPU、内存、I/O)、iostat -x 1(详细磁盘I/O统计,如读写延迟、利用率)等命令,检查服务器资源是否瓶颈:
%CPU持续高于80%,可能存在PHP代码性能问题(如死循环)、MySQL慢查询或大量并发请求;free -m显示可用内存不足(available列接近0),可能导致系统频繁使用swap交换分区,加剧性能下降;await(平均I/O等待时间)过高(如超过100ms),可能是磁盘硬件故障或大量日志写入;rx/tx流量异常(如突然激增),可能存在DDoS攻击或带宽耗尽。日志是故障定位的“金钥匙”,需重点检查以下组件的错误日志:
/var/log/nginx/error.log(可通过nginx -V查看--error-log-path参数确认),主要分析连接错误(如connect() failed (111: Connection refused)表示后端服务未启动)、配置错误(如directive not allowed here表示语法错误)、权限问题(如Permission denied表示文件无法访问);/var/log/php-fpm.error.log(或/var/log/php7.x-fpm.log,取决于PHP版本),主要分析PHP代码错误(如Parse error: syntax error)、进程资源耗尽(如WARNING: [pool www] server reached pm.max_children setting表示子进程数达到上限)、FastCGI通信错误(如recv() failed (104: Connection reset by peer)表示Nginx与PHP-FPM通信中断);/var/log/mysql/error.log(或/var/log/mariadb/mariadb.log),主要分析连接问题(如Access denied for user表示账号密码错误)、查询错误(如Table 'xxx' doesn't exist表示表不存在)、性能瓶颈(如InnoDB: Unable to lock xxx row表示锁等待);journalctl -xe(Systemd系统)或tail -f /var/log/messages查看系统级错误(如内核崩溃、驱动问题)。使用以下命令确认LNMP核心服务是否正常运行:
systemctl status nginx(查看服务状态,若显示active (running)则表示正常);ps aux | grep nginx(检查主进程和worker进程是否存在,若无则需重启服务);systemctl status php-fpm(确认服务运行状态);ps aux | grep php-fpm(检查master进程和子进程,若子进程数为0,可能是pm.max_children设置为0或资源不足);systemctl status mysql(查看服务状态);mysqladmin -uroot -p ping(执行ping命令,若返回mysqld is alive则表示数据库正常)。配置错误是LNMP故障的常见原因,需逐一验证以下文件的配置:
nginx.conf及站点配置文件(如/etc/nginx/conf.d/default.conf),重点确认:
listen指令的端口是否正确(如80/443);server_name是否匹配域名;fastcgi_pass指令是否指向PHP-FPM的正确地址(如unix:/run/php/php7.4-fpm.sock或127.0.0.1:9000);root指令是否指向正确的网站根目录(如/usr/share/nginx/html);php-fpm.conf及pool.d/www.conf(默认池配置),重点确认:
listen指令与Nginx的fastcgi_pass一致(如均使用/run/php/php7.4-fpm.sock);pm.max_children设置是否合理(根据服务器内存计算,如每进程占用100MB内存,1GB内存可设置为pm.max_children = 10);user和group是否与Nginx运行的用户一致(如均为www-data);my.cnf(或/etc/mysql/mysql.conf.d/mysqld.cnf),重点确认:
bind-address是否允许远程连接(如0.0.0.0表示允许所有IP,127.0.0.1仅本地访问);max_connections是否足够(如默认151,若并发连接数超过此值,需调整);innodb_buffer_pool_size是否合理(建议设置为物理内存的50%-70%,用于缓存InnoDB表数据)。若故障涉及外部访问(如网站无法通过域名访问),需使用以下命令测试网络连通性:
ping 域名或IP(检查服务器是否能正常解析域名并响应ICMP请求,若超时报错,可能是DNS问题或网络中断);traceroute 域名或IP(跟踪数据包传输路径,定位网络拥堵或路由故障节点);telnet 域名 端口(如telnet example.com 80,检查端口是否开放,若连接失败,可能是防火墙拦截或服务未监听该端口);netstat -tulnp | grep 端口(如netstat -tulnp | grep 80)或ss -tulnp | grep 端口(查看服务是否监听指定端口,若无输出,可能是服务未启动或配置错误)。Linux系统的权限设置直接影响LNMP服务的正常运行,需重点检查:
/usr/share/nginx/html)需赋予Web用户(如www-data)读写权限(chown -R www-data:www-data /usr/share/nginx/html),但避免使用777(过于宽松,存在安全风险),建议使用chmod -R 755 /usr/share/nginx/html;/var/log/nginx、/var/log/php-fpm)需允许Web用户写入(chown -R www-data:www-data /var/log/nginx);user和group与Nginx运行的用户一致(如均为www-data),避免跨用户权限问题。针对LNMP环境的高频故障,可快速应用以下解决方案:
fastcgi_pass地址是否正确;调整pm.max_children增大子进程数(如从10调整为20);查看PHP-FPM错误日志定位代码问题;php.ini中设置error_reporting = E_ALL、display_errors = On,或在代码顶部添加ini_set('display_errors', 1);),查看PHP错误日志定位具体错误;my.cnf中的bind-address是否允许远程连接;使用mysql -uroot -p 登录验证账号密码;查看max_connections设置并调整(如从151调整为300)。若故障疑似由攻击引起,需进行安全检查:
iptables -L -n(传统防火墙)或firewall-cmd --list-all(Firewalld)检查是否拦截了Nginx(80/443端口)、MySQL(3306端口)的访问;getenforce返回Enforcing),可能阻止Nginx访问网站目录,可使用setenforce 0临时关闭(测试是否解决问题),或通过chcon -R -t httpd_sys_rw_content_t /usr/share/nginx/html修改目录安全上下文;ps aux | grep -E 'nginx|php-fpm|mysql'检查是否有未知进程占用高资源,若有则终止(kill -9 PID)并排查来源。故障解决后,需详细记录以下信息:
upstream prematurely closed connection,进一步查看PHP-FPM日志发现max_children耗尽”);pm.max_children = 20并重启PHP-FPM服务”);记录的目的是为后续类似故障提供参考,提升排查效率。