From 9bf3b9a299ad7c8768b8144fd1324cc11ad4d802 Mon Sep 17 00:00:00 2001 From: Andreas Perhab Date: Tue, 3 May 2022 09:30:29 +0200 Subject: [PATCH] smtp_hello_: improve compatibility * support systems without time executable (if we can use bash time keyword) * use curl as smtp client if available * enable specifying different ports from 25 * enable specifying other test commands than "HELO localhost" (e.g. HELP, QUIT can also be used to test connections) --- plugins/network/smtp_hello_ | 122 ++++++++++++++++++++++++++++++------ 1 file changed, 102 insertions(+), 20 deletions(-) diff --git a/plugins/network/smtp_hello_ b/plugins/network/smtp_hello_ index b8300d03..32068ace 100755 --- a/plugins/network/smtp_hello_ +++ b/plugins/network/smtp_hello_ @@ -2,9 +2,16 @@ # # smtp_hello_ - munin plugin for measuring smtp hello response # Copyright (C) 2008 Marek Mahut +# Copyright (C) 2022 Andreas Perhab, WT-IO-IT GmbH # # Usage: -# ln -s /usr/share/munin/plugins/smtp_hello_ /etc/munin/plugins/smtp_hello_mysmtpserver.example.com +# ln -s /usr/share/munin/plugins/smtp_hello_ /etc/munin/plugins/smtp_hello_mysmtpserver.example.com +# +# Environment variables (optional): +# SMTP_PORT: port number to use for connection, default is 25 +# SMTP_COMMAND: command to use to test the connection, default is "HELO localhost" +# TIMEOUT_SECONDS: seconds to take at most for the test, default is 120 +# # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -21,36 +28,111 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # #$log$ -#Revision 1.0 2008/12/15 17:21:58 Marek Mahut (mmahut) -#Initial commit. +#Revision 2.0 2022/05/03 09:15:32 Andreas Perhab (ap-wtioit) +#Improve compatiblity. # #%# family=auto #%# capabilities=autoconf +. "$MUNIN_LIBDIR/plugins/plugin.sh" -host=`basename $0 | sed 's/^smtp_hello_//g'` +if [ "${MUNIN_DEBUG:-0}" == "1" ]; then + set -x +fi + +SMTP_COMMAND=${SMTP_COMMAND:-HELO localhost} +SMTP_PORT=${SMTP_PORT:-25} +TIMEOUT_SECONDS=${TIMEOUT_SECONDS:-120} +# if we have curl all non-zero exit codes indicate an error +status_warning=${status_warning:-0:0} +# default warning time begins at half the timeout +host_warning=${host_warning:-:$((TIMEOUT_SECONDS/2))} +# default when we get values bigger than 99% of timeout we mark the value as critical +host_critical=${host_critical:-:$((TIMEOUT_SECONDS * 99 / 100))} + +host=$(basename "$0" | sed 's/^smtp_hello_//g') + +time_executable="" +if which time >/dev/null; then + # use time executable found in PATH + time_executable=$(which time) +elif [ -x /usr/bin/time ] ; then + # use time executable found in /usr/bin + time_executable="/usr/bin/time" +fi +if [ "$time_executable" != "" ] ; then + function take_the_time() { + "$time_executable" -f "%e" "$@" 2>&1 | tail -n 1 + return "${PIPESTATUS[0]}" + } +elif { time echo; } >/dev/null 2>&1; then + # if we cannot find time executable but time keyword is successful we use the keyword + function take_the_time() { + # we use LC_ALL=C to force . as decimal separator on systems where LC_ is set to a language that uses , + # to limit the effect of LC_ALL=C and TIMEFORMAT, as well as to be able to redirect stderr of the time keyword + # we use a subshell here + ( + TIMEFORMAT='%R' + LC_ALL=C + time "$@" 1>/dev/null + ) 2>&1 + return $? + } +fi + +nc_executable="" +if which nc >/dev/null ; then + # use nc from PATH + nc_executable=$(which nc) +elif [ -x /usr/bin/nc ] ; then + # as fallback use /usr/bin/nc if found + nc_executable="/usr/bin/nc" +fi + +if which curl >/dev/null && curl_version_info=$(curl --version) && [[ "$curl_version_info" == *" smtp "* ]]; then + curl_with_smtp_support=1 +fi if [ "$1" == "config" ]; then - echo "graph_title smtp response time" - echo "graph_vlabel response in sec" - echo "graph_period minute" - echo "graph_category Network" - echo "graph_args --base 1000 --lower-limit 0" - echo "host.label $host" + echo "graph_title smtp response time" + echo "graph_vlabel response in sec" + echo "graph_period minute" + echo "graph_category network" + echo "graph_args --base 1000 --lower-limit 0" + echo "host.label $host" + print_warning "host" + print_critical "host" + if [ "$curl_with_smtp_support" == "1" ] ; then + echo "status.label $host smtp success" + print_warning "status" + print_critical "status" + fi elif [ "$1" == "autoconf" ]; then - if [ -x /usr/bin/time ] && [ -x /usr/bin/nc ]; then - echo "yes" - else - echo "no (/usr/bin/time or /usr/bin/nc missing)" - fi - exit 0 + if [ "$take_the_time" != "" ] && [ -x "$nc_executable" ]; then + echo "yes" + else + echo "no (/usr/bin/time or /usr/bin/nc missing)" + fi + exit 0 else - - response=`echo HELO localhost | /usr/bin/time -f "%e" nc -C -w 120 $host 25 2>&1 | tail -n 1` - echo "host.value $response" - + if [ "$curl_with_smtp_support" == "1" ] ; then + value=$(take_the_time curl --silent -X "$SMTP_COMMAND" --max-time "$TIMEOUT_SECONDS" "smtp://$host:$SMTP_PORT/") + status=$? + else + # Note: "HELO localhost" only works if the SMTP server terminates the connection when presenting the HELO line + # if you have troubles here, try installing curl (with smtp support), and we will use a proper smtp client + # implementation. alternatively you can also set the SMTP_COMMAND environment variable to QUIT + value=$(echo "$SMTP_COMMAND" | take_the_time "$nc_executable" -C -w "$TIMEOUT_SECONDS" "$host" "$SMTP_PORT") + # with the simple echo command we would need to check a lot of conditions to determine a successful status + # if you want this feature, install curl instead + status="" + fi + echo "host.value $value" + if [ -n "$status" ] ; then + echo "status.value $status" + fi fi