2019-08-12 14:22:49 +02:00
#!/bin/bash
#Ramil Valitov ramilvalitov@gmail.com
#https://github.com/rvalitov/zabbix-php-fpm
2019-12-19 12:02:16 +01:00
#This script scans local machine for active PHP-FPM pools and returns them as a list in JSON format
2019-08-12 14:22:49 +02:00
2020-07-06 21:43:19 +02:00
# This parameter is used to limit the execution time of this script.
# Zabbix allows us to use a script that runs no more than 3 seconds by default. This option can be adjusted in settings:
# see Timeout option https://www.zabbix.com/forum/zabbix-help/1284-server-agentd-timeout-parameter-in-config
# So, we need to stop and save our state in case we need more time to run.
2020-07-07 14:37:07 +02:00
# This parameter sets the maximum number of milliseconds that the script is allowed to run.
2020-07-06 21:43:19 +02:00
# After this duration is reached, the script will stop running and save its state.
# So, the actual execution time will be slightly more than this parameter.
2020-07-07 14:37:07 +02:00
# We put value equivalent to 1.5 seconds here.
2020-09-21 00:49:37 +02:00
# Allowed minimum value is 1 second, maximum value is 30 seconds (defined by Zabbix).
2020-07-07 14:37:07 +02:00
MAX_EXECUTION_TIME = "1500"
2020-06-28 17:18:43 +02:00
#Status path used in calls to PHP-FPM
STATUS_PATH = "/php-fpm-status"
#Debug mode is disabled by default
DEBUG_MODE = ""
2020-07-06 21:43:19 +02:00
#Use sleep for testing timeouts, disabled by default. Can be used for testing & debugging
USE_SLEEP_TIMEOUT = ""
2020-06-28 17:18:43 +02:00
2020-07-06 21:43:19 +02:00
#Sleep timeout in seconds
2020-07-07 05:27:30 +02:00
SLEEP_TIMEOUT = "0.5"
2020-06-28 17:18:43 +02:00
2020-08-05 22:59:19 +02:00
#Parent directory where all cache files are located in the OS
CACHE_ROOT = "/var/cache"
#Name of the private directory to store the cache files
CACHE_DIR_NAME = "zabbix-php-fpm"
#Full path to directory to store cache files
CACHE_DIRECTORY = " $CACHE_ROOT / $CACHE_DIR_NAME "
2020-09-21 00:49:37 +02:00
#Maximum number of tasks allowed to be run in parallel
MAX_PARALLEL_TASKS = 10
2020-09-21 12:44:06 +02:00
# Separator that is used internally in array.
# This is only a single character that should not be distinct and not in a list of characters allowed in:
# PHP-FPM pool name
# domain name
# IP address, port, and colon (:)
ARRAY_SEPARATOR = ";"
2020-06-28 17:18:43 +02:00
#Checking all the required executables
2020-02-06 23:11:57 +01:00
S_PS = $( type -P ps)
S_GREP = $( type -P grep)
S_AWK = $( type -P awk)
S_SORT = $( type -P sort)
2020-06-29 13:32:31 +02:00
S_UNIQ = $( type -P uniq)
2020-02-06 23:11:57 +01:00
S_HEAD = $( type -P head)
S_LSOF = $( type -P lsof)
S_JQ = $( type -P jq)
S_DIRNAME = $( type -P dirname)
S_CAT = $( type -P cat)
S_BASH = $( type -P bash)
S_PRINTF = $( type -P printf )
S_WHOAMI = $( type -P whoami)
2020-07-06 21:43:19 +02:00
S_DATE = $( type -P date)
S_BC = $( type -P bc)
S_SLEEP = $( type -P sleep)
2020-07-07 00:05:11 +02:00
S_FCGI = $( type -P cgi-fcgi)
2019-08-12 14:22:49 +02:00
2020-07-06 23:22:29 +02:00
if [ [ ! -x $S_PS ] ] ; then
2020-07-06 23:26:28 +02:00
echo "Utility 'ps' not found. Please, install it first."
2020-02-06 23:11:57 +01:00
exit 1
2019-08-12 14:22:49 +02:00
fi
2020-07-06 23:22:29 +02:00
if [ [ ! -x $S_GREP ] ] ; then
2020-07-06 23:26:28 +02:00
echo "Utility 'grep' not found. Please, install it first."
2020-02-06 23:11:57 +01:00
exit 1
2019-08-12 14:22:49 +02:00
fi
2020-07-06 23:22:29 +02:00
if [ [ ! -x $S_AWK ] ] ; then
2020-07-06 23:26:28 +02:00
echo "Utility 'awk' not found. Please, install it first."
2020-02-06 23:11:57 +01:00
exit 1
2019-08-12 14:22:49 +02:00
fi
2020-07-06 23:22:29 +02:00
if [ [ ! -x $S_SORT ] ] ; then
2020-07-06 23:26:28 +02:00
echo "Utility 'sort' not found. Please, install it first."
2020-02-06 23:11:57 +01:00
exit 1
2019-08-12 14:22:49 +02:00
fi
2020-07-06 23:22:29 +02:00
if [ [ ! -x $S_UNIQ ] ] ; then
2020-07-06 23:26:28 +02:00
echo "Utility 'uniq' not found. Please, install it first."
2020-06-29 13:32:31 +02:00
exit 1
fi
2020-07-06 23:22:29 +02:00
if [ [ ! -x $S_HEAD ] ] ; then
2020-07-06 23:26:28 +02:00
echo "Utility 'head' not found. Please, install it first."
2020-02-06 23:11:57 +01:00
exit 1
2019-08-12 14:22:49 +02:00
fi
2020-07-06 23:22:29 +02:00
if [ [ ! -x $S_LSOF ] ] ; then
2020-07-06 23:26:28 +02:00
echo "Utility 'lsof' not found. Please, install it first."
2020-02-06 23:11:57 +01:00
exit 1
2019-08-12 14:22:49 +02:00
fi
2020-07-06 23:22:29 +02:00
if [ [ ! -x $S_JQ ] ] ; then
2020-07-06 23:26:28 +02:00
echo "Utility 'jq' not found. Please, install it first."
2020-02-06 23:11:57 +01:00
exit 1
2020-01-17 19:47:39 +01:00
fi
2020-09-21 01:24:53 +02:00
if [ [ ! -x $S_DIRNAME ] ] ; then
2020-07-06 23:26:28 +02:00
echo "Utility 'dirname' not found. Please, install it first."
2020-02-06 23:11:57 +01:00
exit 1
2020-01-17 19:47:39 +01:00
fi
2020-09-21 01:24:53 +02:00
if [ [ ! -x $S_CAT ] ] ; then
2020-07-06 23:26:28 +02:00
echo "Utility 'cat' not found. Please, install it first."
2020-02-06 23:11:57 +01:00
exit 1
2020-01-17 19:47:39 +01:00
fi
2020-09-21 01:24:53 +02:00
if [ [ ! -x $S_BASH ] ] ; then
2020-07-06 23:26:28 +02:00
echo "Utility 'bash' not found. Please, install it first."
2020-02-06 23:11:57 +01:00
exit 1
2020-01-17 19:47:39 +01:00
fi
2020-09-21 01:24:53 +02:00
if [ [ ! -x $S_PRINTF ] ] ; then
2020-07-06 23:26:28 +02:00
echo "Utility 'printf' not found. Please, install it first."
2020-02-06 23:11:57 +01:00
exit 1
2019-08-13 10:32:59 +02:00
fi
2020-09-21 01:24:53 +02:00
if [ [ ! -x $S_WHOAMI ] ] ; then
2020-07-06 23:26:28 +02:00
echo "Utility 'whoami' not found. Please, install it first."
2020-02-06 23:11:57 +01:00
exit 1
2020-01-18 21:04:28 +01:00
fi
2020-09-21 01:24:53 +02:00
if [ [ ! -x $S_DATE ] ] ; then
2020-07-06 23:26:28 +02:00
echo "Utility 'date' not found. Please, install it first."
2020-07-06 21:43:19 +02:00
exit 1
fi
2020-07-06 23:22:29 +02:00
if [ [ ! -x $S_BC ] ] ; then
2020-07-06 23:26:28 +02:00
echo "Utility 'bc' not found. Please, install it first."
2020-07-06 21:43:19 +02:00
exit 1
fi
2020-07-06 23:22:29 +02:00
if [ [ ! -x $S_SLEEP ] ] ; then
2020-07-06 23:26:28 +02:00
echo "Utility 'sleep' not found. Please, install it first."
2020-07-06 21:43:19 +02:00
exit 1
fi
2020-07-07 00:05:11 +02:00
if [ [ ! -x $S_FCGI ] ] ; then
2020-09-20 20:10:42 +02:00
echo "Utility 'cgi-fcgi' not found. Please, install it first. The required package's name depends on your OS type and version and can be 'libfcgi-bin' or 'libfcgi0ldbl' or 'fcgi'."
2020-07-07 00:05:11 +02:00
exit 1
fi
2020-07-06 21:43:19 +02:00
2020-07-21 05:26:29 +02:00
if [ [ " ${ BASH_VERSINFO :- 0 } " -lt 4 ] ] ; then
2020-09-21 01:24:53 +02:00
echo "This script requires bash version 4.x or newer. Older version detected."
2020-07-21 05:26:29 +02:00
exit 1
fi
2020-08-05 22:59:19 +02:00
if [ [ ! -d " $CACHE_ROOT " ] ] ; then
2020-09-21 01:24:53 +02:00
echo " The OS cache directory ' $CACHE_ROOT ' not found in the system. "
2020-08-05 22:59:19 +02:00
exit 1
fi
2020-09-14 17:39:58 +02:00
USER_ID = $( id -u)
if [ [ $USER_ID -ne 0 ] ] ; then
echo "Insufficient privileges. This script must be run under 'root' user or with 'sudo'."
exit 1
fi
2020-08-05 22:59:19 +02:00
function createCacheDirectory( ) {
if [ [ ! -d " $CACHE_DIRECTORY " ] ] ; then
mkdir " $CACHE_DIRECTORY "
fi
if [ [ ! -d " $CACHE_DIRECTORY " ] ] ; then
return 1
fi
chmod 700 " $CACHE_DIRECTORY "
return 0
}
createCacheDirectory
EXIT_CODE = $?
2020-09-21 01:24:53 +02:00
if [ [ $EXIT_CODE -ne 0 ] ] ; then
echo " Failed to create cache directory ' $CACHE_DIRECTORY '. "
2020-08-05 22:59:19 +02:00
exit 1
fi
2020-07-06 21:43:19 +02:00
#Local directory
2020-09-21 01:24:53 +02:00
LOCAL_DIR = $( $S_DIRNAME " $0 " )
2020-07-06 21:43:19 +02:00
#Cache file for pending pools, used to store execution state
#File format:
#<pool name> <socket or TCP>
2020-08-05 22:59:19 +02:00
PENDING_FILE = " $CACHE_DIRECTORY /php_fpm_pending.cache "
2020-07-06 21:43:19 +02:00
#Cache file with list of active pools, used to store execution state
#File format:
#<pool name> <socket or TCP> <pool manager type>
2020-08-05 22:59:19 +02:00
RESULTS_CACHE_FILE = " $CACHE_DIRECTORY /php_fpm_results.cache "
2020-07-06 21:43:19 +02:00
#Path to status script, another script of this bundle
STATUS_SCRIPT = " $LOCAL_DIR /zabbix_php_fpm_status.sh "
#Start time of the script
2020-07-07 14:37:07 +02:00
START_TIME = $( $S_DATE +%s%N)
2019-08-12 14:22:49 +02:00
2020-09-21 01:24:53 +02:00
ACTIVE_USER = $( $S_WHOAMI )
2019-12-19 12:02:16 +01:00
# Prints a string on screen. Works only if debug mode is enabled.
2020-02-06 23:11:57 +01:00
function PrintDebug( ) {
if [ [ -n $DEBUG_MODE ] ] && [ [ -n $1 ] ] ; then
2020-07-06 23:26:28 +02:00
echo " $1 "
2020-02-06 23:11:57 +01:00
fi
2019-12-19 12:02:16 +01:00
}
2020-09-21 14:11:00 +02:00
function getPoolManagerByCode( ) {
local MANAGER_CODE = $1
local $PROCESS_MANAGER
if [ [ $MANAGER_CODE -eq 1 ] ] ; then
PROCESS_MANAGER = "dynamic"
elif [ [ $MANAGER_CODE -eq 2 ] ] ; then
PROCESS_MANAGER = "static"
elif [ [ $MANAGER_CODE -eq 3 ] ] ; then
PROCESS_MANAGER = "ondemand"
else
PROCESS_MANAGER = ""
fi
echo $PROCESS_MANAGER
}
2020-01-17 19:47:39 +01:00
# Encodes input data to JSON and saves it to result string
# Input arguments:
# - pool name
# - pool socket
# Function returns 1 if all OK, and 0 otherwise.
2020-02-06 23:11:57 +01:00
function EncodeToJson( ) {
2020-07-29 03:16:44 +02:00
local POOL_NAME = $1
local POOL_SOCKET = $2
2020-09-21 01:24:53 +02:00
if [ [ -z $POOL_NAME ] ] || [ [ -z $POOL_SOCKET ] ] ; then
2020-02-06 23:11:57 +01:00
return 0
fi
2020-01-17 19:47:39 +01:00
2020-07-29 03:16:44 +02:00
local JSON_POOL
2020-09-21 01:24:53 +02:00
JSON_POOL = $( echo -n " $POOL_NAME " | $S_JQ -aR .)
2020-07-29 03:16:44 +02:00
local JSON_SOCKET
2020-09-21 01:24:53 +02:00
JSON_SOCKET = $( echo -n " $POOL_SOCKET " | $S_JQ -aR .)
if [ [ $POOL_FIRST = = 1 ] ] ; then
2020-02-06 23:11:57 +01:00
RESULT_DATA = " $RESULT_DATA , "
fi
RESULT_DATA = " $RESULT_DATA {\"{#POOLNAME}\": $JSON_POOL ,\"{#POOLSOCKET}\": $JSON_SOCKET } "
POOL_FIRST = 1
return 1
2020-01-17 19:47:39 +01:00
}
2020-07-06 21:43:19 +02:00
# Updates information about the pool in cache.
2020-01-17 19:47:39 +01:00
# Input arguments:
# - pool name
# - pool socket
2020-07-06 21:43:19 +02:00
# - pool type
function UpdatePoolInCache( ) {
2020-07-29 03:16:44 +02:00
local POOL_NAME = $1
local POOL_SOCKET = $2
local POOL_TYPE = $3
local UNSET_USED = ""
2020-07-06 21:43:19 +02:00
if [ [ -z $POOL_NAME ] ] || [ [ -z $POOL_SOCKET ] ] || [ [ -z $POOL_TYPE ] ] ; then
PrintDebug "Error: Invalid arguments for UpdatePoolInCache"
2020-01-17 19:47:39 +01:00
return 0
2020-02-06 23:11:57 +01:00
fi
2020-07-06 21:43:19 +02:00
for ITEM_INDEX in " ${ !CACHE[@] } " ; do
2020-07-29 03:16:44 +02:00
local CACHE_ITEM = " ${ CACHE [ $ITEM_INDEX ] } "
local ITEM_NAME
2020-02-06 23:11:57 +01:00
# shellcheck disable=SC2016
2020-09-21 12:44:06 +02:00
ITEM_NAME = $( echo " $CACHE_ITEM " | $S_AWK -F " $ARRAY_SEPARATOR " '{print $1}' )
2020-07-29 03:16:44 +02:00
local ITEM_SOCKET
2020-02-06 23:11:57 +01:00
# shellcheck disable=SC2016
2020-09-21 12:44:06 +02:00
ITEM_SOCKET = $( echo " $CACHE_ITEM " | $S_AWK -F " $ARRAY_SEPARATOR " '{print $2}' )
2020-07-29 03:16:44 +02:00
local ITEM_POOL_TYPE
2020-07-06 21:43:19 +02:00
# shellcheck disable=SC2016
2020-09-21 12:44:06 +02:00
ITEM_POOL_TYPE = $( echo " $CACHE_ITEM " | $S_AWK -F " $ARRAY_SEPARATOR " '{print $3}' )
2020-09-21 01:10:09 +02:00
2020-07-06 21:43:19 +02:00
if [ [ $ITEM_NAME = = " $POOL_NAME " && $ITEM_SOCKET = = " $POOL_SOCKET " ] ] || [ [ -z $ITEM_POOL_TYPE ] ] ; then
PrintDebug " Pool $POOL_NAME $POOL_SOCKET is in cache, deleting... "
#Deleting the pool first
2020-07-29 03:16:44 +02:00
unset " CACHE[ $ITEM_INDEX ] "
UNSET_USED = "1"
2020-07-06 21:43:19 +02:00
fi
done
2020-07-29 03:16:44 +02:00
if [ [ -n " $UNSET_USED " ] ] ; then
#Renumber the indexes
CACHE = ( " ${ CACHE [@] } " )
fi
2020-09-21 12:44:06 +02:00
CACHE += ( " $POOL_NAME $ARRAY_SEPARATOR $POOL_SOCKET $ARRAY_SEPARATOR $POOL_TYPE " )
2020-07-06 21:43:19 +02:00
PrintDebug " Added pool $POOL_NAME $POOL_SOCKET to cache list "
return 0
}
# Removes pools from cache that are currently inactive and are missing in pending list
function UpdateCacheList( ) {
2020-07-29 03:16:44 +02:00
local UNSET_USED = ""
2020-07-06 21:43:19 +02:00
for ITEM_INDEX in " ${ !CACHE[@] } " ; do
2020-07-29 03:16:44 +02:00
local CACHE_ITEM = " ${ CACHE [ $ITEM_INDEX ] } "
local ITEM_NAME
2020-07-06 21:43:19 +02:00
# shellcheck disable=SC2016
2020-09-21 12:44:06 +02:00
ITEM_NAME = $( echo " $CACHE_ITEM " | $S_AWK -F " $ARRAY_SEPARATOR " '{print $1}' )
2020-07-29 03:16:44 +02:00
local ITEM_SOCKET
2020-07-06 21:43:19 +02:00
# shellcheck disable=SC2016
2020-09-21 12:44:06 +02:00
ITEM_SOCKET = $( echo " $CACHE_ITEM " | $S_AWK -F " $ARRAY_SEPARATOR " '{print $2}' )
2020-07-29 03:16:44 +02:00
local ITEM_POOL_TYPE
2020-07-06 21:43:19 +02:00
# shellcheck disable=SC2016
2020-09-21 12:44:06 +02:00
ITEM_POOL_TYPE = $( echo " $CACHE_ITEM " | $S_AWK -F " $ARRAY_SEPARATOR " '{print $3}' )
2020-07-06 21:43:19 +02:00
if [ [ $ITEM_NAME = = " $POOL_NAME " && $ITEM_SOCKET = = " $POOL_SOCKET " ] ] || [ [ -z $ITEM_POOL_TYPE ] ] ; then
PrintDebug " Pool $POOL_NAME $POOL_SOCKET is in cache, deleting... "
#Deleting the pool first
2020-07-29 03:16:44 +02:00
unset " CACHE[ $ITEM_INDEX ] "
UNSET_USED = "1"
2020-07-06 21:43:19 +02:00
fi
done
2020-07-29 03:16:44 +02:00
if [ [ -n " $UNSET_USED " ] ] ; then
#Renumber the indexes
CACHE = ( " ${ CACHE [@] } " )
fi
2020-07-06 21:43:19 +02:00
}
# Checks if selected pool is in pending list
# Function returns 1 if pool is in list, and 0 otherwise
function IsInPendingList( ) {
2020-07-29 03:16:44 +02:00
local POOL_NAME = $1
local POOL_SOCKET = $2
2020-07-06 21:43:19 +02:00
if [ [ -z $POOL_NAME ] ] || [ [ -z $POOL_SOCKET ] ] ; then
PrintDebug "Error: Invalid arguments for IsInPendingList"
return 0
fi
for ITEM in " ${ PENDING_LIST [@] } " ; do
if [ [ " $ITEM " = = " $POOL_NAME $POOL_SOCKET " ] ] ; then
2020-02-06 23:11:57 +01:00
return 1
fi
done
return 0
2020-01-17 19:47:39 +01:00
}
2020-07-06 21:43:19 +02:00
# Adds a pool to the pending list
# The pool is added only if it's not already in the list.
# A new pool is added to the end of the list.
# Function returns 1, if a pool was added, and 0 otherwise.
function AddPoolToPendingList( ) {
2020-07-29 03:16:44 +02:00
local POOL_NAME = $1
local POOL_SOCKET = $2
2020-07-06 21:43:19 +02:00
if [ [ -z $POOL_NAME ] ] || [ [ -z $POOL_SOCKET ] ] ; then
PrintDebug "Error: Invalid arguments for AddPoolToPendingList"
return 0
fi
IsInPendingList " $POOL_NAME " " $POOL_SOCKET "
2020-07-29 03:16:44 +02:00
local FOUND = $?
2020-07-06 21:43:19 +02:00
2020-09-21 01:24:53 +02:00
if [ [ $FOUND = = 1 ] ] ; then
2020-07-06 21:43:19 +02:00
#Already in list, quit
PrintDebug " Pool $POOL_NAME $POOL_SOCKET is already in pending list "
return 0
fi
#Otherwise add this pool to the end of the list
2020-09-21 12:44:06 +02:00
PENDING_LIST += ( " $POOL_NAME $ARRAY_SEPARATOR $POOL_SOCKET " )
2020-07-06 21:43:19 +02:00
PrintDebug " Added pool $POOL_NAME $POOL_SOCKET to pending list "
return 1
}
# Removes a pool from pending list
# Returns 1 if success, 0 otherwise
function DeletePoolFromPendingList( ) {
2020-07-29 03:16:44 +02:00
local POOL_NAME = $1
local POOL_SOCKET = $2
local UNSET_USED = ""
2020-07-06 21:43:19 +02:00
if [ [ -z $POOL_NAME ] ] || [ [ -z $POOL_SOCKET ] ] ; then
PrintDebug "Error: Invalid arguments for DeletePoolFromPendingList"
return 0
fi
2020-07-29 03:16:44 +02:00
for ITEM_INDEX in " ${ !PENDING_LIST[@] } " ; do
local PENDING_ITEM = " ${ PENDING_LIST [ $ITEM_INDEX ] } "
2020-09-21 12:44:06 +02:00
if [ [ " $PENDING_ITEM " = = " $POOL_NAME $ARRAY_SEPARATOR $POOL_SOCKET " ] ] ; then
2020-07-29 03:16:44 +02:00
unset " PENDING_LIST[ $ITEM_INDEX ] "
UNSET_USED = "1"
fi
done
2020-07-06 21:43:19 +02:00
2020-07-29 03:16:44 +02:00
if [ [ -z " $UNSET_USED " ] ] ; then
2020-07-06 21:43:19 +02:00
#Not in list, quit
PrintDebug " Error: Pool $POOL_NAME $POOL_SOCKET is already missing in pending list "
return 0
fi
2020-07-29 03:16:44 +02:00
#Renumber the indexes
PENDING_LIST = ( " ${ PENDING_LIST [@] } " )
2020-07-06 21:43:19 +02:00
PrintDebug " Removed pool $POOL_NAME $POOL_SOCKET from pending list "
return 1
}
function SavePrintResults( ) {
2020-08-05 22:59:19 +02:00
#Checking and creating cache directory just in case:
createCacheDirectory
2020-07-06 21:43:19 +02:00
#Saving pending list:
if [ [ -f $PENDING_FILE ] ] && [ [ ! -w $PENDING_FILE ] ] ; then
2020-07-06 23:26:28 +02:00
echo " Error: write permission is not granted to user $ACTIVE_USER for cache file $PENDING_FILE "
2020-07-06 21:43:19 +02:00
exit 1
fi
PrintDebug " Saving pending pools list to file $PENDING_FILE ... "
2020-09-21 01:24:53 +02:00
$S_PRINTF "%s\n" " ${ PENDING_LIST [@] } " >" $PENDING_FILE "
2020-07-06 21:43:19 +02:00
2020-07-07 04:37:40 +02:00
#We must sort the cache list
2020-07-07 04:55:00 +02:00
readarray -t CACHE < <( for a in " ${ CACHE [@] } " ; do echo " $a " ; done | $S_SORT )
2020-07-07 04:37:40 +02:00
2020-07-06 21:43:19 +02:00
if [ [ -n $DEBUG_MODE ] ] ; then
PrintDebug "List of pools to be saved to cache pools file:"
PrintCacheList
fi
if [ [ -f $RESULTS_CACHE_FILE ] ] && [ [ ! -w $RESULTS_CACHE_FILE ] ] ; then
2020-07-06 23:26:28 +02:00
echo " Error: write permission is not granted to user $ACTIVE_USER for cache file $RESULTS_CACHE_FILE "
2020-07-06 21:43:19 +02:00
exit 1
fi
PrintDebug " Saving cache file to file $RESULTS_CACHE_FILE ... "
2020-09-21 01:24:53 +02:00
$S_PRINTF "%s\n" " ${ CACHE [@] } " >" $RESULTS_CACHE_FILE "
2020-07-06 21:43:19 +02:00
POOL_FIRST = 0
#We store the resulting JSON data for Zabbix in the following var:
RESULT_DATA = "{\"data\":["
for CACHE_ITEM in " ${ CACHE [@] } " ; do
2020-07-29 03:16:44 +02:00
local ITEM_NAME
2020-07-06 21:43:19 +02:00
# shellcheck disable=SC2016
2020-09-21 12:44:06 +02:00
ITEM_NAME = $( echo " $CACHE_ITEM " | $S_AWK -F " $ARRAY_SEPARATOR " '{print $1}' )
2020-07-29 03:16:44 +02:00
local ITEM_SOCKET
2020-07-06 21:43:19 +02:00
# shellcheck disable=SC2016
2020-09-21 12:44:06 +02:00
ITEM_SOCKET = $( echo " $CACHE_ITEM " | $S_AWK -F " $ARRAY_SEPARATOR " '{print $2}' )
2020-09-21 01:24:53 +02:00
EncodeToJson " $ITEM_NAME " " $ITEM_SOCKET "
2020-07-06 21:43:19 +02:00
done
RESULT_DATA = " $RESULT_DATA ]} "
PrintDebug "Resulting JSON data for Zabbix:"
2020-07-06 23:26:28 +02:00
echo -n " $RESULT_DATA "
2020-07-06 21:43:19 +02:00
}
2020-06-28 17:18:43 +02:00
function CheckExecutionTime( ) {
2020-07-29 03:16:44 +02:00
local CURRENT_TIME
2020-07-07 14:37:07 +02:00
CURRENT_TIME = $( $S_DATE +%s%N)
2020-07-29 03:16:44 +02:00
local ELAPSED_TIME
2020-07-07 14:37:07 +02:00
ELAPSED_TIME = $( echo " ( $CURRENT_TIME - $START_TIME )/1000000 " | $S_BC )
2020-07-06 21:43:19 +02:00
if [ [ $ELAPSED_TIME -lt $MAX_EXECUTION_TIME ] ] ; then
2020-06-28 17:18:43 +02:00
#All good, we can continue
2020-07-07 14:37:07 +02:00
PrintDebug " Check execution time OK, elapsed $ELAPSED_TIME ms "
2020-07-06 21:43:19 +02:00
return 1
2020-06-28 17:18:43 +02:00
fi
#We need to save our state and exit
2020-07-07 14:37:07 +02:00
PrintDebug " Check execution time: stop required, elapsed $ELAPSED_TIME ms "
2020-07-06 21:43:19 +02:00
SavePrintResults
exit 0
2020-06-28 17:18:43 +02:00
}
2020-01-17 19:47:39 +01:00
# Validates the specified pool by getting its status and working with cache.
# Pass two arguments: pool name and pool socket
# Function returns:
# 0 if the pool is invalid
2020-09-21 00:49:37 +02:00
# 1 if the pool is OK and process manager is dynamic
# 2 if the pool is OK and process manager is static
# 3 if the pool is OK and process manager is ondemand
# 4 if the pool is OK and process manager is unknown
2020-07-06 21:43:19 +02:00
function CheckPool( ) {
2020-07-29 03:16:44 +02:00
local POOL_NAME = $1
local POOL_SOCKET = $2
2020-09-21 01:24:53 +02:00
if [ [ -z $POOL_NAME ] ] || [ [ -z $POOL_SOCKET ] ] ; then
2020-07-06 21:43:19 +02:00
PrintDebug "Error: Invalid arguments for CheckPool"
2020-02-06 23:11:57 +01:00
return 0
fi
2020-01-17 19:47:39 +01:00
2020-07-29 03:16:44 +02:00
local STATUS_JSON
2020-09-21 01:24:53 +02:00
STATUS_JSON = $( $S_BASH " $STATUS_SCRIPT " " $POOL_SOCKET " $STATUS_PATH )
2020-07-29 03:16:44 +02:00
local EXIT_CODE = $?
2020-09-21 01:24:53 +02:00
if [ [ $EXIT_CODE = = 0 ] ] ; then
2020-02-06 23:11:57 +01:00
# The exit code is OK, let's check the JSON data
# JSON data example:
# {"pool":"www2","process manager":"ondemand","start time":1578181845,"start since":117,"accepted conn":3,"listen queue":0,"max listen queue":0,"listen queue len":0,"idle processes":0,"active processes":1,"total processes":1,"max active processes":1,"max children reached":0,"slow requests":0}
# We use basic regular expression here, i.e. we need to use \+ and not escape { and }
2020-09-21 01:24:53 +02:00
if [ [ -n $( echo " $STATUS_JSON " | $S_GREP -G '^{.*\"pool\":\".\+\".*,\"process manager\":\".\+\".*}$' ) ] ] ; then
2020-02-06 23:11:57 +01:00
PrintDebug " Status data for pool $POOL_NAME , socket $POOL_SOCKET , status path $STATUS_PATH is valid "
2020-07-06 21:43:19 +02:00
2020-07-29 03:16:44 +02:00
local PROCESS_MANAGER
2020-07-06 23:26:28 +02:00
PROCESS_MANAGER = $( echo " $STATUS_JSON " | $S_GREP -oP '"process manager":"\K([a-z]+)' )
2020-07-06 21:43:19 +02:00
if [ [ -n $PROCESS_MANAGER ] ] ; then
PrintDebug " Detected pool's process manager is $PROCESS_MANAGER "
2020-09-21 00:49:37 +02:00
if [ [ $PROCESS_MANAGER = = "dynamic" ] ] ; then
return 1
elif [ [ $PROCESS_MANAGER = = "static" ] ] ; then
return 2
elif [ [ $PROCESS_MANAGER = = "ondemand" ] ] ; then
return 3
else
PrintDebug "Error: process manager is unknown"
return 4
fi
2020-07-06 21:43:19 +02:00
else
PrintDebug "Error: Failed to detect process manager of the pool"
2020-02-06 23:11:57 +01:00
fi
2020-01-17 19:47:39 +01:00
fi
2020-02-06 23:11:57 +01:00
PrintDebug " Failed to validate status data for pool $POOL_NAME , socket $POOL_SOCKET , status path $STATUS_PATH "
2020-09-21 01:24:53 +02:00
if [ [ -n $STATUS_JSON ] ] ; then
2020-02-06 23:11:57 +01:00
PrintDebug " Status script returned: $STATUS_JSON "
2020-01-17 19:47:39 +01:00
fi
return 0
2020-02-06 23:11:57 +01:00
fi
PrintDebug " Failed to get status for pool $POOL_NAME , socket $POOL_SOCKET , status path $STATUS_PATH "
2020-09-21 01:24:53 +02:00
if [ [ -n $STATUS_JSON ] ] ; then
2020-02-06 23:11:57 +01:00
PrintDebug " Status script returned: $STATUS_JSON "
fi
return 0
2020-01-17 19:47:39 +01:00
}
2020-07-06 21:43:19 +02:00
#Sleeps for a specified predefined amount of time. Works only if "sleep mode" is enabled.
function sleepNow( ) {
if [ [ -n $USE_SLEEP_TIMEOUT ] ] ; then
PrintDebug " Debug: Sleep for $SLEEP_TIMEOUT sec "
$S_SLEEP " $SLEEP_TIMEOUT "
2020-07-07 14:57:20 +02:00
CheckExecutionTime
2020-02-06 23:11:57 +01:00
fi
2020-07-06 21:43:19 +02:00
}
2020-06-28 17:18:43 +02:00
2020-07-06 21:43:19 +02:00
# Analysis of pool by name, scans the processes, and adds them to pending list for further checks
function AnalyzePool( ) {
2020-07-29 03:16:44 +02:00
local POOL_NAME = $1
2020-09-21 01:24:53 +02:00
if [ [ -z $POOL_NAME ] ] ; then
2020-07-06 21:43:19 +02:00
PrintDebug "Invalid arguments for AnalyzePool"
return 0
fi
2020-01-17 19:47:39 +01:00
2020-07-29 03:16:44 +02:00
local POOL_PID_LIST
2020-02-06 23:11:57 +01:00
# shellcheck disable=SC2016
2020-09-21 01:24:53 +02:00
POOL_PID_LIST = $( $S_PRINTF '%s\n' " ${ PS_LIST [@] } " | $S_GREP -F -w " php-fpm: pool $POOL_NAME " | $S_AWK '{print $1}' )
2020-07-29 03:16:44 +02:00
local POOL_PID_ARGS = ""
2020-06-29 13:32:31 +02:00
while IFS = read -r POOL_PID; do
if [ [ -n $POOL_PID ] ] ; then
POOL_PID_ARGS = " $POOL_PID_ARGS -p $POOL_PID "
fi
done <<< " $POOL_PID_LIST "
if [ [ -n $POOL_PID_ARGS ] ] ; then
2020-02-06 23:11:57 +01:00
#We search for socket or IP address and port
#Socket example:
#php-fpm7. 25897 root 9u unix 0x000000006509e31f 0t0 58381847 /run/php/php7.3-fpm.sock type=STREAM
#IP example:
#php-fpm7. 1110 default 0u IPv4 15760 0t0 TCP localhost:8002 (LISTEN)
2019-12-19 12:02:16 +01:00
2020-02-06 23:11:57 +01:00
#Check all matching processes, because we may face a redirect (or a symlink?), examples:
#php-fpm7. 1203 www-data 5u unix 0x000000006509e31f 0t0 15068771 type=STREAM
#php-fpm7. 6086 www-data 11u IPv6 21771 0t0 TCP *:9000 (LISTEN)
#php-fpm7. 1203 www-data 8u IPv4 15070917 0t0 TCP localhost.localdomain:23054->localhost.localdomain:postgresql (ESTABLISHED)
#More info at https://github.com/rvalitov/zabbix-php-fpm/issues/12
2019-12-19 12:02:16 +01:00
2020-07-06 21:43:19 +02:00
PrintDebug " Started analysis of pool $POOL_NAME , PID(s): $POOL_PID_ARGS "
2020-02-06 23:11:57 +01:00
#Extract only important information:
2020-02-07 13:08:15 +01:00
#Use -P to show port number instead of port name, see https://github.com/rvalitov/zabbix-php-fpm/issues/24
2020-06-29 14:40:20 +02:00
#Use -n flag to show IP address and not convert it to domain name (like localhost)
2020-06-29 13:32:31 +02:00
#Sometimes different PHP-FPM versions may have the same names of pools, so we need to consider that.
# It's considered that a pair of pool name and socket must be unique.
#Sorting is required, because uniq needs it
2020-07-29 03:16:44 +02:00
local POOL_PARAMS_LIST
2020-07-06 21:43:19 +02:00
# shellcheck disable=SC2086
2020-06-29 14:40:20 +02:00
POOL_PARAMS_LIST = $( $S_LSOF -n -P $POOL_PID_ARGS 2>/dev/null | $S_GREP -w -e "unix" -e "TCP" | $S_SORT -u | $S_UNIQ -f8)
2020-07-29 03:16:44 +02:00
local FOUND_POOL = ""
2020-02-06 23:11:57 +01:00
while IFS = read -r pool; do
if [ [ -n $pool ] ] ; then
2020-06-29 13:32:31 +02:00
PrintDebug " Checking process: $pool "
2020-07-29 03:16:44 +02:00
local POOL_TYPE
2020-06-29 13:32:31 +02:00
# shellcheck disable=SC2016
2020-09-21 01:24:53 +02:00
POOL_TYPE = $( echo " $pool " | $S_AWK '{print $5}' )
2020-07-29 03:16:44 +02:00
local POOL_SOCKET
2020-06-29 13:32:31 +02:00
# shellcheck disable=SC2016
2020-09-21 01:24:53 +02:00
POOL_SOCKET = $( echo " $pool " | $S_AWK '{print $9}' )
2020-06-29 13:32:31 +02:00
if [ [ -n $POOL_TYPE ] ] && [ [ -n $POOL_SOCKET ] ] ; then
if [ [ $POOL_TYPE = = "unix" ] ] ; then
#We have a socket here, test if it's actually a socket:
if [ [ -S $POOL_SOCKET ] ] ; then
2020-07-06 21:43:19 +02:00
FOUND_POOL = "1"
2020-06-29 13:32:31 +02:00
PrintDebug " Found socket $POOL_SOCKET "
2020-07-06 21:43:19 +02:00
AddPoolToPendingList " $POOL_NAME " " $POOL_SOCKET "
2020-06-29 13:32:31 +02:00
else
PrintDebug " Error: specified socket $POOL_SOCKET is not valid "
fi
elif [ [ $POOL_TYPE = = "IPv4" ] ] || [ [ $POOL_TYPE = = "IPv6" ] ] ; then
#We have a TCP connection here, check it:
2020-07-29 03:16:44 +02:00
local CONNECTION_TYPE
2020-06-29 13:32:31 +02:00
# shellcheck disable=SC2016
2020-09-21 01:24:53 +02:00
CONNECTION_TYPE = $( echo " $pool " | $S_AWK '{print $8}' )
2020-06-29 13:32:31 +02:00
if [ [ $CONNECTION_TYPE = = "TCP" ] ] ; then
#The connection must have state LISTEN:
2020-07-29 03:16:44 +02:00
local LISTEN
2020-09-21 01:24:53 +02:00
LISTEN = $( echo " $pool " | $S_GREP -F -w "(LISTEN)" )
2020-06-29 13:32:31 +02:00
if [ [ -n $LISTEN ] ] ; then
#Check and replace * to localhost if it's found. Asterisk means that the PHP listens on
#all interfaces.
2020-07-06 21:43:19 +02:00
FOUND_POOL = "1"
2020-06-29 13:32:31 +02:00
PrintDebug " Found TCP connection $POOL_SOCKET "
2020-06-29 15:02:20 +02:00
POOL_SOCKET = ${ POOL_SOCKET / \* : /localhost : }
2020-07-06 21:43:19 +02:00
AddPoolToPendingList " $POOL_NAME " " $POOL_SOCKET "
2020-02-06 23:11:57 +01:00
else
2020-06-29 13:32:31 +02:00
PrintDebug "Warning: expected connection state must be LISTEN, but it was not detected"
2020-02-06 23:11:57 +01:00
fi
2019-12-19 12:02:16 +01:00
else
2020-06-29 13:32:31 +02:00
PrintDebug " Warning: expected connection type is TCP, but found $CONNECTION_TYPE "
2019-12-19 12:02:16 +01:00
fi
2020-02-06 23:11:57 +01:00
else
2020-06-29 13:32:31 +02:00
PrintDebug " Unsupported type $POOL_TYPE , skipping "
2020-02-06 23:11:57 +01:00
fi
2019-12-19 12:02:16 +01:00
else
2020-06-29 13:32:31 +02:00
PrintDebug "Warning: pool type or socket is empty"
2019-08-12 14:22:49 +02:00
fi
2020-02-06 23:11:57 +01:00
else
PrintDebug "Error: failed to get process information. Probably insufficient privileges. Use sudo or run this script under root."
fi
done <<< " $POOL_PARAMS_LIST "
2020-09-21 01:24:53 +02:00
if [ [ -z $FOUND_POOL ] ] ; then
2020-07-06 21:43:19 +02:00
PrintDebug " Error: failed to discover information for pool $POOL_NAME "
2019-08-12 14:22:49 +02:00
fi
2020-02-06 23:11:57 +01:00
else
2020-07-06 21:43:19 +02:00
PrintDebug " Error: failed to find PID for pool $POOL_NAME "
2020-02-06 23:11:57 +01:00
fi
2020-01-17 19:47:39 +01:00
2020-07-06 21:43:19 +02:00
return 1
}
# Prints list of pools in pending list
function PrintPendingList( ) {
2020-07-29 03:16:44 +02:00
local COUNTER = 1
2020-07-06 21:43:19 +02:00
for POOL_ITEM in " ${ PENDING_LIST [@] } " ; do
2020-07-29 03:16:44 +02:00
local POOL_NAME
2020-07-06 21:43:19 +02:00
# shellcheck disable=SC2016
2020-09-21 12:44:06 +02:00
POOL_NAME = $( echo " $POOL_ITEM " | $S_AWK -F " $ARRAY_SEPARATOR " '{print $1}' )
2020-07-29 03:16:44 +02:00
local POOL_SOCKET
2020-07-06 21:43:19 +02:00
# shellcheck disable=SC2016
2020-09-21 12:44:06 +02:00
POOL_SOCKET = $( echo " $POOL_ITEM " | $S_AWK -F " $ARRAY_SEPARATOR " '{print $2}' )
2020-07-06 21:43:19 +02:00
if [ [ -n " $POOL_NAME " ] ] && [ [ -n " $POOL_SOCKET " ] ] ; then
PrintDebug " # $COUNTER $POOL_NAME $POOL_SOCKET "
2020-07-06 23:26:28 +02:00
COUNTER = $( echo " $COUNTER + 1 " | $S_BC )
2020-07-06 21:43:19 +02:00
fi
done
}
# Prints list of pools in cache
function PrintCacheList( ) {
2020-07-29 03:16:44 +02:00
local COUNTER = 1
2020-07-06 21:43:19 +02:00
for POOL_ITEM in " ${ CACHE [@] } " ; do
2020-07-29 03:16:44 +02:00
local POOL_NAME
2020-07-06 21:43:19 +02:00
# shellcheck disable=SC2016
2020-09-21 12:44:06 +02:00
POOL_NAME = $( echo " $POOL_ITEM " | $S_AWK -F " $ARRAY_SEPARATOR " '{print $1}' )
2020-07-29 03:16:44 +02:00
local POOL_SOCKET
2020-07-06 21:43:19 +02:00
# shellcheck disable=SC2016
2020-09-21 12:44:06 +02:00
POOL_SOCKET = $( echo " $POOL_ITEM " | $S_AWK -F " $ARRAY_SEPARATOR " '{print $2}' )
2020-07-29 03:16:44 +02:00
local PROCESS_MANAGER
2020-07-06 21:43:19 +02:00
# shellcheck disable=SC2016
2020-09-21 12:44:06 +02:00
PROCESS_MANAGER = $( echo " $POOL_ITEM " | $S_AWK -F " $ARRAY_SEPARATOR " '{print $3}' )
2020-07-06 21:43:19 +02:00
if [ [ -n " $POOL_NAME " ] ] && [ [ -n " $POOL_SOCKET " ] ] && [ [ -n " $PROCESS_MANAGER " ] ] ; then
PrintDebug " # $COUNTER $POOL_NAME $POOL_SOCKET $PROCESS_MANAGER "
2020-07-06 23:26:28 +02:00
COUNTER = $( echo " $COUNTER + 1 " | $S_BC )
2020-07-06 21:43:19 +02:00
fi
done
}
2020-09-21 00:49:37 +02:00
# Function processes a pool by name: makes all required checks and adds it to cache, etc.
# Function returns:
# 0 if the pool is invalid
# 1 if the pool is OK and process manager is dynamic
# 2 if the pool is OK and process manager is static
# 3 if the pool is OK and process manager is ondemand
# 4 if the pool is OK and process manager is unknown
2020-07-06 21:43:19 +02:00
function ProcessPool( ) {
2020-07-29 03:16:44 +02:00
local POOL_NAME = $1
local POOL_SOCKET = $2
2020-07-06 21:43:19 +02:00
if [ [ -z $POOL_NAME ] ] || [ [ -z $POOL_SOCKET ] ] ; then
PrintDebug "Invalid arguments for ProcessPool"
return 0
fi
PrintDebug " Processing pool $POOL_NAME $POOL_SOCKET "
2020-09-21 01:24:53 +02:00
CheckPool " $POOL_NAME " " $POOL_SOCKET "
2020-07-29 03:16:44 +02:00
local POOL_STATUS = $?
2020-09-21 01:24:53 +02:00
if [ [ $POOL_STATUS -gt 0 ] ] ; then
2020-07-06 21:43:19 +02:00
PrintDebug " Success: socket $POOL_SOCKET returned valid status data "
else
PrintDebug " Error: socket $POOL_SOCKET didn't return valid data "
fi
2020-09-21 00:49:37 +02:00
return $POOL_STATUS
2020-07-06 21:43:19 +02:00
}
2020-09-21 00:49:37 +02:00
ARG_ID = 1
ARGS_COUNT = $#
while [ $ARG_ID -le $ARGS_COUNT ] ; do
ARG = $1
if [ [ $ARG = = "debug" ] ] ; then
2020-07-06 21:43:19 +02:00
DEBUG_MODE = "1"
2020-09-21 13:27:04 +02:00
PrintDebug "Debug mode enabled"
if [ [ $ARG_ID -ne 1 ] ] ; then
PrintDebug "Error: argument 'debug' if used must be the first argument"
fi
2020-09-21 00:49:37 +02:00
elif [ [ $ARG = = "sleep" ] ] ; then
2020-07-06 21:43:19 +02:00
USE_SLEEP_TIMEOUT = "1"
2020-09-21 13:27:04 +02:00
PrintDebug "Debug: Sleep timeout enabled"
2020-09-21 00:49:37 +02:00
elif [ [ $ARG = = "max_tasks" ] ] ; then
ARG_ID = $(( ARG_ID + 1 ))
shift 1
ARG = $1
if [ [ $ARG -ge 1 ] ] ; then
MAX_PARALLEL_TASKS = $1
fi
2020-09-21 13:27:04 +02:00
PrintDebug " Debug: argument 'max_tasks' = ' $ARG ' detected, the resulting parameter is set to $MAX_PARALLEL_TASKS "
2020-09-21 00:49:37 +02:00
elif [ [ $ARG = = "max_time" ] ] ; then
ARG_ID = $(( ARG_ID + 1 ))
shift 1
ARG = $1
if [ [ $ARG -ge 1 ] ] ; then
MAX_EXECUTION_TIME = $1
fi
2020-09-21 13:27:04 +02:00
PrintDebug " Debug: argument 'max_time' = ' $ARG ' detected, the resulting parameter is set to $MAX_EXECUTION_TIME "
2020-09-21 00:49:37 +02:00
elif [ [ $ARG = = "nosleep" ] ] ; then
2020-07-07 00:31:17 +02:00
MAX_EXECUTION_TIME = "10000000"
2020-09-21 13:27:04 +02:00
PrintDebug "Debug: Timeout checks disabled"
2020-09-21 00:49:37 +02:00
elif [ [ $ARG = = "?" ] ] || [ [ $ARG = = "help" ] ] || [ [ $ARG = = "/?" ] ] ; then
$S_CAT <<EOF
NAME: discovery script for zabbix-php-fpm
2020-09-21 13:27:04 +02:00
USAGE: $0 [ debug] [ ARGUMENTS...]
2020-09-21 00:49:37 +02:00
ARGUMENTS:
2020-09-21 13:27:04 +02:00
debug - to display verbose output on screen, if you use this argument, then put it first
2020-09-21 00:49:37 +02:00
nosleep - to disable timeout checks, used for testing only
sleep - to enable forced timeouts between operations, used for testing only
max_tasks <VALUE> - sets maximum number of allowed parallel tasks to VALUE ( must be >= 1)
max_time <VALUE> - sets maximum execution time in ms of the script to VALUE ( 1000<= VALUE<= 30000)
<STATUS_PATH> - sets status path used for PHP-FPM. The path should begin with slash symbol '/' . Default value is '/php-fpm-status' .
? or help or /? - display current information
AUTHOR: Ramil Valitov ramilvalitov@gmail.com
PROJECT PAGE: https://github.com/rvalitov/zabbix-php-fpm
WIKI & DOCS: https://github.com/rvalitov/zabbix-php-fpm/wiki
EOF
exit 1
elif [ [ $ARG = = /* ] ] ; then
STATUS_PATH = $ARG
2020-07-06 21:43:19 +02:00
PrintDebug " Argument $ARG is interpreted as status path "
else
PrintDebug " Argument $ARG is unknown and skipped "
2020-02-06 23:11:57 +01:00
fi
2020-09-21 00:49:37 +02:00
ARG_ID = $(( ARG_ID + 1 ))
shift 1
2020-01-17 19:47:39 +01:00
done
2020-07-06 21:43:19 +02:00
PrintDebug " Current user is $ACTIVE_USER "
PrintDebug " Status path to be used: $STATUS_PATH "
2020-01-17 19:47:39 +01:00
2020-07-06 21:43:19 +02:00
PrintDebug " Local directory is $LOCAL_DIR "
2020-09-21 01:24:53 +02:00
if [ [ ! -f $STATUS_SCRIPT ] ] ; then
2020-07-06 23:26:28 +02:00
echo " Helper script $STATUS_SCRIPT not found "
2020-07-06 21:43:19 +02:00
exit 1
fi
2020-09-21 01:24:53 +02:00
if [ [ ! -r $STATUS_SCRIPT ] ] ; then
2020-07-06 23:26:28 +02:00
echo " Helper script $STATUS_SCRIPT is not readable "
2020-02-06 23:11:57 +01:00
exit 1
2020-01-18 21:04:53 +01:00
fi
2020-07-06 21:43:19 +02:00
PrintDebug " Helper script $STATUS_SCRIPT is reachable "
# Loading cached data for pools.
CACHE = ( )
if [ [ -r $RESULTS_CACHE_FILE ] ] ; then
PrintDebug " Reading cache file of pools $RESULTS_CACHE_FILE ... "
2020-09-21 01:24:53 +02:00
mapfile -t CACHE < <( $S_CAT " $RESULTS_CACHE_FILE " )
2020-07-06 21:43:19 +02:00
else
PrintDebug " Cache file of pools $RESULTS_CACHE_FILE not found, skipping... "
fi
if [ [ -n $DEBUG_MODE ] ] ; then
PrintDebug "List of pools loaded from cache pools file:"
PrintCacheList
fi
#Loading pending tasks
PENDING_LIST = ( )
if [ [ -r $PENDING_FILE ] ] ; then
PrintDebug " Reading file of pending pools $PENDING_FILE ... "
mapfile -t PENDING_LIST < <( $S_CAT " $PENDING_FILE " )
else
PrintDebug " List of pending pools $PENDING_FILE not found, skipping... "
fi
if [ [ -n $DEBUG_MODE ] ] ; then
PrintDebug "List of pools loaded from pending pools file:"
PrintPendingList
fi
2020-01-18 21:04:53 +01:00
2020-07-06 21:43:19 +02:00
mapfile -t PS_LIST < <( $S_PS ax | $S_GREP -F "php-fpm: pool " | $S_GREP -F -v "grep" )
# shellcheck disable=SC2016
2020-09-21 01:24:53 +02:00
POOL_NAMES_LIST = $( $S_PRINTF '%s\n' " ${ PS_LIST [@] } " | $S_AWK '{print $NF}' | $S_SORT -u)
2020-07-06 21:43:19 +02:00
#Update pending list with pools that are active and running
while IFS = read -r POOL_NAME; do
2020-09-21 00:49:37 +02:00
AnalyzePool " $POOL_NAME "
2020-07-06 21:43:19 +02:00
done <<< " $POOL_NAMES_LIST "
if [ [ -n $DEBUG_MODE ] ] ; then
PrintDebug "Pending list generated:"
PrintPendingList
fi
#Process pending list
PrintDebug "Processing pools"
2020-09-21 00:49:37 +02:00
PARALLEL_TASKS = 0
TASK_LIST = ( )
LAST_PENDING_ITEM = ${ PENDING_LIST [ ${# PENDING_LIST [@] } - 1] }
2020-09-21 01:10:09 +02:00
2020-07-06 21:43:19 +02:00
for POOL_ITEM in " ${ PENDING_LIST [@] } " ; do
# shellcheck disable=SC2016
2020-09-21 12:44:06 +02:00
POOL_NAME = $( echo " $POOL_ITEM " | $S_AWK -F " $ARRAY_SEPARATOR " '{print $1}' )
2020-07-06 21:43:19 +02:00
# shellcheck disable=SC2016
2020-09-21 12:44:06 +02:00
POOL_SOCKET = $( echo " $POOL_ITEM " | $S_AWK -F " $ARRAY_SEPARATOR " '{print $2}' )
2020-07-06 21:43:19 +02:00
if [ [ -n " $POOL_NAME " ] ] && [ [ -n " $POOL_SOCKET " ] ] ; then
2020-09-21 14:11:00 +02:00
if [ [ $MAX_PARALLEL_TASKS -eq 1 ] ] ; then
#We work in standard mode (non-parallel)
ProcessPool " $POOL_NAME " " $POOL_SOCKET "
EXIT_CODE = $?
DeletePoolFromPendingList " $POOL_NAME " " $POOL_SOCKET "
2020-09-21 00:49:37 +02:00
2020-09-21 14:11:00 +02:00
PROCESS_MANAGER = $( getPoolManagerByCode $EXIT_CODE )
if [ [ -n $PROCESS_MANAGER ] ] ; then
UpdatePoolInCache " $POOL_NAME " " $POOL_SOCKET " " $PROCESS_MANAGER "
2020-09-21 00:49:37 +02:00
fi
2020-09-21 14:11:00 +02:00
else
#We work in parallel mode
PARALLEL_TASKS = $(( PARALLEL_TASKS + 1 ))
if [ [ $PARALLEL_TASKS -le $MAX_PARALLEL_TASKS ] ] ; then
PrintDebug " Starting processing task for pool $POOL_NAME $POOL_SOCKET , subprocess # $PARALLEL_TASKS ... "
ProcessPool " $POOL_NAME " " $POOL_SOCKET " &
TASK_PID = $!
TASK_LIST += ( " $POOL_NAME $ARRAY_SEPARATOR $POOL_SOCKET $ARRAY_SEPARATOR $TASK_PID " )
fi
if [ [ $PARALLEL_TASKS -gt $MAX_PARALLEL_TASKS ] ] || [ [ $LAST_PENDING_ITEM = = " $POOL_ITEM " ] ] ; then
#Wait till all tasks complete
if [ [ $PARALLEL_TASKS -gt $MAX_PARALLEL_TASKS ] ] ; then
PrintDebug " Max number of parallel tasks reached ( $MAX_PARALLEL_TASKS ), waiting till they finish... "
else
PrintDebug "No more parallel tasks to start, waiting for running tasks to finish..."
2020-09-21 00:49:37 +02:00
fi
2020-09-21 14:11:00 +02:00
for TASK_LINE in " ${ TASK_LIST [@] } " ; do
# shellcheck disable=SC2016
POOL_NAME = $( echo " $TASK_LINE " | $S_AWK -F " $ARRAY_SEPARATOR " '{print $1}' )
# shellcheck disable=SC2016
POOL_SOCKET = $( echo " $TASK_LINE " | $S_AWK -F " $ARRAY_SEPARATOR " '{print $2}' )
# shellcheck disable=SC2016
TASK_PID = $( echo " $TASK_LINE " | $S_AWK -F " $ARRAY_SEPARATOR " '{print $3}' )
wait $TASK_PID
EXIT_CODE = $?
PrintDebug " Finished parallel task PID $TASK_PID for pool \" $POOL_NAME \" at $POOL_SOCKET "
DeletePoolFromPendingList " $POOL_NAME " " $POOL_SOCKET "
PROCESS_MANAGER = $( getPoolManagerByCode $EXIT_CODE )
if [ [ -n $PROCESS_MANAGER ] ] ; then
UpdatePoolInCache " $POOL_NAME " " $POOL_SOCKET " " $PROCESS_MANAGER "
fi
done
PrintDebug "All previously started parallel tasks are complete"
PARALLEL_TASKS = 0
TASK_LIST = ( )
fi
#End of parallel mode
2020-09-21 00:49:37 +02:00
fi
2020-07-06 21:43:19 +02:00
#Confirm that we run not too much time
CheckExecutionTime
2020-07-07 05:27:30 +02:00
#Used for debugging:
sleepNow
2020-07-06 21:43:19 +02:00
fi
done
2020-01-17 19:47:39 +01:00
2020-07-06 21:43:19 +02:00
SavePrintResults