Skip to content

Commit 88401e3

Browse files
committed
Add php-fpm-healthcheck script
1 parent 0461efc commit 88401e3

File tree

4 files changed

+172
-0
lines changed

4 files changed

+172
-0
lines changed

.circleci/config.yml

Whitespace-only changes.

Makefile

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
qa: lint test
2+
3+
mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST)))
4+
current_dir := $(abspath $(patsubst %/,%,$(dir $(mkfile_path))))
5+
6+
.PHONY: *
7+
8+
lint:
9+
docker run --rm -v ${current_dir}:/mnt:ro koalaman/shellcheck ./php-fpm-healthcheck
10+
11+
test:
12+
test -f php-fpm-healthcheck

README.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# A PHP fpm Health Check script
2+
3+
With the ascension of containerized applications it becomes more and more useful to have a php-fpm `healthcheck`.
4+
5+
This POSIX compliant sh script gets php-fpm status page using `cgi-fcgi` tool, parses it's outcome and allows you to choose a metric which you want to check one, a ping mode is also available which only makes sure php-fpm is answering.
6+
7+
## Installation
8+
9+
### Download
10+
11+
```sh
12+
curl -L -o /usr/local/bin/php-fpm-healthcheck \
13+
https://raw.githubusercontent.com/renatomefi/php-fpm-healthcheck/master/php-fpm-healthcheck
14+
```
15+
16+
### Update
17+
18+
```sh
19+
curl -L -o $(which php-fpm-healthcheck) \
20+
https://raw.githubusercontent.com/renatomefi/php-fpm-healthcheck/master/php-fpm-healthcheck
21+
```
22+
23+
### Manually
24+
25+
You can always of course manually [download](https://raw.githubusercontent.com/renatomefi/php-fpm-healthcheck/master/php-fpm-healthcheck) and maintain the file, as long as you follow the [MIT License](./LICENSE)
26+
27+
## Why POSIX sh
28+
29+
Most of the containers contain limited software installed, using POSIX sh aims to be compatible with most of the OS images around.
30+
31+
## Author
32+
33+
Made with love by [Renato Mefi](https://github.com/renatomefi)

php-fpm-healthcheck

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
#!/bin/sh
2+
# vim: set filetype=sh :
3+
4+
# Author: <Renato Mefi [email protected]> https://github.com/renatomefi
5+
# The original code lives in https://github.com/renatomefi/php-fpm-healthcheck
6+
#
7+
# A POSIX compliant shell script to healthcheck PHP fpm status, can be used only for pinging the status page
8+
# or check for specific metrics
9+
#
10+
# i.e.: ./php-fpm-healthcheck --verbose --active-processes=6
11+
# The script will fail in case the 'active processes' is bigger than 6.
12+
#
13+
# You can combine multiple options as well, the first one to fail will fail the healthcheck
14+
# i.e.: ./php-fpm-healthcheck --listen-queue-len=10 --active-processes=6
15+
#
16+
# Ping mode (exit 0 if php-fpm returned data): ./php-fpm-healthcheck
17+
#
18+
# Ping mode with data (outputs php-fpm status text): ./php-fpm-healthcheck -v
19+
#
20+
# Exit status codes:
21+
# 9 - Couldn't reach PHP fpm status page, have you configured it with `pm.status_path = /status`?
22+
# 1 - A healthcheck condition has failed
23+
# 3 - Invalid option given
24+
# 4 - One or more required softwares are missing
25+
#
26+
# Available options:
27+
# -v|--verbose
28+
#
29+
# Metric options, fails in case the CURRENT VALUE is bigger than the GIVEN VALUE
30+
# --accepted-conn=n
31+
# --listen-queue-len=n
32+
# --active-processes=n
33+
# --slow-requests=n
34+
#
35+
36+
set -euo pipefail
37+
38+
OPTIND=1 # Reset getopt in case it has been used previously in the shell
39+
40+
# FastCGI variables
41+
export REQUEST_METHOD="GET"
42+
export SCRIPT_NAME="/status"
43+
export SCRIPT_FILENAME="/status"
44+
FCGI_CONNECT_DEFAULT="localhost:9000"
45+
46+
# Required software
47+
command -v cgi-fcgi 1> /dev/null || { >&2 echo "Make sure fcgi is installed (i.e. apk add --no-cache fcgi). Aborting."; exit 4; }
48+
command -v sed 1> /dev/null || { >&2 echo "Make sure sed is installed (i.e. apk add --no-cache busybox). Aborting."; exit 4; }
49+
command -v tail 1> /dev/null || { >&2 echo "Make sure tail is installed (i.e. apk add --no-cache busybox). Aborting."; exit 4; }
50+
command -v grep 1> /dev/null || { >&2 echo "Make sure grep is installed (i.e. apk add --no-cache grep). Aborting."; exit 4; }
51+
52+
# Get status from fastcgi connection
53+
# $1 - cgi-fcgi connect argument
54+
get_fpm_status() {
55+
if test "$VERBOSE" = 1; then printf "Trying to connect to php-fpm via: %s\\n" "$1"; fi;
56+
57+
if test ! -z "$FPM_STATUS"; then
58+
FPM_STATUS=$(cgi-fcgi -bind -connect "$1" | tail +5)
59+
fi;
60+
61+
if test "$VERBOSE" = 1; then printf "php-fpm status output:\\n%s\\n" "$FPM_STATUS"; fi;
62+
}
63+
64+
# $1 - fpm option
65+
# $2 - expected value threshold
66+
check_fpm_health_by() {
67+
OPTION=$(echo "$1" | sed 's/--//g; s/-/ /g;')
68+
VALUE_EXPECTED="$2";
69+
VALUE_ACTUAL=$(echo "$FPM_STATUS" | grep "^$OPTION" | cut -d: -f2 | sed 's/ //g')
70+
71+
if test "$VERBOSE" = 1; then printf "'%s' value is: '%s' and expected is less than: '%s'\\n" "$OPTION" "$VALUE_ACTUAL" "$VALUE_EXPECTED"; fi;
72+
73+
if test "$VALUE_ACTUAL" -gt "$VALUE_EXPECTED"; then
74+
>&2 printf "'%s' value '%s' is greater than expected '%s'\\n" "$OPTION" "$VALUE_ACTUAL" "$VALUE_EXPECTED";
75+
exit 1;
76+
fi;
77+
}
78+
79+
PARAM_AMOUNT=0
80+
81+
# $1 - fpm option
82+
# $2 - expected value threshold
83+
check_later() {
84+
# The POSIX sh way to check if it's an integer, also the output is supressed since it's polution
85+
if ! test "$2" -eq "$2" 2> /dev/null; then
86+
>&2 printf "'%s' option value must be an integer, '%s' given\\n" "$1" "$2"; exit 3;
87+
fi
88+
89+
PARAM_AMOUNT=$(( PARAM_AMOUNT + 1 ))
90+
91+
eval "PARAM_TO_CHECK$PARAM_AMOUNT=$1"
92+
eval "VALUE_TO_CHECK$PARAM_AMOUNT=$2"
93+
}
94+
95+
# From the PARAM_TO_CHECK/VALUE_TO_CHECK magic variables, do all the checks
96+
check_fpm_health() {
97+
j=1
98+
while [ $j -le $PARAM_AMOUNT ]; do
99+
eval "CURRENT_PARAM=\$PARAM_TO_CHECK$j"
100+
eval "CURRENT_VALUE=\$VALUE_TO_CHECK$j"
101+
check_fpm_health_by "$CURRENT_PARAM" "$CURRENT_VALUE"
102+
j=$(( j + 1 ))
103+
done
104+
}
105+
106+
GETOPT=$(getopt -o v --long verbose,accepted-conn:,listen-queue-len:,active-processes:,slow-requests: -n 'php-fpm-healthcheck' -- "$@")
107+
108+
if test "$?" != 0; then >&2 echo "Invalid options, terminating." ; exit 3 ; fi
109+
110+
FCGI_CONNECT="${FCGI_CONNECT:-$FCGI_CONNECT_DEFAULT}"
111+
112+
eval set -- "$GETOPT"
113+
114+
VERBOSE=0
115+
116+
while test "$1"; do
117+
case "$1" in
118+
-v|--verbose ) VERBOSE=1; shift ;;
119+
--) shift ; break ;;
120+
* ) check_later "$1" "$2"; shift 2 ;;
121+
esac
122+
done
123+
124+
FPM_STATUS=false
125+
126+
get_fpm_status "$FCGI_CONNECT"
127+
check_fpm_health

0 commit comments

Comments
 (0)