1#!/usr/local/bin/bash 2# 3# Plugin to graph response times of the specified websites/URLs. 4# 5# Parameters: 6# 7# config (required) 8# autoconf (optional - used by lrrd-config) 9# 10# Configuration example: 11# 12# [wget_page] 13# timeout 30 14# env.names url1 url2 15# env.timeout 20 16# env.error_value 60 17# env.max 120 18# 19# env.url_url1 http://www1.example.com/path1/page1 20# env.label_url1 Example URL#1 21# env.timeout_url1 10 22# env.warning_url1 5 23# env.critical_url1 8 24# 25# env.url_url2 https://www2.example.com/path2/page2 26# env.label_url2 Example URL#2 27# env.timeout_url2 30 28# env.warning_url2 15 29# env.critical_url2 20 30# env.wget_opts_url2 --no-cache --tries=1 --no-check-certificate 31# 32# URL options: 33# 34# You can define the following options for each specified URL 35# as seen in the above example. 36# 37# - url: the URL to be downloaded with Wget 38# - label: the label assigned to the line of the given in URL in the graph 39# - timeout: the value passed to Wget through the "--timeout" option. 40# - warning: the value for the given URL that stands for the warning level 41# - critical: the value for the given URL that stands for the critical level 42# - max: the maximum value for the given URL (values above this will be 43# discarded) 44# - error_value: the value for the given URL that will be used to mark when 45# Wget returned an error. A zero error_value causes the plugin to ignore 46# Wget's return value. 47# - regex_error_value: the value for the given URL that will be used to mark 48# when a regular expression match failed (either for the HTTP response 49# headers or the body). 50# - regex_header_<n>: a regular expression that the HTTP response header must 51# match or the plugin will return regex_error_value for the given URL. 52# By default the plugin uses egrep, thus extended regexps are expected. 53# You can define any number of regexps, but you've to start the index at 54# "1" and increase it sequentially. 55# I.e. regex_header_1, regex_header_2, ... 56# - regex_body_<n>: same as regex_header_<n>, but matches the HTTP response 57# body. 58# - grep_opts: various options supplied to grep for regexp matches for the 59# given URL. By default these are: -E (use of extended regexps) 60# and -i (case insensitive regexp matching) 61# - wget_opts: various options supplied to the Wget command for the given URL. 62# - join_lines: if "true" and regexp matching is applied, the HTTP response body 63# is stripped of newline ("\n") characters. This helps with complex regexps 64# since grep can match only in a single line at a time and it would not be 65# possible to match on complex HTML/XML structures otherwise. 66# This is enabled by default. 67# 68# $Log$ 69# 70# Revision 1.0 2006/07/11 08:49:43 cipixul@gmail.com 71# Initial version 72# 73# Revision 2.0 2010/03/25 13:46:13 muzso@muzso.hu 74# Rewrote most of the code. Added multips-like options. 75# 76# Revision 2.1 2010/04/22 11:43:53 muzso@muzso.hu 77# Added regular expression matching against the contents of the checked URL. 78# 79# Revision 2.2 2010/04/23 15:21:12 muzso@muzso.hu 80# Bugfix. Regexp matching on HTTP response bodies with a trailing newline 81# was flawed. 82# 83#%# family=auto 84#%# capabilities=autoconf 85 86[ -n "${wget_bin}" ] || wget_bin=$(which wget) 87[ -n "${time_bin}" ] || time_bin=$(which time) 88[ -n "${mktemp_bin}" ] || mktemp_bin=$(which mktemp) 89[ -n "${grep_bin}" ] || grep_bin=$(which grep) 90[ -n "${tail_bin}" ] || tail_bin=$(which tail) 91 92default_error_value=30 93default_regex_error_value=40 94default_grep_opts="-E -i" 95default_wget_opts="--no-cache --tries=1" 96default_timeout=20 97default_join_lines=true 98 99if [ "${1}" = "autoconf" ]; then 100 if [ -z "$wget_bin" ] || [ ! -f "$wget_bin" ] || [ ! -x "$wget_bin" ]; then 101 echo "no (missing 'wget' executable)" 102 elif [ -z "$time_bin" ] || [ ! -f "$time_bin" ] || [ ! -x "$time_bin" ]; then 103 echo "no (missing 'time' executable)" 104 elif [ -z "$mktemp_bin" ] || [ ! -f "$mktemp_bin" ] || [ ! -x "$mktemp_bin" ]; then 105 echo "no (missing 'mktemp' executable)" 106 elif [ -z "$grep_bin" ] || [ ! -f "$grep_bin" ] || [ ! -x "$grep_bin" ]; then 107 echo "no (missing 'grep' executable)" 108 elif [ -z "$tail_bin" ] || [ ! -f "$tail_bin" ] || [ ! -x "$tail_bin" ]; then 109 echo "no (missing 'tail' executable)" 110 else 111 echo "yes" 112 fi 113 exit 0 114fi 115 116if [ -z "${names}" ]; then 117 echo "Configuration required" 118 exit 1 119fi 120 121[ -n "${error_value}" ] || error_value=${default_error_value} 122[ -n "${regex_error_value}" ] || regex_error_value=${default_regex_error_value} 123[ -n "${grep_opts}" ] || grep_opts=${default_grep_opts} 124[ -n "${wget_opts}" ] || wget_opts=${default_wget_opts} 125[ -n "${timeout}" ] || timeout=${default_timeout} 126[ -n "${join_lines}" ] || join_lines=${default_join_lines} 127[ -n "${warning}" ] || warning=$((timeout/2)) 128[ -n "${critical}" ] || critical=${timeout} 129[ -n "${max}" ] || max=$((timeout*2)) 130 131if [ "${1}" = "config" ]; then 132 echo "graph_title wget loadtime of webpages" 133 echo "graph_args --base 1000 -l 0" 134 echo "graph_scale no" 135 echo "graph_vlabel Load time in seconds" 136 echo "graph_category webserver" 137 echo "graph_info This graph shows load time in seconds of one or more urls" 138 I=1 139 for name in ${names}; do 140 eval iurl='${url_'${name}'}' 141 if [ -n "${iurl}" ]; then 142 eval ilabel='${label_'${name}':-url${I}}' 143 eval iwarning='${warning_'${name}':-${warning}}' 144 eval icritical='${critical_'${name}':-${critical}}' 145 eval imax='${max_'${name}':-${max}}' 146 cat << EOH 147loadtime${I}.label ${ilabel} 148loadtime${I}.info Load time for ${iurl} 149loadtime${I}.min 0 150loadtime${I}.max ${imax} 151EOH 152 [ ${iwarning} -gt 0 ] && echo "loadtime${I}.warning ${iwarning}" 153 [ ${icritical} -gt 0 ] && echo "loadtime${I}.critical ${icritical}" 154 I=$((I+1)) 155 fi 156 done 157 exit 0 158fi 159 160I=1 161for name in ${names}; do 162 eval iurl='${url_'${name}'}' 163 if [ -n "${iurl}" ]; then 164 eval ierror_value='${error_value_'${name}':-${error_value}}' 165 eval iregex_error_value='${regex_error_value_'${name}':-${regex_error_value}}' 166 eval igrep_opts='${grep_opts_'${name}':-${grep_opts}}' 167 eval iwget_opts='${wget_opts_'${name}':-${wget_opts}}' 168 eval iwget_post_data='${wget_post_data_'${name}':-${wget_post_data}}' 169 eval ijoin_lines='${join_lines_'${name}':-${join_lines}}' 170 eval itimeout='${timeout_'${name}':-${timeout}}' 171 loadtime="" 172 tempfile=$(mktemp) 173 if [ -z "${iwget_post_data}" ]; then 174 timing=$(${time_bin} -p ${wget_bin} --save-headers --no-directories --output-document "${tempfile}" --timeout ${itimeout} ${iwget_opts} "${iurl}" 2>&1) 175 else 176 timing=$(${time_bin} -p ${wget_bin} --post-data "${iwget_post_data}" --save-headers --no-directories --output-document "${tempfile}" --timeout ${itimeout} ${iwget_opts} "${iurl}" 2>&1) 177 fi 178 wget_result=$? 179 if [ -f "${tempfile}" ]; then 180 if [ ${wget_result} -ne 0 -a ${ierror_value} -gt 0 ]; then 181 loadtime=${ierror_value} 182 else 183 tempheader="" 184 tempbody="" 185 K=0 186 while [ -z "${loadtime}" ]; do 187 K=$((K+1)) 188 eval iregex_header='${regex_header_'${K}'_'${name}':-${regex_header_'${K}'}}' 189 eval iregex_body='${regex_body_'${K}'_'${name}':-${regex_body_'${K}'}}' 190 [ -z "${iregex_header}" -a -z "${iregex_body}" ] && break 191 if [ ${K} -eq 1 ]; then 192 OIFS="${IFS}" 193 # we skip carriage return characters from the end of header lines 194 IFS=$(echo -en "\r") 195 inheader=0 196 # The "read" command reads only lines terminated by a specific 197 # character (which by default the newline char). 198 # To read the end of the file (the bytes after the last newline) too 199 # we append a newline. 200 echo "" >> "${tempfile}" 201 while read -r line; do 202 if [ -z "${line}" ]; then 203 inheader=1 204 # We reached the border of the header and the body. 205 # Setting IFS to an empty string puts the entire read lines from 206 # the body into our "line" variable. 207 IFS="" 208 else 209 if [ ${inheader} -eq 0 ]; then 210 tempheader="${tempheader}${line} 211" 212 else 213 if [ "${ijoin_lines}" = "true" ]; then 214 tempbody="${tempbody}${line}" 215 else 216 tempbody="${tempbody}${line} 217" 218 fi 219 fi 220 fi 221 done < "${tempfile}" 222 IFS="${OIFS}" 223 fi 224 if [ -n "${iregex_header}" ] && ! echo "${tempheader}" | ${grep_bin} -qs ${igrep_opts} "${iregex_header}" 2> /dev/null; then 225 loadtime=${iregex_error_value} 226 else 227 if [ -n "${iregex_body}" ] && ! echo "${tempbody}" | ${grep_bin} -qs ${igrep_opts} "${iregex_body}" 2> /dev/null; then 228 loadtime=${iregex_error_value} 229 fi 230 fi 231 done 232 if [ -z "${loadtime}" ]; then 233 loadtime=$(echo "${timing}" | grep "^real *[0-9]" | cut -d ' ' -f 2) 234 fi 235 fi 236 rm -f "${tempfile}" > /dev/null 2>&1 237 else 238 loadtime=$((ierror_value*2)) 239 fi 240 echo "loadtime${I}.value ${loadtime}" 241 I=$((I+1)) 242 fi 243done 244 245