Refactoring: Changed all check parameters starting with an 'o' to the new rulespec...
[check_mk.git] / agents / plugins / nginx_status
blob8eb52fcec708a66a768dbd64098215de641d5100
1 #!/usr/bin/python
2 # -*- encoding: utf-8; py-indent-offset: 4 -*-
3 # +------------------------------------------------------------------+
4 # | ____ _ _ __ __ _ __ |
5 # | / ___| |__ ___ ___| | __ | \/ | |/ / |
6 # | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
7 # | | |___| | | | __/ (__| < | | | | . \ |
8 # | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
9 # | |
10 # | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
11 # +------------------------------------------------------------------+
13 # This file is part of Check_MK.
14 # The official homepage is at http://mathias-kettner.de/check_mk.
16 # check_mk is free software; you can redistribute it and/or modify it
17 # under the terms of the GNU General Public License as published by
18 # the Free Software Foundation in version 2. check_mk is distributed
19 # in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
20 # out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
21 # PARTICULAR PURPOSE. See the GNU General Public License for more de-
22 # tails. You should have received a copy of the GNU General Public
23 # License along with GNU Make; see the file COPYING. If not, write
24 # to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
25 # Boston, MA 02110-1301 USA.
27 # Check_MK-Agent-Plugin - Nginx Server Status
29 # Fetches the stub nginx_status page from detected or configured nginx
30 # processes to gather status information about this process.
32 # Take a look at the check man page for details on how to configure this
33 # plugin and check.
35 # By default this plugin tries to detect all locally running processes
36 # and to monitor them. If this is not good for your environment you might
37 # create an nginx_status.cfg file in MK_CONFDIR and populate the servers
38 # list to prevent executing the detection mechanism.
40 import os
41 import re
42 import sys
43 import urllib2
45 # tell urllib2 not to honour "http(s)_proxy" env variables
46 urllib2.getproxies = lambda: {}
48 config_dir = os.getenv("MK_CONFDIR", "/etc/check_mk")
49 config_file = config_dir + "/nginx_status.cfg"
51 # None or list of (proto, ipaddress, port) tuples.
52 # proto is 'http' or 'https'
53 servers = None
54 ssl_ports = [
55 443,
58 if os.path.exists(config_file):
59 execfile(config_file)
62 def try_detect_servers():
63 pids = []
64 results = []
65 for netstat_line in os.popen('netstat -tlnp 2>/dev/null').readlines():
66 parts = netstat_line.split()
67 # Skip lines with wrong format
68 if len(parts) < 7 or '/' not in parts[6]:
69 continue
71 pid, proc = parts[6].split('/', 1)
72 to_replace = re.compile('^.*/')
73 proc = to_replace.sub('', proc)
75 procs = ['nginx', 'nginx:', 'nginx.conf']
76 # the pid/proc field length is limited to 19 chars. Thus in case of
77 # long PIDs, the process names are stripped of by that length.
78 # Workaround this problem here
79 procs = [p[:19 - len(pid) - 1] for p in procs]
81 # Skip unwanted processes
82 if proc not in procs:
83 continue
85 # Add only the first found port of a single server process
86 if pid in pids:
87 continue
88 pids.append(pid)
90 server_proto = 'http'
91 server_address, server_port = parts[3].rsplit(':', 1)
92 server_port = int(server_port)
94 # Use localhost when listening globally
95 if server_address == '0.0.0.0':
96 server_address = '127.0.0.1'
97 elif server_address == '::':
98 server_address = '::1'
100 # Switch protocol if port is SSL port. In case you use SSL on another
101 # port you would have to change/extend the ssl_port list
102 if server_port in ssl_ports:
103 server_proto = 'https'
105 results.append((server_proto, server_address, server_port))
107 return results
110 if servers is None:
111 servers = try_detect_servers()
113 if not servers:
114 sys.exit(0)
116 sys.stdout.write('<<<nginx_status>>>\n')
117 for server in servers:
118 if isinstance(server, tuple):
119 proto, address, port = server
120 page = 'nginx_status'
121 else:
122 proto = server['protocol']
123 address = server['address']
124 port = server['port']
125 page = server.get('page', 'nginx_status')
127 try:
128 url = '%s://%s:%s/%s' % (proto, address, port, page)
129 # Try to fetch the status page for each server
130 try:
131 request = urllib2.Request(url, headers={"Accept": "text/plain"})
132 fd = urllib2.urlopen(request)
133 except urllib2.URLError, e:
134 if 'SSL23_GET_SERVER_HELLO:unknown protocol' in str(e):
135 # HACK: workaround misconfigurations where port 443 is used for
136 # serving non ssl secured http
137 url = 'http://%s:%s/%s' % (address, port, page)
138 fd = urllib2.urlopen(url)
139 else:
140 raise
142 for line in fd.read().split('\n'):
143 if not line.strip():
144 continue
145 if line.lstrip()[0] == '<':
146 # seems to be html output. Skip this server.
147 break
148 sys.stdout.write("%s %s %s\n" % (address, port, line))
149 except urllib2.HTTPError, e:
150 sys.stderr.write('HTTP-Error (%s:%d): %s %s\n' % (address, port, e.code, e))
152 except Exception, e:
153 sys.stderr.write('Exception (%s:%d): %s\n' % (address, port, e))