whoami7 - Manager
:
/
lib64
/
nagios
/
plugins
/
Upload File:
files >> //lib64/nagios/plugins/check-phpfpm-status.py
#!/usr/bin/env python ################################### # Check PHP-FPM status page # # Created by Bogdan Kukharskiy # # Namecheap # ################################### # This script checks PHP-FPM status page for all pools (domains) found in cPanel configs # # Returns the nagios native status codes: # 0 = OK # 1 = WARNING # 2 = CRITICAL # 3 = UNKNOWN """ Threaded Python Fastcgi socket statistics collector """ import glob import threading import json import getopt import sys from subprocess import Popen, PIPE from os import R_OK, access from os.path import isfile, getsize, basename from re import split def usage(): print("Usage: %s -v <verbose> more verbose output" % (sys.argv[0])) class FPMConfig(object): # Data structure for a cPanel FPM config. The class properties are config attributes def __init__(self, conf_info): self.pool_name = conf_info[0] self.socket_path = conf_info[1] # listen = self.status_path = conf_info[2] self.max_children = conf_info[3] self.max_requests = conf_info[4] self.max_spare_servers = conf_info[5] self.min_spare_servers = conf_info[6] self.process_idle_timeout = conf_info[7] self.start_servers = conf_info[8] def get_FPMconfigs_list(): # Retrieves a list [] of Proc objects representing the active process list into list phpfpm_configs_list = [] includes_list = [] cpanelfpm_configs_list = [] fileName = '' p1 = Popen(["ps", "auxf"], stdout=PIPE) p2 = Popen(["grep", "[p]hp-fpm: master"], stdin=p1.stdout, stdout=PIPE) p3 = Popen(["grep", "-Po", "([a-zA-z0-9/\-_]+.conf)"], stdin=p2.stdout, stdout=PIPE) p2.stdout.close() # Allow p2 to receive a SIGPIPE if p3 exits. p1.stdout.close() # Allow p1 to receive a SIGPIPE if p2 exits. for line in p3.stdout: phpfpm_configs_list.append(line.rstrip()) # Now let's find includes in config files for fileName in phpfpm_configs_list: if not (isfile(fileName) and access(fileName, R_OK)): print("php-fpm config file doesn't exist or isn't readable: " + str(fileName)) exit(3) try: if getsize(fileName) > 0: with open(fileName, 'r') as fin: buffer = fin.read().splitlines() fin.close() for line in buffer: if 'include=' in line: includes_list.append(line) else: print("php-fpm config file is empty: " + str(fileName)) exit(3) except OSError as e: print("php-fpm config file does not exist or not accessible: %s" % e) exit(3) # And finally let's find sockets paths in all includes config files for includeName in includes_list: includePath = includeName.lstrip('include=') domains_fpm_list = [] domains_fpm_list = glob.glob(includePath) for domainFileName in domains_fpm_list: if not (isfile(domainFileName) and access(domainFileName, R_OK)): print("cPanel FPM config file doesn't exist or isn't readable: " + domainFileName) exit(3) try: if getsize(domainFileName) > 0: with open(domainFileName, 'r') as fin: buffer = fin.read().splitlines() fin.close() conf_info = [basename(domainFileName.rstrip('.conf'))] tmp_list = [] for line in buffer: tmp = split(" = ", line.strip()) tmp_list.append(tmp) conf_info.append([s for s in tmp_list if 'listen' in s][0][1]) conf_info.append([s for s in tmp_list if 'pm.status_path' in s][0][1]) conf_info.append([s for s in tmp_list if 'pm.max_children' in s][0][1]) conf_info.append([s for s in tmp_list if 'pm.max_requests' in s][0][1]) conf_info.append([s for s in tmp_list if 'pm.max_spare_servers' in s][0][1]) conf_info.append([s for s in tmp_list if 'pm.min_spare_servers' in s][0][1]) conf_info.append([s for s in tmp_list if 'pm.process_idle_timeout' in s][0][1]) conf_info.append([s for s in tmp_list if 'pm.start_servers' in s][0][1]) cpanelfpm_configs_list.append(FPMConfig(conf_info)) else: print("php-fpm config file is empty: " + str(fileName)) exit(3) except OSError as e: print("php-fpm config file does not exist or not accessible: %s" % e) exit(3) return cpanelfpm_configs_list def check_via_flup(poolName, socketPath, statusPath): # "flup_fcgi_client.py" is the modified flup.client.fcgi_app module # located in the same directory import flup_fcgi_client as fcgi_client fcgi = fcgi_client.FCGIApp(connect=socketPath) script = statusPath query = 'full&json' env = { 'SCRIPT_NAME': script, 'SCRIPT_FILENAME': script, 'QUERY_STRING': query, 'REQUEST_METHOD': 'GET'} code, headers, body, err = fcgi(env) if code != "200 OK" or len(err) > 0: if verbose: print("Status page HTTP code for pool '{0}' is {1}".format(poolName, code)) print("Error is: %s" % err) sockets_CRITICAL.append(poolName) return res = json.loads(body) if verbose: print(json.dumps(res, indent=4)) # checking max_children_reached and listen_queue if res['max children reached'] != 0 or res['listen queue'] != 0: sockets_CRITICAL.append(poolName) # checking active processes consumes >= 80% of total processes # elif (100 * res['active processes']) / res['total processes'] >= 80: # sockets_WARNING.append(poolName) else: sockets_OK.append(poolName) if __name__ == "__main__": verbose = False try: optlist, args = getopt.getopt(sys.argv[1:], 'vh') except getopt.GetoptError: usage() sys.exit(3) for opt, arg in optlist: if opt == '-h': usage() sys.exit(3) if opt == '-v': verbose = True sockets_OK = [] sockets_WARNING = [] sockets_CRITICAL = [] sockets_UNKNOWN = [] configs_list = get_FPMconfigs_list() threads = [] for cfgs in configs_list: t = threading.Thread(target=check_via_flup, args=(cfgs.pool_name, cfgs.socket_path, cfgs.status_path)) t.start() threads.append(t) for t in threads: t.join(2) if sockets_CRITICAL: msg = "Following pool(s) have 'max children reached' or 'listen queue'>0 or timed out: %s" % sockets_CRITICAL exit_code = 2 # elif sockets_WARNING: # msg = "Following pool(s) have active processes consuming >= 80% of total processes: {0}".format(sockets_WARNING) # exit_code = 1 elif sockets_UNKNOWN: msg = "Something is wrong/unknown: %s" % sockets_UNKNOWN exit_code = 3 elif sockets_OK: msg = "PHP-FPM status of all pools is OK. Pools checked: %s" % len(configs_list) exit_code = 0 else: msg = "Strange, all status arrays are empty. Maybe PHP-FPM is not enabled? or service is down?" exit_code = 3 print(msg) sys.exit(exit_code)
Copyright ©2021 || Defacer Indonesia