HTTP Monitor cURL Basic POST

Problem this snippet solves:

External HTTP monitor script that sends a POST request to the pool member to which it is applied, marking it up if the expected response is received. URI, POST data, and response string are user-configurable. cURL by default uses HTTP/1.1 and, since no hostname is specified in the cURL command, inserts the IP address in the Host header.

NOTE: Use external monitors only when a built-in monitor won't do the trick. This monitor is intended as an example of using cURL (which offers a large number of other useful options) to perform a POST. More basic HTTP monitors are much more efficiently configured using the built-in HTTP monitor template instead.

UPDATE: The script below had a logic error in it where by it was using the NODE and PORT variables to create a PID file before the variables were defined. This meant that if your monitor took long enough to run the PID running monitor was killed before it finished and a new process ran in its place. This gave the appearence of the monitor not functioning correctly. I have corrected this below.

How to use this snippet:

  1. Create a new file containing the code below in /usr/bin/monitors on the LTM filesystem. Permissions on the file must be 700 or better, giving root rwx access to the file.
  2. Create a monitor profile of type "External" with the following values:

    • External Program: . . the name of the script file created in step 1
    • Variables:
      • Name.......Value
      • URI . . . . .the URI to which the POST will be sent (URI only, no hostname)
      • DATA . . . . the POST data to be sent to the server
      • RECV . . . . the expected response
  3. Adjust the interval and timeout as appropriate for your application

Jan  3 00:00:00 local/bigip err logger: EAV exceeded runtime needed to kill 10.0.0.10:80

If the interval and timeout is smaller then the execution time of the script, the monitor marks the element down and logs a message in /var/log/ltm. This is a false negative. To fix this, please increase the interval and timeout accordingly.

Code :

#!/bin/sh
#
# (c) Copyright 1996-2007 F5 Networks, Inc.
#
# This software is confidential and may contain trade secrets that are the
# property of F5 Networks, Inc.  No part of the software may be disclosed
# to other parties without the express written consent of F5 Networks, Inc.
# It is against the law to copy the software.  No part of the software may
# be reproduced, transmitted, or distributed in any form or by any means,
# electronic or mechanical, including photocopying, recording, or information
# storage and retrieval systems, for any purpose without the express written
# permission of F5 Networks, Inc.  Our services are only available for legal
# users of the program, for instance in the event that we extend our services
# by offering the updating of files via the Internet.
#
# @(#) $Id: http_monitor_cURL+POST,v 1.0 2007/06/28 16:36:11 deb Exp $
# (based on sample_monitor,v 1.3 2005/02/04 18:47:17 saxon)
#

#
# these arguments supplied automatically for all external monitors:
# $1 = IP (nnn.nnn.nnn.nnn notation)
# $2 = port (decimal, host byte order)
#
# additional command line arguments ($3 and higher) may be specified in the monitor template
# This example does not expect any additional command line arguments
#
# Name/Value pairs may also be specified in the monitor template
# This example expects the following Name/Value pairs:
#  URI  = the URI to which the POST will be sent
#  DATA = the POST data to send to the server
#  RECV = the expected response (not case sensitive)
#
# remove IPv6/IPv4 compatibility prefix (LTM passes addresses in IPv6 format)
NODE=`echo ${1} | sed 's/::ffff://'`
PORT=${2}

PIDFILE="/var/run/`basename ${0}`.${NODE}_${PORT}.pid"
# kill of the last instance of this monitor if hung and log current pid
if [ -f $PIDFILE ]
then
   echo "EAV exceeded runtime needed to kill ${IP}:${PORT}" | logger -p local0.error
   kill -9 `cat $PIDFILE` > /dev/null 2>&1
fi
echo "$$" > $PIDFILE

# send request & check for expected response
curl -fNs http://${NODE}:${PORT}${URI} -d "${DATA}" | grep -i "${RECV}" 2>&1 > /dev/null

# mark node UP if expected response was received
if [ $? -eq 0 ]
then
    # Remove the PID file
    rm -f $PIDFILE

    echo "UP"
else
    # Remove the PID file
    rm -f $PIDFILE
fi

exit
Published Mar 12, 2015
Version 1.0

Was this article helpful?

2 Comments

  • lol, and still no example of the actual command use....Dev Central notorious for lack of command examples

     

  • The above steps might not exactly work, but are good enough to point you in the right directions.

     

    STEPS:

     

    1. Copy the script
    2. Paste it on your textpad (notepad, etc)
    3. Import the script System > File Management > External Monitor Program File List
    4. Once the import is completed, a file is automatically generated under /config/filestore/files_d/Common_d/external_monitor_d.
    5. In this example the name if the created file is curl_monitor_ex_68725_1
    6. Run the following command
    7. sed -i 's/\r$//' /config/filestore/files_d/Common_d/external_monitor_d/\:Common\:curl_monitor_ex_68725_1
    8. Create the monitor and attach it to the pool

     

    STEP #7 in an important step. If STEP 7 is skipped then you can see the following errors in /var/log/monitors/<name> (if monitor logging is enabled)

     

    l_up=0 immed=0 next_ping=[1564634525.155247][2019-08-01 12:42:05] last_ping=[1564634520.236345][2019-08-01 12:42:00] deadline=[1564634523.946757][2019-08-01 12:42:03] on_service_list=True snd_cnt=12 rcv_cnt=0 ]

    [0][6419] 2019-08-01 12:42:00.237862: ID 79  :(spawn_external_pinger): EAV execve: No such file or directory

    [0][6419] 2019-08-01 12:42:00.238338: ID 79  :(_main_loop): Service ready for read, now=[1564634520.238304][2019-08-01 12:42:00] [ addr=::ffff:10.200.143.252:80 srcaddr=::%0:0 fd=13 pend=0 #conn=0 ]

    [0][6419] 2019-08-01 12:42:00.238374: ID 79  :(_recv_external_node_ping): reading [ addr=::ffff:x.x.x.x:80 ]

    [0][6419] 2019-08-01 12:42:00.238397: ID 79  :(recv_external_node_ping): EAV failed [ addr=::ffff:x.x.x.x:80 ]

    [0][6419] 2019-08-01 12:42:00.238421: ID 79  :(_kill_external_pinger): killing pid=2642 [ addr=::ffff:x.x.x.x:80 fd=13 ]