#!/usr/bin/bash #---------------------------------------------------------------------- IFS=$'\n' \ SITES=("$@") TIMEOUT=${TIMEOUT:=10} HTTP_TRIES=${HTTP_TRIES:=2} HTTP_SAFE=${HTTP_SAFE:=no} HTTP_OK_STATUS=${HTTP_OK_STATUS:='2[0-9][0-9]|30[1-9]|401|501'} #---------------------------------------------------------------------- # Help... case $1 in -h|--help) echo "Do a status check on URL(s)." echo echo "Suage:" echo " `basename $0` URL ..." echo # XXX would be fun to make the docs dynamic... echo "Supported URL formats and schemes:" echo " http://" echo " https://" echo " Check if is reachable via http/https." echo " ssh://[:]" echo " Check if has an open port with a listening ssh server." echo " git://[:]" echo " The same as ssh://..." echo " ovpn://[:]" echo " Check if an OpenVPN server is listening on ." echo " NOTE: this will not work if 'tls-auth' is enabled but the thing was" echo " already implemented when I found out about this." echo " lxc://::" echo " Proxmox-specific set of checks." echo exit ;; *) ;; esac #---------------------------------------------------------------------- source .pct-helpers #---------------------------------------------------------------------- # Handlers... declare -A HANDLERS # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # Port # # tcp://: # udp://: # HANDLERS[tcp]=check-port HANDLERS[udp]=check-port # XXX this seems to be broken... check-port(){ local udp= if [[ "${1:0:3}" == "udp" ]] ; then udp='u' fi local target=`sed \ -e 's/^.*\s*\(tcp\|udp\):\/\///' \ -e 's/^\s*//;s/\s*$//' \ <<<$1` local port=`cut -sd ':' -f 2 <<<$target` port=${port:=80} target=`cut -d ':' -f 1 <<<$target` local res=$(timeout $TIMEOUT nc -vz${udp} $target $port 2>&1) if ! [[ $res =~ .*open$ ]] ; then echo ERROR else echo OK fi } # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # Proxmox lxc # # lxc://:: # # supported commands: # status: # ip:= # service:= # HANDLERS[lxc]=check-lxc declare -A LXC_HANDLERS LXC_HANDLERS[status]=check-lxc-status check-lxc-status(){ local status=`pct status $1` status=${status/status: /} [ "$status" = "$2" ] \ && echo "OK" \ || echo "ERROR" } LXC_HANDLERS[ip]=check-lxc-ip check-lxc-ip(){ local dev=${2/=*/} local ip=${2/*=/} local res=$(\ lxc-attach $1 ip a show dev $dev \ | awk '/inet / {print $2}') [ "$ip" = "$res" ] \ && echo "OK" \ || echo "ERROR" } LXC_HANDLERS[service]=check-lxc-service check-lxc-service(){ local service=${2/=*/} local status=${2/*=/} local res=$(\ lxc-attach $1 systemctl status $service \ | awk '/Active: / {print $2}') [ "$status" = "$res" ] \ && echo "OK" \ || echo "ERROR" } check-lxc(){ local target=`sed \ -e 's/^.*\s*lxc:\/\///' \ -e 's/^\s*//;s/\s*$//' \ <<<$1` local cmd=`sed 's/^[^:]*://' <<<$target` target=${target/:*/} local value=`sed 's/^[^:]*://' <<<$cmd` cmd=${cmd/:*/} if [ -z ${LXC_HANDLERS[$cmd]} ] ; then echo "ERROR (unknown command: $cmd)" return fi ${LXC_HANDLERS[$cmd]} "$target" "$value" } # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # OpenVPN # # NOTE: this will not work if 'tls-auth' is enabled... HANDLERS[ovpn]=check-ovpn check-ovpn(){ local target=`sed \ -e 's/^.*\s*ovpn:\/\///' \ -e 's/^\s*//;s/\s*$//' \ <<<$1` local port=`cut -sd ':' -f 2 <<<$target` port=${port:=1194} target=`cut -d ':' -f 1 <<<$target` local res=$(echo -e "\x38\x01\x00\x00\x00\x00\x00\x00\x00" \ | timeout $TIMEOUT nc -u $target $port \ | cat -v) if [ -z $res ] ; then echo ERROR else echo OK fi } # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # SSH HANDLERS[ssh]=check-ssh HANDLERS[git]=check-ssh check-ssh(){ local target=`sed \ -e 's/^.*\s*\(ssh\|git\):\/\///' \ -e 's/^\s*//;s/\s*$//' \ <<<$1` local port=`cut -sd ':' -f 2 <<<$target` port=${port:=22} target=`cut -d ':' -f 1 <<<$target` # open port... response=$(\ [ $(sleep $TIMEOUT \ | telnet $target $port 2> /dev/null \ | grep SSH) ] \ && echo "OK" \ || echo "ERROR" ) echo $response } # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # HTTP/HTTPS HANDLERS[http]=check-http HANDLERS[https]=check-http status_pattern="\(${HTTP_OK_STATUS//|/\\|}\)" check-http(){ local target=`sed \ -e 's/^.*\s*\(https\?:\/\/\)/\1/' \ -e 's/^\s*//;s/\s*$//' \ <<<$1` # http/https if [ "$HTTP_SAFE" = "no" ] ; then local safe=--no-check-certificate else local safe fi local response=$(\ wget -S --spider -T $TIMEOUT --tries=$HTTP_TRIES $safe $target 2>&1 \ | awk '/HTTP\// {print $2}' ) if [ "$(grep "$status_pattern" <<<$response)" ] ; then response=OK else if [ -z $response ] ; then response='ERROR: TIMEOUT' else response="ERROR: $response" fi fi echo $response } # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - PROTOCOLS=$(printf "\\|%s" "${!HANDLERS[@]}") PROTOCOLS=${PROTOCOLS:2} check(){ # NOTE: we are preserving whitespace here... local comment=`sed \ -e 's/^\(.*\)\('"$PROTOCOLS"'\):\/\/.*$/\1/' \ -e 's/\s*$//' \ <<<$1` local target=`sed \ -e 's/^.*\s*\(\('"$PROTOCOLS"'\):\/\/\)/\1/' \ -e 's/^\s*//;s/\s*$//' \ <<<$1` local scheme=`sed 's/\('"$PROTOCOLS"'\):\/\/.*/\1/' \ <<<$target` echo "COMMENT=$comment" echo "URL=$target" # call the checker... echo "RESPONSE=$(${HANDLERS[$scheme]} "$target")" } #---------------------------------------------------------------------- problems= for site in ${SITES[@]} ; do # skip things we do not recognize... if ! [ "$(grep "$PROTOCOLS://" <<<$site)" ] ; then echo $site continue fi IFS=$'\n' \ res=($(check "$site")) comment="${res[0]/COMMENT=/}" site=${res[1]/URL=/} res=${res[2]/RESPONSE=/} if [ -z $res ] ; then res='Timeout?' fi ! [ -z $comment ] \ && comment="$comment " echo "${comment}${site} : ${res}" done if [ $problems ] ; then exit 1 fi #---------------------------------------------------------------------- # vim:set ts=4 sw=4 :