From ed2ff78a1ebafbf6bd965b195960627cbee3d767 Mon Sep 17 00:00:00 2001
From: Jan Philipp Timme <jan.philipp@timme.it>
Date: Tue, 7 Jan 2020 11:58:44 +0100
Subject: [PATCH] Add more vendor files for later use

---
 checkmk/checkmk-files/apache_status          | 182 +++++++
 checkmk/checkmk-files/check_mk_agent.freebsd |   1 +
 checkmk/checkmk-files/mk_apt                 |  65 +++
 checkmk/checkmk-files/mk_haproxy.freebsd     |   2 +-
 checkmk/checkmk-files/mk_logins              |  29 ++
 checkmk/checkmk-files/mk_postgres            | 520 +++++++++++++++++++
 checkmk/checkmk-files/mk_zypper              |  50 ++
 checkmk/checkmk-files/netstat.linux          |  31 ++
 checkmk/checkmk-files/nginx_status           | 153 ++++++
 checkmk/checkmk-files/smart                  | 179 +++++++
 10 files changed, 1211 insertions(+), 1 deletion(-)
 create mode 100644 checkmk/checkmk-files/apache_status
 create mode 100644 checkmk/checkmk-files/mk_apt
 create mode 100644 checkmk/checkmk-files/mk_logins
 create mode 100644 checkmk/checkmk-files/mk_postgres
 create mode 100644 checkmk/checkmk-files/mk_zypper
 create mode 100644 checkmk/checkmk-files/netstat.linux
 create mode 100644 checkmk/checkmk-files/nginx_status
 create mode 100644 checkmk/checkmk-files/smart

diff --git a/checkmk/checkmk-files/apache_status b/checkmk/checkmk-files/apache_status
new file mode 100644
index 0000000..ad11fc9
--- /dev/null
+++ b/checkmk/checkmk-files/apache_status
@@ -0,0 +1,182 @@
+#!/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 - Apache Server Status
+#
+# Fetches the server-status page from detected or configured apache
+# processes to gather status information about this apache process.
+#
+# To make this agent plugin work you have to load the status_module
+# into your apache process. It is also needed to enable the "server-status"
+# handler below the URL "/server-status".
+#
+# By default this plugin tries to detect all locally running apache processes
+# and to monitor them. If this is not good for your environment you might
+# create an apache_status.cfg file in MK_CONFDIR and populate the servers
+# list to prevent executing the detection mechanism.
+#
+# It is also possible to override or extend the ssl_ports variable to make the
+# check contact other ports than 443 with HTTPS requests.
+import os
+import re
+import socket
+import sys
+import urllib2
+
+
+config_dir = os.getenv("MK_CONFDIR", "/etc/check_mk")
+config_file = config_dir + "/apache_status.conf"
+
+if not os.path.exists(config_file):
+    config_file = config_dir + "/apache_status.cfg"
+
+# We have to deal with socket timeouts. Python > 2.6
+# supports timeout parameter for the urllib2.urlopen method
+# but we are on a python 2.5 system here which seem to use the
+# default socket timeout. We are local here so  set it to 1 second.
+socket.setdefaulttimeout(5.0)
+
+# 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():
+    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 = [
+            'apache2',
+            'httpd',
+            'httpd-prefork',
+            'httpd2-prefork',
+            'httpd2-worker',
+            'httpd.worker',
+            'fcgi-pm',
+        ]
+        # 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
+
+        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]'
+        elif ':' in address:
+            address = '[%s]' % address
+
+        # 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'
+        else:
+            proto = 'http'
+
+        results.append((proto, address, port))
+
+    return results
+
+
+if servers is None:
+    servers = try_detect_servers()
+
+
+if not servers:
+    sys.exit(0)
+
+
+sys.stdout.write('<<<apache_status>>>\n')
+for server in servers:
+    if isinstance(server, tuple):
+        proto, address, port = server
+        page = 'server-status'
+    else:
+        proto = server['protocol']
+        address = server['address']
+        port = server['port']
+        page = server.get('page', 'server-status')
+
+    portspec = port and ":%d" % port or ""
+
+    try:
+        url = '%s://%s%s/%s?auto' % (proto, address, portspec, page)
+        is_local = address in ("127.0.0.1", "[::1]", "localhost")
+        # Try to fetch the status page for each server
+        try:
+            request = urllib2.Request(url, headers={"Accept" : "text/plain"})
+            if is_local and proto == 'https':
+                import ssl
+                no_cert_context = ssl.create_default_context()
+                no_cert_context.check_hostname = False
+                no_cert_context.verify_mode = ssl.CERT_NONE
+                fd = urllib2.urlopen(url, context=no_cert_context)
+            else:
+                fd = urllib2.urlopen(request)
+        except urllib2.URLError, e:
+            if 'unknown protocol' in str(e):
+                # HACK: workaround misconfigurations where port 443 is used for
+                # serving non ssl secured http
+                url = 'http://%s%s/server-status?auto' % (address, portspec)
+                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%s): %s %s\n' % (address, portspec, e.code, e))
+
+    except Exception, e:
+        sys.stderr.write('Exception (%s%s): %s\n' % (address, portspec, e))
diff --git a/checkmk/checkmk-files/check_mk_agent.freebsd b/checkmk/checkmk-files/check_mk_agent.freebsd
index f75ed90..c1b3601 100644
--- a/checkmk/checkmk-files/check_mk_agent.freebsd
+++ b/checkmk/checkmk-files/check_mk_agent.freebsd
@@ -442,3 +442,4 @@ then
         echo
     done
 fi
+
diff --git a/checkmk/checkmk-files/mk_apt b/checkmk/checkmk-files/mk_apt
new file mode 100644
index 0000000..31f930b
--- /dev/null
+++ b/checkmk/checkmk-files/mk_apt
@@ -0,0 +1,65 @@
+#!/bin/bash
+# Check for APT updates (Debian, Ubuntu)
+# +------------------------------------------------------------------+
+# |             ____ _               _        __  __ _  __           |
+# |            / ___| |__   ___  ___| | __   |  \/  | |/ /           |
+# |           | |   | '_ \ / _ \/ __| |/ /   | |\/| | ' /            |
+# |           | |___| | | |  __/ (__|   <    | |  | | . \            |
+# |            \____|_| |_|\___|\___|_|\_\___|_|  |_|_|\_\           |
+# |                                                                  |
+# | 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.
+
+# TODO:
+# Einstellungen:
+# - upgrade oder dist-upgrade
+# - vorher ein update machen
+# Bakery:
+# - Bakelet anlegen
+# - Async-Zeit einstellbar machen und das Ding immer async laufen lassen
+# Check programmieren:
+#   * Schwellwerte auf Anzahlen
+#   * Regexen auf Pakete, die zu CRIT/WARN führen
+# - Graph malen mit zwei Kurven
+
+# This variable can either be "upgrade" or "dist-upgrade"
+UPGRADE=upgrade
+DO_UPDATE=yes
+
+
+function check_apt_update {
+    if [ "$DO_UPDATE" = yes ] ; then
+        # NOTE: Even with -qq, apt-get update can output several lines to
+        # stderr, e.g.:
+        #
+        # W: There is no public key available for the following key IDs:
+        # 1397BC53640DB551
+        apt-get update -qq 2> /dev/null
+    fi
+    apt-get -o 'Debug::NoLocking=true' -o 'APT::Get::Show-User-Simulation-Note=false' -s -qq "$UPGRADE" | grep -v '^Conf'
+}
+
+
+if type apt-get > /dev/null ; then
+    echo '<<<apt:sep(0)>>>'
+    out=$(check_apt_update)
+    if [ -z "$out" ]; then
+        echo "No updates pending for installation"
+    else
+        echo "$out"
+    fi
+fi
diff --git a/checkmk/checkmk-files/mk_haproxy.freebsd b/checkmk/checkmk-files/mk_haproxy.freebsd
index dd8f6c6..7c7a0fe 100644
--- a/checkmk/checkmk-files/mk_haproxy.freebsd
+++ b/checkmk/checkmk-files/mk_haproxy.freebsd
@@ -1,4 +1,4 @@
-if [ -r /var/run/haproxy.sock ]; then
+if [ -r /var/run/haproxy.stat ]; then
 	echo "<<<haproxy:sep(44)>>>"
 	echo "show stat" | socat - UNIX-CONNECT:/var/run/haproxy.sock
 fi
diff --git a/checkmk/checkmk-files/mk_logins b/checkmk/checkmk-files/mk_logins
new file mode 100644
index 0000000..b4b8b64
--- /dev/null
+++ b/checkmk/checkmk-files/mk_logins
@@ -0,0 +1,29 @@
+#!/bin/bash
+# +------------------------------------------------------------------+
+# |             ____ _               _        __  __ _  __           |
+# |            / ___| |__   ___  ___| | __   |  \/  | |/ /           |
+# |           | |   | '_ \ / _ \/ __| |/ /   | |\/| | ' /            |
+# |           | |___| | | |  __/ (__|   <    | |  | | . \            |
+# |            \____|_| |_|\___|\___|_|\_\___|_|  |_|_|\_\           |
+# |                                                                  |
+# | 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.
+
+if type who >/dev/null; then
+    echo "<<<logins>>>"
+    who | wc -l
+fi
diff --git a/checkmk/checkmk-files/mk_postgres b/checkmk/checkmk-files/mk_postgres
new file mode 100644
index 0000000..47fef50
--- /dev/null
+++ b/checkmk/checkmk-files/mk_postgres
@@ -0,0 +1,520 @@
+#!/bin/bash
+# +------------------------------------------------------------------+
+# |             ____ _               _        __  __ _  __           |
+# |            / ___| |__   ___  ___| | __   |  \/  | |/ /           |
+# |           | |   | '_ \ / _ \/ __| |/ /   | |\/| | ' /            |
+# |           | |___| | | |  __/ (__|   <    | |  | | . \            |
+# |            \____|_| |_|\___|\___|_|\_\___|_|  |_|_|\_\           |
+# |                                                                  |
+# | Copyright Mathias Kettner 2015             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.
+
+
+# TODO postgres_connections output format
+
+
+#   .--common funcs--------------------------------------------------------.
+#   |                                             __                       |
+#   |  ___ ___  _ __ ___  _ __ ___   ___  _ __   / _|_   _ _ __   ___ ___  |
+#   | / __/ _ \| '_ ` _ \| '_ ` _ \ / _ \| '_ \ | |_| | | | '_ \ / __/ __| |
+#   || (_| (_) | | | | | | | | | | | (_) | | | ||  _| |_| | | | | (__\__ \ |
+#   | \___\___/|_| |_| |_|_| |_| |_|\___/|_| |_||_|  \__,_|_| |_|\___|___/ |
+#   |                                                                      |
+#   '----------------------------------------------------------------------'
+
+
+function compare_version_greater_equal() {
+    local GREATER_ONE
+    GREATER_ONE=$(echo "$1 $2" | awk '{if ($1 >= $2) print $1; else print $2}')
+    if [ "$GREATER_ONE" == "$1" ] ; then
+        return 0
+    else
+        return 1
+    fi
+}
+
+
+#.
+#   .--section funcs-------------------------------------------------------.
+#   |                   _   _                __                            |
+#   |     ___  ___  ___| |_(_) ___  _ __    / _|_   _ _ __   ___ ___       |
+#   |    / __|/ _ \/ __| __| |/ _ \| '_ \  | |_| | | | '_ \ / __/ __|      |
+#   |    \__ \  __/ (__| |_| | (_) | | | | |  _| |_| | | | | (__\__ \      |
+#   |    |___/\___|\___|\__|_|\___/|_| |_| |_|  \__,_|_| |_|\___|___/      |
+#   |                                                                      |
+#   '----------------------------------------------------------------------'
+
+
+function postgres_instances() {
+    echo '<<<postgres_instances>>>'
+    # If we have no instances we take db id (pqsql/postgres) because
+    # ps output may be unreadable
+    # In case of instances ps output shows them readable
+    if [ ! -z "${1}" ]; then
+        echo "[[[${1}]]]"
+    fi
+
+    # shellcheck disable=SC2009
+    # The pgrep command would be different for older distros. Newer distros
+    # need the -a option, but older ones need the -f option. The first idea
+    # was to use:
+    #   pgrep -af bin/postgres 2>/dev/null || pgrep -lf bin/postgres
+    # but SLES 11 returns the exit code 0 for a wrong command line.
+    ps -eo pid,command | grep bin/postgres | grep -vE '^[ ]*[0-9]+ grep '
+}
+
+
+function postgres_sessions() {
+    local OUTPUT
+
+    # In postgresql 9.2 the column state was introduced, which has to be queried to
+    # find the state of the sessions. The column state can be NULL.
+    CONDITION="$ROW = $IDLE"
+    OUTPUT="$(echo "\echo '<<<postgres_sessions>>>${INSTANCE_SECTION}'
+              SELECT $CONDITION, count(*) FROM pg_stat_activity WHERE $ROW IS NOT NULL GROUP BY ($CONDITION);" |\
+              su - "$DBUSER" -c "$export_PGPASSFILE $psql -X --variable ON_ERROR_STOP=1 ${EXTRA_ARGS} -A -t -F' '" 2>/dev/null)"
+
+    echo "$OUTPUT"
+    # line with number of idle sessions is sometimes missing on Postgres 8.x. This can lead
+    # to an altogether empty section and thus the check disappearing.
+    echo "$OUTPUT" | grep -q '^t ' || echo "t 0"
+}
+
+
+function postgres_simple_queries() {
+    # Querytime
+    # Supports versions >= 8.3, > 9.1
+    local QUERYTIME_QUERY
+    if compare_version_greater_equal "$POSTGRES_VERSION" "9.2" ; then
+        QUERYTIME_QUERY="SELECT datname, datid, usename, client_addr, state AS state, COALESCE(ROUND(EXTRACT(epoch FROM now()-query_start)),0) AS seconds,
+        pid, regexp_replace(query, E'[\\n\\r\\u2028]+', ' ', 'g' ) AS current_query FROM pg_stat_activity WHERE (query_start IS NOT NULL AND (state NOT LIKE 'idle%' OR state IS NULL)) ORDER BY query_start, pid DESC;"
+    else
+        QUERYTIME_QUERY="SELECT datname, datid, usename, client_addr, '' AS state,    COALESCE(ROUND(EXTRACT(epoch FROM now()-query_start)),0) AS seconds,
+        procpid as pid, regexp_replace(current_query, E'[\\n\\r\\u2028]+', ' ', 'g' ) AS current_query FROM pg_stat_activity WHERE (query_start IS NOT NULL AND current_query NOT LIKE '<IDLE>%') ORDER BY query_start, procpid DESC;"
+    fi
+
+    # Number of current connections per database
+    # We need to output the databases, too.
+    # This query does not report databases without an active query
+    local CONNECTIONS_QUERY
+
+    # Here the order of the columns did not match with what the server side expects,
+    # with the result, that there was never any active connection shown in the
+    # web-gui.
+    CONDITION="$ROW <> $IDLE"
+    CONNECTIONS_QUERY="SELECT d.datname, COUNT(datid) AS current,
+          (SELECT setting AS mc FROM pg_settings WHERE name = 'max_connections') AS mc
+        FROM pg_database d
+        LEFT JOIN pg_stat_activity s ON (s.datid = d.oid) WHERE $CONDITION
+        GROUP BY 1
+        ORDER BY datname;"
+
+    echo "\pset footer off
+          \echo '<<<postgres_stat_database:sep(59)>>>${INSTANCE_SECTION}'
+          SELECT datid, datname, numbackends, xact_commit, xact_rollback, blks_read, blks_hit, tup_returned, tup_fetched, tup_inserted, tup_updated, tup_deleted, pg_database_size(datname) AS datsize FROM pg_stat_database;
+
+          \echo '<<<postgres_locks:sep(59)>>>${INSTANCE_SECTION}'
+          \echo '[databases_start]'
+          $ECHO_DATABASES
+          \echo '[databases_end]'
+          SELECT datname, granted, mode FROM pg_locks l RIGHT JOIN pg_database d ON (d.oid=l.database) WHERE d.datallowconn;
+
+          \echo '<<<postgres_query_duration:sep(59)>>>${INSTANCE_SECTION}'
+          \echo '[databases_start]'
+          $ECHO_DATABASES
+          \echo '[databases_end]'
+          $QUERYTIME_QUERY
+
+          \echo '<<<postgres_connections:sep(59)>>>${INSTANCE_SECTION}'
+          \echo '[databases_start]'
+          $ECHO_DATABASES
+          \echo '[databases_end]'
+          $CONNECTIONS_QUERY" \
+        | su - "$DBUSER" -c "$export_PGPASSFILE $psql -X ${EXTRA_ARGS} -q -A -F';'"
+}
+
+
+function postgres_stats() {
+    # Contains last vacuum time and analyze time
+    local LASTVACUUM="SELECT current_database() AS datname, nspname AS sname, relname AS tname,
+                          CASE WHEN v IS NULL THEN -1 ELSE round(extract(epoch FROM v)) END AS vtime,
+                          CASE WHEN g IS NULL THEN -1 ELSE round(extract(epoch FROM v)) END AS atime
+                      FROM (SELECT nspname, relname, GREATEST(pg_stat_get_last_vacuum_time(c.oid), pg_stat_get_last_autovacuum_time(c.oid)) AS v,
+                                GREATEST(pg_stat_get_last_analyze_time(c.oid), pg_stat_get_last_autoanalyze_time(c.oid)) AS g
+                            FROM pg_class c, pg_namespace n
+                            WHERE relkind = 'r' AND n.oid = c.relnamespace AND n.nspname <> 'information_schema'
+                      ORDER BY 3) AS foo;"
+
+    local FIRST=
+    local QUERY="\pset footer off
+                 BEGIN;
+                 SET statement_timeout=30000;
+                 COMMIT;
+
+                 \echo '<<<postgres_stats:sep(59)>>>${INSTANCE_SECTION}'
+                 \echo '[databases_start]'
+                 $ECHO_DATABASES
+                 \echo '[databases_end]'"
+
+    for db in $DATABASES ; do
+        QUERY="$QUERY
+               \c $db
+               $LASTVACUUM
+              "
+        if [ -z $FIRST ] ; then
+            FIRST=false
+            QUERY="$QUERY
+                   \pset tuples_only on
+                  "
+        fi
+    done
+    echo "$QUERY" | su - "$DBUSER" -c "$export_PGPASSFILE $psql -X ${EXTRA_ARGS} -q -A -F';'" | grep -v -e 'COMMIT$' -e 'SET$' -e 'BEGIN$'
+}
+
+
+function postgres_version() {
+    # Postgres version an connection time
+    echo -e "<<<postgres_version:sep(1)>>>${INSTANCE_SECTION}"
+    (TIMEFORMAT='%3R'; time echo "SELECT version() AS v" |\
+    su - "$DBUSER" -c "$export_PGPASSFILE $psql -X ${EXTRA_ARGS} -t -A -F';'; echo -e '<<<postgres_conn_time>>>${INSTANCE_SECTION}'") 2>&1
+}
+
+
+function postgres_bloat() {
+    # Bloat index and tables
+    # Supports versions <9.0, >=9.0
+    # This huge query has been gratefully taken from Greg Sabino Mullane's check_postgres.pl
+    local BLOAT_QUERY
+    if compare_version_greater_equal "$POSTGRES_VERSION" "9.0" ; then
+        BLOAT_QUERY="SELECT
+          current_database() AS db, schemaname, tablename, reltuples::bigint AS tups, relpages::bigint AS pages, otta,
+          ROUND(CASE WHEN sml.relpages=0 OR sml.relpages=otta THEN 0.0 ELSE (sml.relpages-otta::numeric)/sml.relpages END,3) AS tbloat,
+          CASE WHEN relpages < otta THEN 0 ELSE relpages::bigint - otta END AS wastedpages,
+          CASE WHEN relpages < otta THEN 0 ELSE bs*(sml.relpages-otta)::bigint END AS wastedbytes,
+          CASE WHEN relpages < otta THEN 0 ELSE (bs*(relpages-otta))::bigint END AS wastedsize,
+          iname, ituples::bigint AS itups, ipages::bigint AS ipages, iotta,
+          ROUND(CASE WHEN ipages=0 OR ipages<=iotta THEN 0.0 ELSE (ipages-iotta::numeric)/ipages END,3) AS ibloat,
+          CASE WHEN ipages < iotta THEN 0 ELSE ipages::bigint - iotta END AS wastedipages,
+          CASE WHEN ipages < iotta THEN 0 ELSE bs*(ipages-iotta) END AS wastedibytes,
+          CASE WHEN ipages < iotta THEN 0 ELSE (bs*(ipages-iotta))::bigint END AS wastedisize,
+          CASE WHEN relpages < otta THEN
+            CASE WHEN ipages < iotta THEN 0 ELSE bs*(ipages-iotta::bigint) END
+            ELSE CASE WHEN ipages < iotta THEN bs*(relpages-otta::bigint)
+              ELSE bs*(relpages-otta::bigint + ipages-iotta::bigint) END
+          END AS totalwastedbytes
+        FROM (
+          SELECT
+            nn.nspname AS schemaname,
+            cc.relname AS tablename,
+            COALESCE(cc.reltuples,0) AS reltuples,
+            COALESCE(cc.relpages,0) AS relpages,
+            COALESCE(bs,0) AS bs,
+            COALESCE(CEIL((cc.reltuples*((datahdr+ma-
+              (CASE WHEN datahdr%ma=0 THEN ma ELSE datahdr%ma END))+nullhdr2+4))/(bs-20::float)),0) AS otta,
+            COALESCE(c2.relname,'?') AS iname, COALESCE(c2.reltuples,0) AS ituples, COALESCE(c2.relpages,0) AS ipages,
+            COALESCE(CEIL((c2.reltuples*(datahdr-12))/(bs-20::float)),0) AS iotta -- very rough approximation, assumes all cols
+          FROM
+             pg_class cc
+          JOIN pg_namespace nn ON cc.relnamespace = nn.oid AND nn.nspname <> 'information_schema'
+          LEFT JOIN
+          (
+            SELECT
+              ma,bs,foo.nspname,foo.relname,
+              (datawidth+(hdr+ma-(case when hdr%ma=0 THEN ma ELSE hdr%ma END)))::numeric AS datahdr,
+              (maxfracsum*(nullhdr+ma-(case when nullhdr%ma=0 THEN ma ELSE nullhdr%ma END))) AS nullhdr2
+            FROM (
+              SELECT
+                ns.nspname, tbl.relname, hdr, ma, bs,
+                SUM((1-coalesce(null_frac,0))*coalesce(avg_width, 2048)) AS datawidth,
+                MAX(coalesce(null_frac,0)) AS maxfracsum,
+                hdr+(
+                  SELECT 1+count(*)/8
+                  FROM pg_stats s2
+                  WHERE null_frac<>0 AND s2.schemaname = ns.nspname AND s2.tablename = tbl.relname
+                ) AS nullhdr
+              FROM pg_attribute att
+              JOIN pg_class tbl ON att.attrelid = tbl.oid
+              JOIN pg_namespace ns ON ns.oid = tbl.relnamespace
+              LEFT JOIN pg_stats s ON s.schemaname=ns.nspname
+              AND s.tablename = tbl.relname
+              AND s.inherited=false
+              AND s.attname=att.attname,
+              (
+                SELECT
+                  (SELECT current_setting('block_size')::numeric) AS bs,
+                    CASE WHEN SUBSTRING(SPLIT_PART(v, ' ', 2) FROM '#\[0-9]+.[0-9]+#\%' for '#')
+                      IN ('8.0','8.1','8.2') THEN 27 ELSE 23 END AS hdr,
+                  CASE WHEN v ~ 'mingw32' OR v ~ '64-bit' THEN 8 ELSE 4 END AS ma
+                FROM (SELECT version() AS v) AS foo
+              ) AS constants
+              WHERE att.attnum > 0 AND tbl.relkind='r'
+              GROUP BY 1,2,3,4,5
+            ) AS foo
+          ) AS rs
+          ON cc.relname = rs.relname AND nn.nspname = rs.nspname
+          LEFT JOIN pg_index i ON indrelid = cc.oid
+          LEFT JOIN pg_class c2 ON c2.oid = i.indexrelid
+        ) AS sml
+         WHERE sml.relpages - otta > 0 OR ipages - iotta > 10 ORDER BY totalwastedbytes DESC LIMIT 10;"
+    else
+        BLOAT_QUERY="SELECT
+          current_database() AS db, schemaname, tablename, reltuples::bigint AS tups, relpages::bigint AS pages, otta,
+          ROUND(CASE WHEN sml.relpages=0 OR sml.relpages=otta THEN 0.0 ELSE (sml.relpages-otta::numeric)/sml.relpages END,3) AS tbloat,
+          CASE WHEN relpages < otta THEN 0 ELSE relpages::bigint - otta END AS wastedpages,
+          CASE WHEN relpages < otta THEN 0 ELSE bs*(sml.relpages-otta)::bigint END AS wastedbytes,
+          CASE WHEN relpages < otta THEN '0 bytes'::text ELSE (bs*(relpages-otta))::bigint || ' bytes' END AS wastedsize,
+          iname, ituples::bigint AS itups, ipages::bigint AS ipages, iotta,
+          ROUND(CASE WHEN ipages=0 OR ipages<=iotta THEN 0.0 ELSE (ipages-iotta::numeric)/ipages END,3) AS ibloat,
+          CASE WHEN ipages < iotta THEN 0 ELSE ipages::bigint - iotta END AS wastedipages,
+          CASE WHEN ipages < iotta THEN 0 ELSE bs*(ipages-iotta) END AS wastedibytes,
+          CASE WHEN ipages < iotta THEN '0 bytes' ELSE (bs*(ipages-iotta))::bigint || ' bytes' END AS wastedisize,
+          CASE WHEN relpages < otta THEN
+            CASE WHEN ipages < iotta THEN 0 ELSE bs*(ipages-iotta::bigint) END
+            ELSE CASE WHEN ipages < iotta THEN bs*(relpages-otta::bigint)
+              ELSE bs*(relpages-otta::bigint + ipages-iotta::bigint) END
+          END AS totalwastedbytes
+        FROM (
+          SELECT
+            nn.nspname AS schemaname,
+            cc.relname AS tablename,
+            COALESCE(cc.reltuples,0) AS reltuples,
+            COALESCE(cc.relpages,0) AS relpages,
+            COALESCE(bs,0) AS bs,
+            COALESCE(CEIL((cc.reltuples*((datahdr+ma-
+              (CASE WHEN datahdr%ma=0 THEN ma ELSE datahdr%ma END))+nullhdr2+4))/(bs-20::float)),0) AS otta,
+            COALESCE(c2.relname,'?') AS iname, COALESCE(c2.reltuples,0) AS ituples, COALESCE(c2.relpages,0) AS ipages,
+            COALESCE(CEIL((c2.reltuples*(datahdr-12))/(bs-20::float)),0) AS iotta -- very rough approximation, assumes all cols
+          FROM
+             pg_class cc
+          JOIN pg_namespace nn ON cc.relnamespace = nn.oid AND nn.nspname <> 'information_schema'
+          LEFT JOIN
+          (
+            SELECT
+              ma,bs,foo.nspname,foo.relname,
+              (datawidth+(hdr+ma-(case when hdr%ma=0 THEN ma ELSE hdr%ma END)))::numeric AS datahdr,
+              (maxfracsum*(nullhdr+ma-(case when nullhdr%ma=0 THEN ma ELSE nullhdr%ma END))) AS nullhdr2
+            FROM (
+              SELECT
+                ns.nspname, tbl.relname, hdr, ma, bs,
+                SUM((1-coalesce(null_frac,0))*coalesce(avg_width, 2048)) AS datawidth,
+                MAX(coalesce(null_frac,0)) AS maxfracsum,
+                hdr+(
+                  SELECT 1+count(*)/8
+                  FROM pg_stats s2
+                  WHERE null_frac<>0 AND s2.schemaname = ns.nspname AND s2.tablename = tbl.relname
+                ) AS nullhdr
+              FROM pg_attribute att
+              JOIN pg_class tbl ON att.attrelid = tbl.oid
+              JOIN pg_namespace ns ON ns.oid = tbl.relnamespace
+              LEFT JOIN pg_stats s ON s.schemaname=ns.nspname
+              AND s.tablename = tbl.relname
+              AND s.attname=att.attname,
+              (
+                SELECT
+                  (SELECT current_setting('block_size')::numeric) AS bs,
+                    CASE WHEN SUBSTRING(SPLIT_PART(v, ' ', 2) FROM '#\"[0-9]+.[0-9]+#\"%' for '#')
+                      IN ('8.0','8.1','8.2') THEN 27 ELSE 23 END AS hdr,
+                  CASE WHEN v ~ 'mingw32' OR v ~ '64-bit' THEN 8 ELSE 4 END AS ma
+                FROM (SELECT version() AS v) AS foo
+              ) AS constants
+              WHERE att.attnum > 0 AND tbl.relkind='r'
+              GROUP BY 1,2,3,4,5
+            ) AS foo
+          ) AS rs
+          ON cc.relname = rs.relname AND nn.nspname = rs.nspname
+          LEFT JOIN pg_index i ON indrelid = cc.oid
+          LEFT JOIN pg_class c2 ON c2.oid = i.indexrelid
+        ) AS sml
+         WHERE sml.relpages - otta > 0 OR ipages - iotta > 10 ORDER BY totalwastedbytes DESC LIMIT 10;"
+    fi
+
+    local FIRST=
+    local QUERY="\pset footer off
+                 \echo '<<<postgres_bloat:sep(59)>>>${INSTANCE_SECTION}'
+                 \echo '[databases_start]'
+                 $ECHO_DATABASES
+                 \echo '[databases_end]'"
+
+    for db in $DATABASES ; do
+        QUERY="$QUERY
+               \c $db
+               $BLOAT_QUERY
+              "
+        if [ -z $FIRST ] ; then
+            FIRST=false
+            QUERY="$QUERY
+                   \pset tuples_only on
+                  "
+        fi
+    done
+    echo "$QUERY" | su - "$DBUSER" -c "$export_PGPASSFILE $psql -X ${EXTRA_ARGS} -q -A -F';'"
+}
+
+
+#.
+#   .--main----------------------------------------------------------------.
+#   |                                       _                              |
+#   |                       _ __ ___   __ _(_)_ __                         |
+#   |                      | '_ ` _ \ / _` | | '_ \                        |
+#   |                      | | | | | | (_| | | | | |                       |
+#   |                      |_| |_| |_|\__,_|_|_| |_|                       |
+#   |                                                                      |
+#   '----------------------------------------------------------------------'
+
+
+### postgres.cfg ##
+# DBUSER=OS_USER_NAME
+# INSTANCE=/home/postgres/db1.env:USER_NAME:/PATH/TO/.pgpass
+# INSTANCE=/home/postgres/db2.env:USER_NAME:/PATH/TO/.pgpass
+
+# TODO @dba USERNAME in .pgpass ?
+# INSTANCE=/home/postgres/db2.env:/PATH/TO/.pgpass
+
+
+function postgres_main() {
+    if [ -z "$DBUSER" ] || [ -z "$PGDATABASE" ] ; then
+        exit 0
+    fi
+
+    EXTRA_ARGS=""
+    if [ ! -z "$PGUSER" ]; then
+        EXTRA_ARGS=$EXTRA_ARGS" -U $PGUSER"
+    fi
+    if [ ! -z "$PGDATABASE" ]; then
+        EXTRA_ARGS=$EXTRA_ARGS" -d $PGDATABASE"
+    fi
+    if [ ! -z "$PGPORT" ]; then
+        EXTRA_ARGS=$EXTRA_ARGS" -p $PGPORT"
+    fi
+
+    if [ ! -z "$PGPASSFILE" ]; then
+        export_PGPASSFILE="export PGPASSFILE=$PGPASSFILE; "
+    fi
+
+    DATABASES="$(echo "SELECT datname FROM pg_database WHERE datistemplate = false;" |\
+                 su - "$DBUSER" -c "$export_PGPASSFILE $psql -X ${EXTRA_ARGS} -t -A -F';'")"
+    # shellcheck disable=SC2001
+    # DATABASES contains one database per line. To print each database in the psql terminal
+    # we have to prefix each line with '\echo '. ${varialbe//search/replace} is not
+    # sufficient in this case.
+    ECHO_DATABASES="$(echo "$DATABASES" | sed 's/^/\\echo /')"
+
+    postgres_check_server_version
+    postgres_sessions
+    postgres_simple_queries
+    postgres_stats
+    postgres_version
+    postgres_bloat
+}
+
+
+function postgres_check_server_version() {
+    # Query the server version from the server. Originally the version of the
+    # client tools was taken, but what really matters is the version of the server.
+    # Terminate the script if the server can not be queried.
+    # We want $(su ...) to be
+    # shellcheck disable=SC2046
+    set -- $(su - "$DBUSER" -c "$psql -A -t -X ${EXTRA_ARGS} -c 'SHOW server_version;'" | tr '.' ' ')
+    test $# -eq 0 && exit 0
+    POSTGRES_VERSION="$1.$2"
+    postgres_set_condition_vars
+}
+
+
+function postgres_set_condition_vars() {
+    if compare_version_greater_equal "$POSTGRES_VERSION" "9.2" ; then
+        ROW=state
+        IDLE="'idle'"
+    else
+        ROW=current_query
+        IDLE="'<IDLE>'"
+    fi
+}
+
+
+MK_CONFFILE=$MK_CONFDIR/postgres.cfg
+if [ -e "$MK_CONFFILE" ]; then
+
+    postgres_instances
+
+    DBUSER=$(grep DBUSER "$MK_CONFFILE" | sed 's/.*=//g')
+
+    # read -r: we do not want to interpret backslashes before spaces and line feeds
+    while read -r line; do
+        case $line in
+            INSTANCE*)
+                instance=$line
+                ;;
+            *)
+                instance=
+                ;;
+        esac
+
+        if [ ! -z "$instance" ]; then
+            # Too complicated for ${variable//search/replace}
+            # shellcheck disable=SC2001
+            instance_path=$(echo "$instance" | sed 's/.*=\(.*\):.*:.*$/\1/g')
+            instance_name=$(echo "$instance_path" | sed -e 's/.*\/\(.*\)/\1/g' -e 's/\.env$//g')
+            if [ ! -z "$instance_name" ]; then
+                INSTANCE_SECTION="\n[[[$instance_name]]]"
+            else
+                INSTANCE_SECTION=""
+            fi
+
+            psql="/$DBUSER/$(grep "^export PGVERSION=" "$instance_path" |
+                 sed -e 's/.*=//g' -e 's/\s*#.*$//g')/bin/psql"
+
+            # Too complicated for ${variable//search/replace}
+            # shellcheck disable=SC2001
+            PGUSER=$(echo "$instance" | sed 's/.*=.*:\(.*\):.*$/\1/g')
+            # Too complicated for ${variable//search/replace}
+            # shellcheck disable=SC2001
+            PGPASSFILE="$(echo "$instance" | sed 's/.*=.*:.*:\(.*\)$/\1/g')"
+            PGDATABASE=$(grep "^export PGDATABASE=" "$instance_path" |
+                         sed -e 's/.*=//g' -e 's/\s*#.*$//g')
+            PGPORT=$(grep "^export PGPORT=" "$instance_path" |
+                     sed -e 's/.*=//g' -e 's/\s*#.*$//g')
+
+            # Fallback
+            if [ ! -f "$psql" ]; then
+                psql="$(grep "^export PGHOME=" "$instance_path" |
+                     sed -e 's/.*=//g' -e 's/\s*#.*$//g')/psql"
+            fi
+
+            postgres_main
+
+        fi
+    done < "$MK_CONFFILE"
+
+else
+
+    if id pgsql >/dev/null 2>&1; then
+        DBUSER=pgsql
+    elif id postgres >/dev/null 2>&1; then
+        DBUSER=postgres
+    else
+        exit 0
+    fi
+
+    PGDATABASE=postgres
+    INSTANCE_SECTION=""
+    psql="psql"
+
+    postgres_instances "$DBUSER"
+    postgres_main
+
+fi
diff --git a/checkmk/checkmk-files/mk_zypper b/checkmk/checkmk-files/mk_zypper
new file mode 100644
index 0000000..a12d09b
--- /dev/null
+++ b/checkmk/checkmk-files/mk_zypper
@@ -0,0 +1,50 @@
+#!/bin/bash
+# +------------------------------------------------------------------+
+# |             ____ _               _        __  __ _  __           |
+# |            / ___| |__   ___  ___| | __   |  \/  | |/ /           |
+# |           | |   | '_ \ / _ \/ __| |/ /   | |\/| | ' /            |
+# |           | |___| | | |  __/ (__|   <    | |  | | . \            |
+# |            \____|_| |_|\___|\___|_|\_\___|_|  |_|_|\_\           |
+# |                                                                  |
+# | 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.
+
+if type zypper > /dev/null ; then
+    echo '<<<zypper:sep(124)>>>'
+    if grep -q '^VERSION = 10' < /etc/SuSE-release
+    then
+        ZYPPER='waitmax 10 zypper --no-gpg-checks --non-interactive --terse'
+        REFRESH=`$ZYPPER refresh 2>&1`
+        if  [ "$REFRESH" ]
+        then
+	    echo "ERROR: $REFRESH"
+        else
+            { $ZYPPER pchk || [ $? = 100 -o $? = 101 ] && $ZYPPER lu ; } \
+    	      | egrep '(patches needed|\|)' | egrep -v '^(#|Repository |Catalog )'
+        fi
+    else
+        ZYPPER='waitmax 10 zypper --no-gpg-checks --non-interactive --quiet'
+        REFRESH=`$ZYPPER refresh 2>&1`
+        if  [ "$REFRESH" ]
+        then
+            echo "ERROR: $REFRESH"
+        else
+            { { $ZYPPER pchk || [ $? = 100 -o $? = 101 ] && $ZYPPER lp ; } ; $ZYPPER ll ; } \
+    	      | egrep '(patches needed|\|)' | egrep -v '^(#|Repository)'
+        fi
+    fi
+fi
diff --git a/checkmk/checkmk-files/netstat.linux b/checkmk/checkmk-files/netstat.linux
new file mode 100644
index 0000000..55a27ae
--- /dev/null
+++ b/checkmk/checkmk-files/netstat.linux
@@ -0,0 +1,31 @@
+#!/bin/sh
+# +------------------------------------------------------------------+
+# |             ____ _               _        __  __ _  __           |
+# |            / ___| |__   ___  ___| | __   |  \/  | |/ /           |
+# |           | |   | '_ \ / _ \/ __| |/ /   | |\/| | ' /            |
+# |           | |___| | | |  __/ (__|   <    | |  | | . \            |
+# |            \____|_| |_|\___|\___|_|\_\___|_|  |_|_|\_\           |
+# |                                                                  |
+# | 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.
+
+# This is not part of the standard agent since it can take very
+# long to run if your TCP/UDP table is large. Netstat seems to
+# have an execution time complexity of at least O(n^2) on Linux.
+
+echo '<<<netstat>>>'
+netstat -ntua  |  egrep '^(tcp|udp)' | sed -e 's/LISTEN/LISTENING/g'
diff --git a/checkmk/checkmk-files/nginx_status b/checkmk/checkmk-files/nginx_status
new file mode 100644
index 0000000..8eb52fc
--- /dev/null
+++ b/checkmk/checkmk-files/nginx_status
@@ -0,0 +1,153 @@
+#!/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
+import re
+import sys
+import urllib2
+
+# 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 netstat_line in os.popen('netstat -tlnp 2>/dev/null').readlines():
+        parts = netstat_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)
+
+        server_proto = 'http'
+        server_address, server_port = parts[3].rsplit(':', 1)
+        server_port = int(server_port)
+
+        # Use localhost when listening globally
+        if server_address == '0.0.0.0':
+            server_address = '127.0.0.1'
+        elif server_address == '::':
+            server_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 server_port in ssl_ports:
+            server_proto = 'https'
+
+        results.append((server_proto, server_address, server_port))
+
+    return results
+
+
+if servers is None:
+    servers = try_detect_servers()
+
+if not servers:
+    sys.exit(0)
+
+sys.stdout.write('<<<nginx_status>>>\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))
diff --git a/checkmk/checkmk-files/smart b/checkmk/checkmk-files/smart
new file mode 100644
index 0000000..6e28c91
--- /dev/null
+++ b/checkmk/checkmk-files/smart
@@ -0,0 +1,179 @@
+#!/bin/bash
+# +------------------------------------------------------------------+
+# |             ____ _               _        __  __ _  __           |
+# |            / ___| |__   ___  ___| | __   |  \/  | |/ /           |
+# |           | |   | '_ \ / _ \/ __| |/ /   | |\/| | ' /            |
+# |           | |___| | | |  __/ (__|   <    | |  | | . \            |
+# |            \____|_| |_|\___|\___|_|\_\___|_|  |_|_|\_\           |
+# |                                                                  |
+# | 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.
+
+
+
+
+# This will be called on LSI based raidcontrollers and accesses
+# the SMART data of SATA disks attached to a SAS Raid HBA via
+# SCSI protocol interface.
+megaraid_info()
+{
+    #PDINFO=$(MegaCli -PDlist -a0)
+    if [ -z "$1" ]; then
+        PDINFO=$(megacli -PDlist -a0 -NoLog)
+    else
+        PDINFO=$($1 -PDlist -a0 -NoLog)
+    fi
+
+    echo "$PDINFO" | \
+    while read line ; do
+        case "$line" in
+           # FIRST LINE
+           "Enclosure Device ID"*) #Enclosure Device ID: 252
+            ENC=$( echo "$line" | awk '{print $4}')
+                  unset SLOT LOG_DEV_ID VEND MODEL
+        ;;
+        "Slot Number"*)  #Slot Number: 7
+            SLOT=$( echo "$line" | awk '{print $3}')
+        ;;
+        # Identify the logical device ID. smartctl needs it to access the disk.
+        "Device Id"*)    #Device Id: 19
+            LOG_DEV_ID=$( echo "$line" | awk '{print $3}')
+        ;;
+        "PD Type"*)      #PD Type: SATA
+            VEND=$( echo "$line" | awk '{print $3}')
+        ;;
+        # This is the last value, generate output here
+        "Inquiry Data"*)
+         #Inquiry Data: WD-WCC1T1035197WDC WD20EZRX-00DC0B0 80.00A80
+            # $4 seems to be better for some vendors... wont be possible to get this perfect.
+            MODEL=$( echo "$line" | awk '{print $3}')
+
+            # /dev/sdc ATA SAMSUNG_SSD_830   5 Reallocated_Sector_Ct   0x0033   100   100   010    Pre-fail  Always       -
+            smartctl -d megaraid,${LOG_DEV_ID} -v 9,raw48 -A /dev/sg0 | \
+              grep Always  | egrep -v '^190(.*)Temperature(.*)'       | \
+              sed "s|^|Enc${ENC}/Slot${SLOT} $VEND $MODEL |"
+            ;;
+            esac
+       done
+}
+
+
+# Only handle always updated values, add device path and vendor/model
+if which smartctl > /dev/null 2>&1 ; then
+    #
+    # if the 3ware-utility is found
+    # get the serials for all disks on the controller
+    #
+    if which tw_cli > /dev/null 2>&1 ; then
+        # support for only one controller at the moment
+        TWAC=$(tw_cli show | awk 'NR < 4 { next } { print $1 }' | head -n 1)
+
+        # - add a trailing zero to handle case of unused slot
+        #   trailing zeros are part of the device links in /dev/disk/by-id/... anyway
+        # - only the last 9 chars seem to be relevant
+        # (hopefully all this doesn't change with new kernels...)
+        eval `tw_cli /$TWAC show drivestatus | grep -E '^p[0-9]' | awk '{print $1 " " $7 "0"}' | while read twaminor serial ; do
+            twaminor=${twaminor#p}
+            serial=${serial:(-9)}
+            serial=AMCC_${serial}00000000000
+            echo "$serial=$twaminor"
+        done`
+    else:
+        echo "tw_cli not found" >&2
+    fi
+
+    echo '<<<smart>>>'
+    SEEN=
+    for D in /dev/disk/by-id/{scsi,ata}-*; do
+        [ "$D" != "${D%scsi-\*}" ] && continue
+        [ "$D" != "${D%ata-\*}" ] && continue
+        [ "$D" != "${D%-part*}" ] && continue
+        N=$(readlink $D)
+        N=${N##*/}
+        if [ -r /sys/block/$N/device/vendor ]; then
+            VEND=$(tr -d ' ' < /sys/block/$N/device/vendor)
+        else
+            # 2012-01-25 Stefan Kaerst CDJ - in case $N does not exist
+            VEND=ATA
+        fi
+        if [ -r /sys/block/$N/device/model ]; then
+            MODEL=$(sed -e 's/ /_/g' -e 's/_*$//g' < /sys/block/$N/device/model)
+        else
+            MODEL=$(smartctl -a $D | grep -i "device model" | sed -e "s/.*:[ ]*//g" -e "s/\ /_/g")
+        fi
+        # Excluded disk models for SAN arrays or certain RAID luns that are also not usable..
+        if [ "$MODEL" = "iSCSI_Disk" -o "$MODEL" = "LOGICAL_VOLUME" ]; then
+            continue
+        fi
+
+        # Avoid duplicate entries for same device
+        if [ "${SEEN//.$N./}" != "$SEEN" ] ; then
+            continue
+        fi
+        SEEN="$SEEN.$N."
+
+        # strip device name for final output
+        DNAME=${D#/dev/disk/by-id/scsi-}
+        DNAME=${DNAME#/dev/disk/by-id/ata-}
+        # 2012-01-25 Stefan Kaerst CDJ - special option in case vendor is AMCC
+        CMD=
+        if [ "$VEND" == "AMCC" -a -n "$TWAC" ]; then
+            DNAME=${DNAME#1}
+            [ -z "${!DNAME}" ] && continue
+            CMD="smartctl -d 3ware,${!DNAME} -v 9,raw48 -A /dev/twa0"
+            # create nice device name including model
+            MODEL=$(tw_cli /$TWAC/p${!DNAME} show model | head -n 1 | awk -F= '{ print $2 }')
+            MODEL=${MODEL## }
+            MODEL=${MODEL// /-}
+            DNAME=${DNAME#AMCC_}
+            DNAME="AMCC_${MODEL}_${DNAME%000000000000}"
+        elif [ "$VEND" != "ATA" ] ; then
+            TEMP=
+            # create temperature output as expected by checks/smart
+            # this is a hack, TODO: change checks/smart to support SCSI-disks
+            eval `smartctl -d scsi -i -A $D | while read a b c d e ; do
+                [ "$a" == Serial ] && echo SN=$c
+                [ "$a" == Current -a "$b" == Drive  -a "$c" == Temperature: ] && echo TEMP=$d
+            done`
+            [ -n "$TEMP" ] && CMD="echo 194 Temperature_Celsius 0x0000 000 000 000 Old_age Always - $TEMP (0 0 0 0)"
+            DNAME="${VEND}_${MODEL}_${SN}"
+        else
+            CMD="smartctl -d ata -v 9,raw48 -A $D"
+        fi
+
+            [ -n "$CMD" ] && $CMD | grep Always | egrep -v '^190(.*)Temperature(.*)' | sed "s|^|$DNAME $VEND $MODEL |"
+    done 2>/dev/null
+
+
+    # Call MegaRaid submodule if conditions are met
+    if type MegaCli >/dev/null 2>&1; then
+        MegaCli_bin="MegaCli"
+    elif type MegaCli64 >/dev/null 2>&1; then
+        MegaCli_bin="MegaCli64"
+    elif type megacli >/dev/null 2>&1; then
+        MegaCli_bin="megacli"
+    else
+        MegaCli_bin="unknown"
+    fi
+
+    if [ "$MegaCli_bin" != "unknown" ]; then
+        megaraid_info "$MegaCli_bin"
+    fi
+else
+    echo "ERROR: smartctl not found" >&2
+fi
+
-- 
GitLab