Windows File Share Monitor SMB CIFS

Problem this snippet solves:

This external monitor performs a health check of a Windows file share using CIFS/Samba. There is an inbuilt SMB monitor for LTM. However, GTM does not (yet?) have this.

See the comments in the script for details on how to implement it. Please post any questions about this monitor in the Advanced Design/Config forum

Code :

#!/bin/bash

# Samba (CIFS) external monitor script
#
# Use smbget to perform a health check of an SMB/CIFS pool member IP address and port for LTM or GTM
#
# v0.3 - 2011-04-20 - Aaron Hooley - F5 Networks - hooleylists at gmail dot com - Initial version tested on 10.2.1 LTM and GTM
#
# Save this script as /usr/bin/monitors/smb_monitor.bash
# Make executable using chmod 755 /usr/bin/monitors/smb_monitor.bash
#
# Example LTM monitor which references this script:
#
#monitor smb_external_monitor {
#   defaults from external
#   DEBUG "1"
#   FILE "/share/test.txt"
#   PASSWORD "Test123!"
#   run "smb_monitor.bash"
#   SEARCH_STRING "got it"
#   USERNAME "aaron"
#}
#
# Example GTM monitor which references this script:
#monitor "smb_external_monitor" {
#   defaults from "external"
#   interval 10
#   timeout 40
#   probe_interval 1
#   probe_timeout 5
#   probe_num_probes 1
#   probe_num_successes 1
#   dest *:*
#   "SEARCH_STRING" "got it"
#   "DEBUG" "1"
#   run "smb_monitor.bash"
#   "USERNAME" "aaron"
#   "FILE" "/share/test.txt"
#   args ""
#   "PASSWORD" "Test123!"
#   partition "Common"
#}

# Log debug to local0.debug (/var/log/ltm)?
# Check if a variable named DEBUG exists from the monitor definition
# This can be set using a monitor variable DEBUG=0 or 1
if [ -n "$DEBUG" ]
then
if [ $DEBUG -eq 1 ]
then
logger -p local0.debug "EAV `basename $0` (PID $$): Start of PID $$"
logger -p local0.debug "EAV `basename $0` (PID $$): \$DEBUG: $DEBUG"
fi
else
# If the monitor config didn't specify debug, enable/disable it here
DEBUG=0
#logger -p local0.debug "EAV `basename $0` (PID $$): \$DEBUG: $DEBUG"
fi

# If user and pass are both not set, then use anonymous/guest access for the server
if [ "x$USERNAME" = "x" ] && [ "x$PASSWORD" = "x" ]
then
        GUEST_FLAG="--guest"
        if [ $DEBUG -eq 1 ]; then logger -p local0.debug "EAV `basename $0` (PID $$): No username and no password specified, using guest access"; fi
else
        GUEST_FLAG=""
fi

# Check if a variable named USERNAME exists from the monitor definition
# This can be set using a monitor variable USERNAME=my_username
if [ -n "$USERNAME" ]
then
        if [ $DEBUG -eq 1 ]; then logger -p local0.debug "EAV `basename $0` (PID $$): Username: $USERNAME"; fi
USERNAME="-u $USERNAME"
else
if [ $DEBUG -eq 1 ]; then logger -p local0.debug "EAV `basename $0` (PID $$): No username specified"; fi
USERNAME=''
fi

# Check if a variable named PASSWORD exists from the monitor definition
# This can be set using a monitor variable PASSWORD=my_password
if [ -n "$PASSWORD" ]
then
        if [ $DEBUG -eq 1 ]; then logger -p local0.debug "EAV `basename $0` (PID $$): Password: $PASSWORD"; fi
# Set the password flag
PASSWORD="-p $PASSWORD"
else
if [ $DEBUG -eq 1 ]; then logger -p local0.debug "EAV `basename $0` (PID $$): No password specified"; fi
PASSWORD=''
fi

# Check if a variable named FILE exists from the monitor definition
# This can be set using a monitor variable FILE=/path/to/file.txt
if [ -n "$FILE" ]
then
# Replace \ with / for *nix paths
FILE=${FILE//\\/\//replacement}
if [ $DEBUG -eq 1 ]; then logger -p local0.debug "EAV `basename $0` (PID $$): Checking \$FILE: $FILE"; fi
else
FILE="/"
logger -p local0.notice "EAV `basename $0` (PID $$): \$FILE is not defined, checking smb://$IP/"
fi

# Remove IPv6/IPv4 compatibility prefix (LTM passes addresses in IPv6 format)
IP=`echo $1 | sed 's/::ffff://'`

# Save the port for use in the shell command.  smbget doesn't seem to support a port other than 445.
PORT=$2
if [ "$PORT" != 445 ]
then
logger -p local0.debug "EAV `basename $0` (PID $$): Port $PORT will be ignored. This monitor only supports port 445 due to smbget limitation."
fi

# Check if there is a prior instance of the monitor running
pidfile="/var/run/`basename $0`.$IP.$PORT.pid"
if [ -f $pidfile ]
then
kill -9 `cat $pidfile` > /dev/null 2>&1
logger -p local0.debug "EAV `basename $0` (PID $$): Exceeded monitor interval, needed to kill past check for ${IP}:${PORT} with PID `cat $pidfile`"
fi

# Add the current PID to the pidfile
echo "$$" > $pidfile

if [ $DEBUG -eq 1 ]; then logger -p local0.debug "EAV `basename $0` (PID $$): Running for ${IP}:${PORT}"; fi

# Send the request and check the response.  If we have a string to search for, use grep to look for it.
# Check if a variable named SEARCH_STRING exists from the monitor definition
# This can be set using a monitor variable SEARCH_STRING=my_string
if [ -n "$SEARCH_STRING" ]
then
        SUCCESS_STATUS=0
if [ $DEBUG -eq 1 ]; then logger -p local0.debug "EAV `basename $0` (PID $$): Checking ${IP}${FILE} for "$SEARCH_STRING" with status of $SUCCESS_STATUS using\
smbget $USERNAME $PASSWORD $GUEST_FLAG --nonprompt --quiet --stdout smb://${IP}${FILE} | grep \"$SEARCH_STRING\" 1>/dev/null 2>/dev/null"; 
fi
smbget $USERNAME $PASSWORD $GUEST_FLAG --nonprompt --quiet --stdout smb://${IP}${FILE} | grep $SEARCH_STRING 2>&1 > /dev/null
else
        SUCCESS_STATUS=1
if [ $DEBUG -eq 1 ]; then logger -p local0.debug "EAV `basename $0` (PID $$): Checking ${IP}${FILE} with status of $SUCCESS_STATUS using\
smbget $USERNAME $PASSWORD $GUEST_FLAG --nonprompt --quiet --stdout smb://${IP}${FILE} 1>/dev/null 2>/dev/null";
fi
smbget $USERNAME $PASSWORD $GUEST_FLAG --nonprompt --quiet --stdout smb://${IP}${FILE} 1>/dev/null 2>/dev/null
fi

# Check if the command ran successfully
#
# For some reason, smbget returns a status of 1 for success which is the opposite of typical commands.  See this page (or its cache) for details:
# http://bugs.opensolaris.org/bugdatabase/view_bug.do?bug_id=6828364
# http://webcache.googleusercontent.com/search?q=cache:Ef3KgrvGnygJ:bugs.opensolaris.org/bugdatabase/view_bug.do%3Fbug_id%3D6828364+&cd=2&hl=en&ct=clnk&gl=us
#
# Note that any standard output will result in the script execution being stopped
# So do any cleanup before echoing to STDOUT
if [ $? -eq $SUCCESS_STATUS ]
then
rm -f $pidfile
if [ $DEBUG -eq 1 ]; then logger -p local0.debug "EAV `basename $0` (PID $$): Succeeded for ${IP}:${PORT}"; fi
echo "UP"
else
rm -f $pidfile
if [ $DEBUG -eq 1 ]; then logger -p local0.debug "EAV `basename $0` (PID $$): Failed for ${IP}:${PORT}"; fi
fi
Published Mar 12, 2015
Version 1.0

Was this article helpful?

2 Comments

  • steve2's avatar
    steve2
    Icon for Nimbostratus rankNimbostratus

    I am trying to use this script on a GTM running 11.6, without much luck. The config of the monitor is below, I have made sure the external monitor file is on all prober pool members (which are 2 GTMs that are in this cluster). It is marked down and I get no debugs in the ltm log file. Any clues?

     

    the GTM log file reports:

     

    Monitor instance /Common/MON-EXTERNAL-CSMACSRV-30 1.2.3.4:445 UNKNOWN_MONITOR_STATE --> DOWN from 1.2.3.4 (state returned down)

     

    SNMP_TRAP: VS VIP-CSMACSRV01-445 (ip:port=1.2.3.4:445) (Server /Common/server1) state change blue --> red ( Monitor /Common/MON-EXTERNAL-CSMACSRV-30 from 10.16.4.5 : state returned down)

     

    gtm monitor external /Common/MON-EXTERNAL-CSMACSRV-30 { defaults-from /Common/external description "External Monitor to check NAS File Share" destination : interval 30 probe-timeout 5 run /Common/smb_monitor.bash timeout 121 user-defined DEBUG 1 user-defined FILE /CS_Storage/F5GTMTST.txt user-defined PASSWORD password user-defined SEARCH_STRING up user-defined USERNAME domain\admin >>>I have tried including and excluding the domain<<<