#!/bin/bash # ********************************************************************** # Pandora FMS Generic Linux Agent # (c) 2010 Artica Soluciones Tecnológicas # with the help of many people. Please see http://pandorafms.org # This code is licensed under GPL 2.0 license. # ********************************************************************** AGENT_VERSION=3.1 AGENT_BUILD=100516 # ********************************************************************** # function configure_agent() # Parses the configuration file and configures the agent. # ********************************************************************** function configure_agent { # Read config file for a in `cat $PANDORA_HOME/pandora_agent.conf | grep -v -e "^#" | grep -v -e "^module" ` do a=`echo $a | tr -s " " " "` # Get general configuration parameters from config file if [ ! -z "`echo $a | grep -e '^logfile'`" ] then PANDORA_LOGFILE=`echo $a | awk '{ print $2 }' ` echo "$TIMESTAMP - [SETUP] - Pandora Logfile is $PANDORA_LOGFILE" >> $PANDORA_LOGFILE elif [ ! -z "`echo $a | grep -e '^server_ip'`" ] then SERVER_IP=`echo $a | awk '{ print $2 }' ` echo "$TIMESTAMP - [SETUP] - Server IP Address is $SERVER_IP" >> $PANDORA_LOGFILE elif [ ! -z "`echo $a | grep -e '^server_path'`" ] then SERVER_PATH=`echo $a | awk '{ print $2 }' ` echo "$TIMESTAMP - [SETUP] - Server Path is $SERVER_PATH" >> $PANDORA_LOGFILE elif [ ! -z "`echo $a | grep -e '^temporal'`" ] then TEMP=`echo $a | awk '{ print $2 }' ` echo "$TIMESTAMP - [SETUP] - Temporal Path is $TEMP" >> $PANDORA_LOGFILE elif [ ! -z "`echo $a | grep -e '^interval'`" ] then INTERVAL=`echo $a | awk '{ print $2 }' ` echo "$TIMESTAMP - [SETUP] - Interval is $INTERVAL seconds" >> $PANDORA_LOGFILE elif [ ! -z "`echo $a | grep -e '^agent_name'`" ] then NOMBRE_HOST=`echo $a | awk '{ print $2 }' ` echo "$TIMESTAMP - [SETUP] - Agent name is $NOMBRE_HOST " >> $PANDORA_LOGFILE elif [ ! -z "`echo $a | grep -e '^debug'`" ] then DEBUG_MODE=`echo $a | awk '{ print $2 }' ` echo "$TIMESTAMP - [SETUP] - Debug mode is $DEBUG_MODE " >> $PANDORA_LOGFILE # Contribution of daggett elif [ ! -z "`echo $a | grep -e '^server_port'`" ] then SERVER_PORT=`echo $a | awk '{ print $2 }' ` echo "$TIMESTAMP - [SETUP] - Server Port is $SERVER_PORT" >> $PANDORA_LOGFILE # Contribution of daggett elif [ ! -z "`echo $a | grep -e '^encoding'`" ] then ENCODING=`echo $a | awk '{ print $2 }' ` echo "$TIMESTAMP - [SETUP] - Encoding is $ENCODING" >> $PANDORA_LOGFILE elif [ ! -z "`echo $a | grep -e '^transfer_mode'`" ] then TRANSFER_MODE=`echo $a | awk '{ print $2 }' ` echo "$TIMESTAMP - [SETUP] - Transfer Mode is $TRANSFER_MODE" >> $PANDORA_LOGFILE elif [ ! -z "`echo $a | grep -e '^delayed_startup'`" ] then DELAYED_STARTUP=`echo $a | awk '{ print $2 }' ` echo "$TIMESTAMP - [SETUP] - DELAYED_STARTUP is $DELAYED_STARTUP" >> $PANDORA_LOGFILE # CPU protection elif [ ! -z "`echo $a | grep -e '^pandora_nice'`" ] then PANDORA_NICE=`echo $a | awk '{ print $2 }' ` echo "$TIMESTAMP - [SETUP] - PandoraFMS Nice is $PANDORA_NICE" >> $PANDORA_LOGFILE # Tentacle options elif [ ! -z "`echo $a | grep -e '^server_pwd'`" ] then SERVER_PWD=`echo $a | awk '{ print $2 }' ` if [ ! -z "$SERVER_PWD" ] then TENTACLE_OPTS="-x $SERVER_PWD $TENTACLE_OPTS" echo "$TIMESTAMP - [SETUP] - Server password set (FTP/Tentacle)" >> $PANDORA_LOGFILE fi elif [ ! -z "`echo $a | grep -e '^server_ssl'`" ] then SERVER_SSL=`echo $a | awk '{ print $2 }' ` if [ "$SERVER_SSL" == "yes" ] then TENTACLE_OPTS="-c $TENTACLE_OPTS" echo "$TIMESTAMP - [SETUP] - OpenSSL enabled for Tentacle" >> $PANDORA_LOGFILE fi elif [ ! -z "`echo $a | grep -e '^cron_mode'`" ] then CRON_MODE=1 echo "$TIMESTAMP - [SETUP] - Cronmode enabled" >> $PANDORA_LOGFILE elif [ ! -z "`echo $a | grep -e '^server_opts'`" ] then SERVER_OPTS=`echo $a | cut -d" " -f2-` if [ ! -z "$SERVER_OPTS" ] then TENTACLE_OPTS="$SERVER_OPTS $TENTACLE_OPTS" echo "$TIMESTAMP - [SETUP] - Extra options for the Tentacle client $SERVER_OPTS" >> $PANDORA_LOGFILE fi # Remote configuration elif [ ! -z "`echo $a | grep -e '^remote_config'`" ] then REMOTE_CONFIG=`echo $a | awk '{ print $2 }'` if [ "$REMOTE_CONFIG" == "1" ] then echo "$TIMESTAMP - [SETUP] - Remote configuration enabled" >> $PANDORA_LOGFILE fi # Secondary server configuration elif [ ! -z "`echo $a | grep -e '^secondary_mode'`" ] then SECONDARY_MODE=`echo $a | awk '{ print $2 }' ` echo "$TIMESTAMP - [SETUP] - Secondary server mode is '$SECONDARY_MODE'" >> $PANDORA_LOGFILE elif [ ! -z "`echo $a | grep -e '^secondary_transfer_mode'`" ] then SECONDARY_TRANSFER_MODE=`echo $a | awk '{ print $2 }' ` echo "$TIMESTAMP - [SETUP] - Secondary transfer Mode is $SECONDARY_TRANSFER_MODE" >> $PANDORA_LOGFILE elif [ ! -z "`echo $a | grep -e '^secondary_server_ip'`" ] then SECONDARY_SERVER_IP=`echo $a | awk '{ print $2 }' ` echo "$TIMESTAMP - [SETUP] - Secondary server IP Address is $SECONDARY_SERVER_IP" >> $PANDORA_LOGFILE elif [ ! -z "`echo $a | grep -e '^secondary_server_path'`" ] then SECONDARY_SERVER_PATH=`echo $a | awk '{ print $2 }' ` echo "$TIMESTAMP - [SETUP] - Secondary server Path is $SECONDARY_SERVER_PATH" >> $PANDORA_LOGFILE elif [ ! -z "`echo $a | grep -e '^secondary_server_port'`" ] then SECONDARY_SERVER_PORT=`echo $a | awk '{ print $2 }' ` echo "$TIMESTAMP - [SETUP] - Secondary server Port is $SECONDARY_SERVER_PORT" >> $PANDORA_LOGFILE elif [ ! -z "`echo $a | grep -e '^secondary_server_pwd'`" ] then SECONDARY_SERVER_PWD=`echo $a | awk '{ print $2 }' ` if [ ! -z "$SECONDARY_SERVER_PWD" ] then SECONDARY_TENTACLE_OPTS="-x $SECONDARY_SERVER_PWD $SECONDARY_TENTACLE_OPTS" echo "$TIMESTAMP - [SETUP] - Secondary server password set (FTP/Tentacle)" >> $PANDORA_LOGFILE fi elif [ ! -z "`echo $a | grep -e '^secondary_server_ssl'`" ] then SECONDARY_SERVER_SSL=`echo $a | awk '{ print $2 }' ` if [ "$SECONDARY_SERVER_SSL" == "yes" ] then SECONDARY_TENTACLE_OPTS="-c $SECONDARY_TENTACLE_OPTS" echo "$TIMESTAMP - [SETUP] - OpenSSL enabled for secondary Tentacle" >> $PANDORA_LOGFILE fi elif [ ! -z "`echo $a | grep -e '^secondary_server_opts'`" ] then SECONDARY_SERVER_OPTS=`echo $a | cut -d" " -f2-` if [ ! -z "$SERVER_OPTS" ] then SECONDARY_TENTACLE_OPTS="$SECONDARY_SERVER_OPTS $SECONDARY_TENTACLE_OPTS" echo "$TIMESTAMP - [SETUP] - Extra options for the secondary Tentacle client $SECONDARY_SERVER_OPTS" >> $PANDORA_LOGFILE fi # Agent description elif [ ! -z "`echo $a | grep -e '^description'`" ] then AGENT_DESCRIPTION=`echo $a | cut -d" " -f2-` # Agent group elif [ ! -z "`echo $a | grep -e '^group'`" ] then AGENT_GROUP=`echo $a | cut -d" " -f2-` # Agent autotime (use always current server time) elif [ ! -z "`echo $a | grep -e '^autotime'`" ] then AGENT_AUTOTIME=`echo $a | cut -d" " -f2-` fi done if [ "$CRON_MODE" == "0" ] then # Script banner at start echo "Pandora FMS Agent $AGENT_VERSION (c) Artica ST 2003-2010" echo "This program is licensed under GPL2 Terms. http://pandorafms.org" echo "Running in $NOMBRE_HOST at $TIMESTAMP" echo " " else # Checks if there is another instance running PID_RUNNING=`pidof -x pandora_agent` PID_ME=$$ if [ "$PID_ME" != "$PID_RUNNING" ] then echo "Aborting execution. Another instance of Pandora FMS running" exit fi fi # Make some checks if [ "$DEBUG_MODE" == "1" ] then echo "(**) Warning: Running in DEBUG mode" fi if [ $DELAYED_STARTUP != 0 ] then echo "Delayed startup in $DELAYED_STARTUP minutes " echo "Delayed startup in $DELAYED_STARTUP minutes" > $PANDORA_LOGFILE.err echo " " sleep $(($DELAYED_STARTUP*60)) fi # Renice me renice $PANDORA_NICE $$ 2> /dev/null > /dev/null } # ********************************************************************** # function send_file(file) # Sends a file to the server. # ********************************************************************** function send_file { FILE="$1" if [ "$TRANSFER_MODE" == "tentacle" ] then eval tentacle_client -v -a $SERVER_IP -p $SERVER_PORT $TENTACLE_OPTS $FILE > /dev/null 2> $PANDORA_LOGFILE.err return $? fi if [ "$TRANSFER_MODE" == "ssh" ] then scp -P $SERVER_PORT $FILE pandora@$SERVER_IP:$SERVER_PATH > /dev/null 2> $PANDORA_LOGFILE.err return $? fi if [ "$TRANSFER_MODE" == "ftp" ] then BASENAME=`basename $FILE` DIRNAME=`dirname $FILE` ftp -n $SERVER_IP $SERVER_PORT > /dev/null 2> $PANDORA_LOGFILE.err < /dev/null 2> $PANDORA_LOGFILE.err return $? fi return 1 } # ********************************************************************** # function send_file_secure(file) # Sends the file to the available server. # ********************************************************************** function send_file_secure { FILE="$1" send_file "$FILE" RC=$? # Always send the file to the secondary server if [ "$SECONDARY_MODE" = "always" ]; then switch_servers send_file "$FILE" switch_servers # Send the file to the secondary server only if something went wrong elif [ "$SECONDARY_MODE" = "on_error" ]; then if [ $RC != 0 ]; then switch_servers send_file "$FILE" RC=$? switch_servers fi fi return $RC } # ********************************************************************** # function recv_file(file) # Gets a file from the server and saves it under $TEMP. Paths are not # allowed. # ********************************************************************** function recv_file { FILE="$1" if [ "$TRANSFER_MODE" == "tentacle" ] then WD=`pwd` cd $TEMP eval tentacle_client -v -g -a $SERVER_IP -p $SERVER_PORT $TENTACLE_OPTS $FILE > /dev/null 2> $PANDORA_LOGFILE.err STATUS=$? cd $WD return $STATUS fi if [ "$TRANSFER_MODE" == "ssh" ] then scp -P $SERVER_PORT pandora@$SERVER_IP:$SERVER_PATH/$FILE $TEMP > /dev/null 2> $PANDORA_LOGFILE.err return $? fi if [ "$TRANSFER_MODE" == "ftp" ] then ftp -n $SERVER_IP $SERVER_PORT > /dev/null 2> $PANDORA_LOGFILE.err < /dev/null 2> $PANDORA_LOGFILE.err return $? fi return 1 } # ********************************************************************** # function switch(var1, var2) # Switches the values of var1 and var2 # ********************************************************************** function switch { eval "TEMP=\"\$$1\"" eval "$1=\"\$$2\"" eval "$2=\"\$TEMP\"" } # ********************************************************************** # function switch_servers() # Switches the target server # ********************************************************************** function switch_servers { switch TRANSFER_MODE SECONDARY_TRANSFER_MODE switch SERVER_IP SECONDARY_SERVER_IP switch SERVER_PORT SECONDARY_SERVER_PORT switch TENTACLE_OPTS SECONDARY_TENTACLE_OPTS switch SERVER_PATH SECONDARY_SERVER_PATH switch SERVER_PWD SECONDARY_SERVER_PWD } # ********************************************************************** # function check_remote_config() # Checks for a newer remote configuration file. # ********************************************************************** function check_remote_config { if [ "$REMOTE_CONFIG" != "1" ] then return 1 fi # Disabled in DEBUG mode if [ "$DEBUG_MODE" == "1" ] then return 1 fi # Agent name md5sum AGENT_MD5=`echo -n $NOMBRE_HOST | md5sum | cut -d" " -f1` CONFIG_FILE="$AGENT_MD5.conf" MD5_FILE="$AGENT_MD5.md5" # Local config file md5sum CONFIG_MD5=`md5sum $PANDORA_HOME/pandora_agent.conf | cut -d" " -f1` # Get remote config file md5sum recv_file "$MD5_FILE" # Configuration has not been uploaded to the server if [ $? != 0 ] then echo "$TIMESTAMP - Uploading configuration for the first time" >> $PANDORA_LOGFILE cp "$PANDORA_HOME/pandora_agent.conf" "$TEMP/$CONFIG_FILE" echo "$CONFIG_MD5" > "$TEMP/$MD5_FILE" send_file "$TEMP/$CONFIG_FILE" send_file "$TEMP/$MD5_FILE" rm -f "$TEMP/$CONFIG_FILE" rm -f "$TEMP/$MD5_FILE" return 0 fi # Check for configuration changes REMOTE_MD5=`cat $TEMP/$MD5_FILE` rm -f "$TEMP/$MD5_FILE" if [ "$REMOTE_MD5" == "$CONFIG_MD5" ] then return 0 fi echo "$TIMESTAMP - Configuration has changed" >> $PANDORA_LOGFILE recv_file "$CONFIG_FILE" if [ $? != 0 ] then echo "$TIMESTAMP - Error retrieving configuration file" > $PANDORA_LOGFILE.err return 1 fi mv "$TEMP/$CONFIG_FILE" "$PANDORA_HOME/pandora_agent.conf" # Reload configuration configure_agent return 0 } # ********************************************************************** # Main # ********************************************************************** if [ -z "$1" ] then echo " " echo "Fatal error: I need an argument to Pandora FMS Agent config directory" echo " " echo " example: pandora_agent /etc/pandora" echo " " exit -1 else PANDORA_HOME=$1 fi if [ ! -f $PANDORA_HOME/pandora_agent.conf ] then echo " " echo "FATAL ERROR: Cannot load $PANDORA_HOME/pandora_agent.conf" echo " " exit -1 fi # Init internal variables CONTADOR=0 EXECUTE=1 MODULE_END=0 TIMESTAMP=`date +"%Y/%m/%d %H:%M:%S"` IFS=$'\n' # Default values DEBUG_MODE=0 DELAYED_STARTUP=0 SERVER_PORT=22 PANDORA_NICE=0 INTERVAL=300 TRANSFER_MODE=ssh CRON_MODE=0 if [ -z "`echo $LANG | grep '\.'`" ] then ENCODING="UTF-8" else ENCODING=`echo $LANG | cut -f 2 -d "."` fi NOMBRE_HOST=`/bin/hostname` OS_NAME=`uname -s` PANDORA_LOGFILE=/var/log/pandora/pandora_agent.log TEMP=/tmp # Get Linux Distro type and version if [ -f "/etc/SuSE-release" ] then OS_VERSION=`cat /etc/SuSE-release | grep VERSION | cut -f 3 -d " "` LINUX_DISTRO=SUSE else if [ -f "/etc/lsb-release" ] then OS_VERSION=`cat /etc/lsb-release | grep DISTRIB_RELEASE | cut -f 2 -d "="` LINUX_DISTRO=UBUNTU OS_VERSION="UBUNTU $OS_VERSION" else if [ -f "/etc/debian_version" ] then OS_VERSION=`cat /etc/debian_version` OS_VERSION="DEBIAN $OS_VERSION" LINUX_DISTRO=DEBIAN else if [ -f "/etc/fedora-release" ] then OS_VERSION=`cat /etc/fedora-release | cut -f 4 -d " "` OS_VERSION="FEDORA $OS_VERSION" LINUX_DISTRO=FEDORA else LINUX_DISTRO=GENERIC OS_VERSION=`uname -r` fi fi fi fi # Configure this agent configure_agent # MAIN Program loop begin while [ "1" == "1" ] do # Deleted debug / error info on each run to avoid giant logs rm -Rf $PANDORA_LOGFILE.err 2> /dev/null # Check for configuration changes if remote_config is enabled check_remote_config # Date and time, SERIAL is number of seconds since 1/1/1970, for every packet. TIMESTAMP=`date +"%Y/%m/%d %H:%M:%S"` SERIAL=`date +"%s"` if [ "$AGENT_AUTOTIME" == "1" ] then TIMESTAMP="AUTO" fi # File names DATA=$TEMP/$NOMBRE_HOST.$SERIAL.data DATA2=$TEMP/$NOMBRE_HOST.$SERIAL.data_temp # Makes data packet echo " " > $DATA echo "" >> $DATA for a in `cat $PANDORA_HOME/pandora_agent.conf | grep -v -e "^#" | grep -e "^module" ` do a=`echo $a | tr -s " " " "` if [ ! -z "`echo $a | grep -e '^module_exec'`" ] then if [ $EXECUTE -eq 0 ] then execution=`echo $a | cut -c 13- ` res=`eval $execution` if [ -z "$flux_string" ] then res=`eval expr $res 2> $PANDORA_LOGFILE.err` fi echo "" >> $DATA2 fi fi if [ ! -z "`echo $a | grep -e '^module_name'`" ] then name=`echo $a | cut -c 13- ` echo "" >> $DATA2 fi if [ ! -z "`echo $a | grep -e '^module_begin'`" ] then echo "" >> $DATA2 EXECUTE=0 fi if [ ! -z "`echo $a | grep -e '^module_max' `" ] then max=`echo $a | awk '{ print $2 }' ` echo "" >> $DATA2 fi if [ ! -z "`echo $a | grep -e '^module_min'`" ] then min=`echo $a | awk '{ print $2 }' ` echo "" >> $DATA2 fi if [ ! -z "`echo $a | grep -e '^module_description'`" ] then desc=`echo $a | cut -c 20- ` echo "" >> $DATA2 fi if [ ! -z "`echo $a | grep -e '^module_end'`" ] then echo "" >> $DATA2 MODULE_END=1 else MODULE_END=0 fi if [ ! -z "`echo $a | grep -e '^module_type'`" ] then mtype=`echo $a | awk '{ print $2 }' ` if [ ! -z "`echo $mtype | grep 'generic_data_string'`" ] || [ ! -z "`echo $mtype | grep 'async_string'`" ] then flux_string=1 else flux_string=0 unset flux_string fi echo "" >> $DATA2 fi if [ ! -z "`echo $a | grep '^module_interval'`" ] then # Determine if execution is to be done MODULEINTERVAL=`echo $a | awk '{ print $2 }'` EXECUTE=`expr \( $CONTADOR + 1 \) % $MODULEINTERVAL` fi # Plugin execution if [ ! -z "`echo $a | grep '^module_plugin'`" ] then PLUGIN=`echo $a | cut -d" " -f2` PARAMS=`echo $a | cut -d" " -f3-` if [ -f $PANDORA_HOME/plugins/$PLUGIN ] then eval $PANDORA_HOME/plugins/$PLUGIN $PARAMS >> $DATA else echo "$TIMESTAMP - Plugin $PANDORA_HOME/plugins/$PLUGIN not found" > $PANDORA_LOGFILE.err fi fi # Module postprocess info if [ ! -z "`echo $a | grep -e '^module_postprocess'`" ] then pprocess=`echo $a | cut -d" " -f2-` echo "" >> $DATA2 fi # If module ends, and execute for this module is enabled # then write if [ $MODULE_END -eq 1 ] then if [ $EXECUTE -eq 0 ] then cat $DATA2 >> $DATA fi rm -Rf $DATA2 > /dev/null 2> /dev/null fi done # Count number of agent runs CONTADOR=`expr $CONTADOR + 1` # Keep a limit of 100 for overflow reasons if [ $CONTADOR -eq 100 ] then CONTADOR=0 fi # Finish data packet echo "" >> $DATA echo "" >> $DATA # Replace & chars in XML (should not to be any) to avoid syntax problems sed "s/&/&/g" $DATA > $TEMP/finalxml.tmp rm -f $DATA mv $TEMP/finalxml.tmp $DATA if [ "$DEBUG_MODE" == "1" ] then echo "$TIMESTAMP - Finish writing XML $DATA" >> $PANDORA_LOGFILE echo "(**) Data file is at $DATA - Exiting now" echo " " exit 0 fi # Send packets to server and delete it send_file_secure $DATA # Delete data rm -f $DATA > /dev/null 2> $PANDORA_LOGFILE.err # Cron mode if [ "$CRON_MODE" == "1" ] then exit fi # Go to bed :-) sleep $INTERVAL done # This runs forever!