How to Monitor Nginx, MySQL, PHP‑FPM and Zabbix Server with Zabbix
This guide explains how to enable status modules for Nginx, MySQL and PHP‑FPM, write Bash monitoring scripts, configure Zabbix agent user parameters, create Zabbix templates, add items, triggers and graphs, and verify monitoring of all components including the Zabbix server itself.
Monitor Nginx
Enable the
ngx_http_stub_status_module(compile Nginx with
--with-http_stub_status_module) and add a location block to the Nginx configuration:
<code>location /status {
stub_status;
}</code>Reload Nginx:
<code>systemctl reload nginx</code>Visit
http://127.0.0.1/statusto see the status page.
Parameter explanation:
Active connections: current active client connections (including waiting). accepts: total accepted connections. handled: total handled connections. requests: total client requests. Reading: connections reading request headers. Writing: connections writing responses. Waiting: idle connections waiting for a request.
Write a Bash script to extract these values:
<code>#!/bin/bash
ping() { /sbin/pidof nginx | wc -l; }
nginx_active() { curl -s "http://127.0.0.1/status" | awk '/Active/ {print $NF}'; }
reading() { curl -s "http://127.0.0.1/status" | awk '/Reading/ {print $2}'; }
writing() { curl -s "http://127.0.0.1/status" | awk '/Writing/ {print $4}'; }
waiting() { curl -s "http://127.0.0.1/status" | awk '/Waiting/ {print $6}'; }
accepts() { curl -s "http://127.0.0.1/status" | awk 'NR==3 {print $1}'; }
handled() { curl -s "http://127.0.0.1/status" | awk 'NR==3 {print $2}'; }
requests() { curl -s "http://127.0.0.1/status" | awk 'NR==3 {print $3}'; }
$1</code>Make the script executable:
<code>chmod +x /usr/lib/zabbix/alertscripts/monitor_nginx.sh</code>Add a user parameter to the Zabbix agent configuration:
<code>UserParameter=nginx.[*],/usr/lib/zabbix/alertscripts/monitor_nginx.sh $1</code>Restart the agent and test:
<code>systemctl restart zabbix-agent
zabbix_get -s 192.168.179.132 -k nginx.[ping]</code>Create Nginx Monitoring Template
Link the template to the host, add items (e.g.,
nginx.ping), create triggers and graphs as shown in the screenshots.
Monitor MySQL
Retrieve MySQL status with:
<code>mysqladmin -uroot -proot extended-status
mysqladmin -uroot -proot status</code>To avoid plain‑text passwords, store credentials in a MySQL option file and run:
<code>mysqladmin --defaults-extra-file=/etc/my.cnf status</code>Two script approaches are provided. Below is the first Bash script:
<code>#!/bin/bash
MYSQL_USER='root'
MYSQL_PWD='root'
MYSQL_HOST='192.168.179.132'
MYSQL_PORT='3306'
MYSQL_CONN="/usr/local/mysql/bin/mysqladmin -u${MYSQL_USER} -p${MYSQL_PWD} -h${MYSQL_HOST} -P${MYSQL_PORT}"
if [ $# -ne 1 ]; then
echo "arg error!"
exit 1
fi
case $1 in
Uptime) result=`${MYSQL_CONN} status | cut -f2 -d":" | cut -f1 -d"T"`; echo $result;;
Com_update) result=`${MYSQL_CONN} extended-status | grep -w "Com_update" | cut -d"|" -f3`; echo $result;;
Slow_queries) result=`${MYSQL_CONN} status | cut -f5 -d":" | cut -f1 -d"O"`; echo $result;;
Com_select) result=`${MYSQL_CONN} extended-status | grep -w "Com_select" | cut -d"|" -f3`; echo $result;;
Com_rollback) result=`${MYSQL_CONN} extended-status | grep -w "Com_rollback" | cut -d"|" -f3`; echo $result;;
Questions) result=`${MYSQL_CONN} status | cut -f4 -d":" | cut -f1 -d"S"`; echo $result;;
Com_insert) result=`${MYSQL_CONN} extended-status | grep -w "Com_insert" | cut -d"|" -f3`; echo $result;;
Com_delete) result=`${MYSQL_CONN} extended-status | grep -w "Com_delete" | cut -d"|" -f3`; echo $result;;
Com_commit) result=`${MYSQL_CONN} extended-status | grep -w "Com_commit" | cut -d"|" -f3`; echo $result;;
Bytes_sent) result=`${MYSQL_CONN} extended-status | grep -w "Bytes_sent" | cut -d"|" -f3`; echo $result;;
Bytes_received) result=`${MYSQL_CONN} extended-status | grep -w "Bytes_received" | cut -d"|" -f3`; echo $result;;
Com_begin) result=`${MYSQL_CONN} extended-status | grep -w "Com_begin" | cut -d"|" -f3`; echo $result;;
*) echo "Usage:$0(Uptime|Com_update|Slow_queries|Com_select|Com_rollback|Questions|Com_insert|Com_delete|Com_commit|Bytes_sent|Bytes_received|Com_begin)";;
esac</code>Make it executable:
<code>chmod +x /usr/lib/zabbix/alertscripts/monitor_mysql.sh</code>Add user parameters to
/etc/zabbix/zabbix_agentd.d/userparameter_mysql.conf:
<code>UserParameter=mysql.status[*],/usr/lib/zabbix/alertscripts/monitor_mysql.sh $1
UserParameter=mysql.ping,/usr/local/mysql/bin/mysqladmin -uroot -proot ping 2>/dev/null | grep -c alive
UserParameter=mysql.slave,mysql -uroot -proot -e 'show slave status\G' 2>/dev/null | grep -E "Slave_IO_Running|Slave_SQL_Running" | awk '{print $2}' | grep -c Yes</code>Restart the agent and test:
<code>systemctl restart zabbix-agent
zabbix_get -s 192.168.179.132 -k mysql.ping
zabbix_get -s 192.168.179.132 -k mysql.[Uptime]</code>Monitor PHP‑FPM
Enable status in
/usr/local/php/etc/php-fpm.d/www.conf:
<code>pm.status_path = /php_status</code>Uncomment the PID line in
/usr/local/php/etc/php-fpm.conf:
<code>pid = run/php-fpm.pid</code>Reload PHP‑FPM:
<code>kill -USR2 `cat /usr/local/php/var/run/php-fpm.pid`</code>Add a location to Nginx for the status page:
<code>location ~ ^/(php_status|ping)$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /usr/share/nginx/html$fastcgi_script_name;
include fastcgi_params;
}</code>Reload Nginx and test:
<code>systemctl reload nginx
curl 127.0.0.1/php_status
curl 127.0.0.1/php_status?full</code>PHP‑FPM status parameters:
pool, process manager, start time, start since, accepted conn, listen queue, max listen queue, listen queue len, idle processes, active processes, total processes, max active processes, max children reached, slow requests.
Full detail (XML output) parameters:
pid, state, start time, start since, requests, request duration, request method, request URI, content length, user, script, last request cpu, last request memory.
Add user parameters for PHP‑FPM to
/etc/zabbix/zabbix_agentd.d/userparameter_mysql.conf:
<code>UserParameter=php-fpm.status[*],/usr/bin/curl -s "http://127.0.0.1/php_status?xml" | grep "<$1>" | cut -d '>' -f2 | cut -d '<' -f1
UserParameter=php-fpm.ping,/sbin/pidof php-fpm | wc -l
UserParameter=php-fpm.version,/usr/local/php/sbin/php-fpm -v | awk 'NR==1{print $1,$2}'</code>Restart the agent and verify:
<code>systemctl restart zabbix-agent
zabbix_get -s 192.168.179.132 -k php-fpm.ping</code>Monitor Zabbix Server
Zabbix already provides a template for monitoring the server itself; simply link the Zabbix‑server template to the host. No additional Zabbix‑agent template is required because it is already linked to the OS template.
All templates and scripts referenced in this article are available on GitHub:
https://github.com/zhouhua-amei/zabbix/
Feel free to join the discussion and share your experience.
Ops Development Stories
Maintained by a like‑minded team, covering both operations and development. Topics span Linux ops, DevOps toolchain, Kubernetes containerization, monitoring, log collection, network security, and Python or Go development. Team members: Qiao Ke, wanger, Dong Ge, Su Xin, Hua Zai, Zheng Ge, Teacher Xia.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.