#!/usr/bin/python # -*- encoding: utf-8; py-indent-offset: 4 -*- # +------------------------------------------------------------------+ # | ____ _ _ __ __ _ __ | # | / ___| |__ ___ ___| | __ | \/ | |/ / | # | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / | # | | |___| | | | __/ (__| < | | | | . \ | # | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ | # | | # | Copyright Mathias Kettner 2014 mk@mathias-kettner.de | # +------------------------------------------------------------------+ # # This file is part of Check_MK. # The official homepage is at http://mathias-kettner.de/check_mk. # # check_mk is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation in version 2. check_mk is distributed # in the hope that it will be useful, but WITHOUT ANY WARRANTY; with- # out even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. See the GNU General Public License for more de- # tails. You should have received a copy of the GNU General Public # License along with GNU Make; see the file COPYING. If not, write # to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, # Boston, MA 02110-1301 USA. # Check_MK-Agent-Plugin - Nginx Server Status # # Fetches the stub nginx_status page from detected or configured nginx # processes to gather status information about this process. # # Take a look at the check man page for details on how to configure this # plugin and check. # # By default this plugin tries to detect all locally running processes # and to monitor them. If this is not good for your environment you might # create an nginx_status.cfg file in MK_CONFDIR and populate the servers # list to prevent executing the detection mechanism. import os, sys, urllib2, re # tell urllib2 not to honour "http(s)_proxy" env variables urllib2.getproxies = lambda: {} config_dir = os.getenv("MK_CONFDIR", "/etc/check_mk") config_file = config_dir + "/nginx_status.cfg" # None or list of (proto, ipaddress, port) tuples. # proto is 'http' or 'https' servers = None ssl_ports = [ 443, ] if os.path.exists(config_file): execfile(config_file) def try_detect_servers(): pids = [] results = [] for line in os.popen('netstat -tlnp 2>/dev/null').readlines(): parts = line.split() # Skip lines with wrong format if len(parts) < 7 or '/' not in parts[6]: continue pid, proc = parts[6].split('/', 1) to_replace = re.compile('^.*/') proc = to_replace.sub('', proc) procs = [ 'nginx', 'nginx:', 'nginx.conf' ] # the pid/proc field length is limited to 19 chars. Thus in case of # long PIDs, the process names are stripped of by that length. # Workaround this problem here procs = [ p[:19 - len(pid) - 1] for p in procs ] # Skip unwanted processes if proc not in procs: continue # Add only the first found port of a single server process if pid in pids: continue pids.append(pid) proto = 'http' address, port = parts[3].rsplit(':', 1) port = int(port) # Use localhost when listening globally if address == '0.0.0.0': address = '127.0.0.1' elif address == '::': address = '::1' # Switch protocol if port is SSL port. In case you use SSL on another # port you would have to change/extend the ssl_port list if port in ssl_ports: proto = 'https' results.append((proto, address, port)) return results if servers is None: servers = try_detect_servers() if not servers: sys.exit(0) sys.stdout.write('<<>>\n') for server in servers: if isinstance(server, tuple): proto, address, port = server page = 'nginx_status' else: proto = server['protocol'] address = server['address'] port = server['port'] page = server.get('page', 'nginx_status') try: url = '%s://%s:%s/%s' % (proto, address, port, page) # Try to fetch the status page for each server try: request = urllib2.Request(url, headers={"Accept" : "text/plain"}) fd = urllib2.urlopen(request) except urllib2.URLError, e: if 'SSL23_GET_SERVER_HELLO:unknown protocol' in str(e): # HACK: workaround misconfigurations where port 443 is used for # serving non ssl secured http url = 'http://%s:%s/%s' % (address, port, page) fd = urllib2.urlopen(url) else: raise for line in fd.read().split('\n'): if not line.strip(): continue if line.lstrip()[0] == '<': # seems to be html output. Skip this server. break sys.stdout.write("%s %s %s\n" % (address, port, line)) except urllib2.HTTPError, e: sys.stderr.write('HTTP-Error (%s:%d): %s %s\n' % (address, port, e.code, e)) except Exception, e: sys.stderr.write('Exception (%s:%d): %s\n' % (address, port, e))