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

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 :

# (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://'`

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 ]
   echo "EAV exceeded runtime needed to kill ${IP}:${PORT}" | logger -p local0.error
   kill -9 `cat $PIDFILE` > /dev/null 2>&1
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 ]
    # Remove the PID file
    rm -f $PIDFILE

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

Published Mar 12, 2015
Version 1.0

Was this article helpful?


  • 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.




    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: 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 ]