Syed Jahanzaib Personal Blog to Share Knowledge !

December 23, 2016

Howto get combined average Load of multi core CPU by BASH

Filed under: Linux Related — Tags: , — Syed Jahanzaib / Pinochio~:) @ 11:46 AM

cpu-load

Following is a small script to get combined multi-core CPU load (average) from remote server. I made it to create MRTG graph for CPU load of all cores combined average value for our local ESXI servers.


#!/bin/bash
# Script to query ESXI server
#set -x
HOST="$1"
SNMP_STRING="public"
TMP_HOLDER="/tmp/cpuinfo.$HOST"
OID="hrProcessorLoad."
MIB="/cfg/mibs/HOST-RESOURCES-MIB"
snmpwalk -v2c -c $SNMP_STRING -m "$MIB" $HOST |grep $OID | awk '{print $4}' > $TMP_HOLDER
CPU_CORE=`cat $TMP_HOLDER | wc -l`
CPU_LOAD_SUM=`cat $TMP_HOLDER | awk '{ sum += $1 } END { print sum }'`
CPU_LOAD_FINAL=`echo "scale=2; $CPU_LOAD_SUM/$CPU_CORE" | bc -l`
echo $CPU_LOAD_FINAL
echo $CPU_LOAD_FINAL


Result:

(following result is average value of my esxi server which have 2 physical processor with 6 cores each, so virtually there are 24 cores for ESXI guests). SNMP must be enabled on remote esxi server , I wrote on how it can be enabled one esxi, see my old postings on it.

root@linux:/temp# ./cpu_load.sh 10.0.0.1

Output:

6.70
6.70


CFG example:

ESXI Server -10.0.0.1- CPU Utilization ###
Target[esxi_cpu_1010.0.0.1]: `/temp/cpu_load.sh 10.0.0.1`
Options[esxi_cpu_1010.0.0.1]: growright, gauge, integer, noo
MaxBytes[esxi_cpu_1010.0.0.1]: 100
LegendI[esxi_cpu_1010.0.0.1]: Total CPU Cores Used %
LegendO[esxi_cpu_1010.0.0.1]:
Legend1[esxi_cpu_1010.0.0.1]: Total CPU Cores Used %
Legend2[esxi_cpu_1010.0.0.1]:
Title[esxi_cpu_1010.0.0.1]: ESXI Server -10.0.0.1- CPU Load %
PageTop[esxi_cpu_1010.0.0.1]: <h1>ESXI Server -10.0.0.1- CPU Load %</h1>
Unscaled[esxi_cpu_1010.0.0.1]: ymwd
ShortLegend[esxi_cpu_1010.0.0.1]: %
YLegend[esxi_cpu_1010.0.0.1]: % CPU Used
Colours[esxi_cpu_1010.0.0.1]: RED#ff4f27,DIRTY YELLOW#E6B420,RED#ff4f27,DIRTY YELLOW#E6B420

Syed.Jahanzaib!

Single Script to Create All Storage CFG file in MRTG

Filed under: Linux Related — Tags: , — Syed Jahanzaib / Pinochio~:) @ 9:07 AM

auto

Reference Post:

It’s a headache if you want to create configuration file in bulk for all the storage available in remote servers, that includes disks/memory. To make life a little easier, I made following script which simply query the storage indexes and create CFG file in /cfg folder.

#!/bin/bash
# Script to query remote server
#set -x
# Colors Config . . . [[ JZ . . . ]]
ESC_SEQ="\x1b["
COL_RESET=$ESC_SEQ"39;49;00m"
COL_RED=$ESC_SEQ"31;01m"
COL_GREEN=$ESC_SEQ"32;01m"
MIB_NAME="HOST-RESOURCES-MIB"

#If MIB is not present, EXIT with error
MIB_CHECK=`locate $MIB_NAME > /tmp/miblocate.txt`
MIB_CHECK_RESULT=`cat /tmp/miblocate.txt`
if [ -z "$MIB_CHECK_RESULT" ]; then
echo -e "$COL_RED MRTG ERROR MNF1: HOST-RESOURCES-MIB not found, cannot continue without it. Download them first ... $COL_RESET"
exit 1
fi

HOST="$1"
# Temporary Folder where all CFG will be placed . . . [[ JZ . . . ]]
CFGDIR="cfg"
# Checking if $CFGDIR folder is previously present or not . . .
{
if [ ! -d "/$CFGDIR" ]; then
echo
echo -e "$COL_RED /$CFGDIR folder not found, Creating it so all cfg will be placed here . . . $COL_RESET"
mkdir /temp
else
echo
echo -e "$COL_GREEN /$CFGDIR folder is already present , so no need to create it, Proceeding further . . . $COL_RESET"
echo
fi
}

CFG_FILE_NAME="/$CFGDIR/storage.$1.cfg"
SNMP_STRING="PUBLIC"
snmpwalk -Os -c $SNMP_STRING -v 2c -m "/cfg/mibs/HOST-RESOURCES-MIB" $HOST hrStorageDescr |
sed -nre 's,hrStorageDescr.([0-9]*) = STRING: (.*),\1 \2,p' |
grep -Ev ' /(proc|sys)($|/)' |
while read NM DESC; do

STORAGE_SIZE=`snmpwalk -Onqv -Os -c $SNMP_STRING -v 2c -m "/cfg/mibs/HOST-RESOURCES-MIB" $HOST hrStorageSize.${NM}`
ALLOCATION_UNIT=`snmpwalk -Onqv -Os -c $SNMP_STRING -v 2c -m "/cfg/mibs/HOST-RESOURCES-MIB" $HOST hrStorageAllocationUnits.${NM} | awk '{print $1}'`

# FORMULAS
MAXSIZE_BITS=`echo $(($STORAGE_SIZE*$ALLOCATION_UNIT*8))`
MAXSIZE_MB=`echo $(($STORAGE_SIZE*$ALLOCATION_UNIT/1024/1024))`
MAXSIZE_GB=`echo $(($STORAGE_SIZE*$ALLOCATION_UNIT/1024/1024/1024))`
MAXSIZE_TB=`echo $(($STORAGE_SIZE*$ALLOCATION_UNIT/1024/1024/1024/1024))`

#TITLE LINES
MAXSIZE_MB_T=`echo "scale=2; $STORAGE_SIZE*$ALLOCATION_UNIT / 1024 / 1024" | bc -l`
MAXSIZE_GB_T=`echo "scale=2; $STORAGE_SIZE*$ALLOCATION_UNIT/1024/1024/1024" | bc -l`
MAXSIZE_TB_T=`echo "scale=2; $MAXSIZE_GB/1000" | bc -l`

if [ $MAXSIZE_BITS -eq 0 ]; then
MAXSIZE_BITS="1"
fi
# Under 1GB TITLE
if [ $MAXSIZE_MB -lt 1024 ]; then
#echo "$hrStorageSize.${NM} = MAX Size in MB = $MAXSIZE_MB_T"
MAXSIZE_TITLE="MAX Size in MB = $MAXSIZE_MB_T"
fi
# ABOVE 1GB TITLE
if [ $MAXSIZE_MB -gt 1024 ]; then
#echo "$hrStorageSize.${NM} = MAX Size in GB = $MAXSIZE_GB_T"
MAXSIZE_TITLE="MAX Size in GB = $MAXSIZE_GB_T"
fi
# ABOVE 1 TB TITLE
if [ $MAXSIZE_MB -gt 1048576 ]; then
#echo "$hrStorageSize.${NM} = MAX Size in TB = $MAXSIZE_TB_T"
MAXSIZE_TITLE="MAX Size in TB = $MAXSIZE_TB_T"
fi

IDENT="stor_$(echo "${DESC}" | tr '[A-Z]/ ' '[a-z]_' | sed 's/\:/-/g')"
echo "Target[${IDENT}]: hrStorageUsed.${NM}&hrStorageSize.${NM}:$SNMP_STRING@$HOST * hrStorageAllocationUnits.${NM}&hrStorageAllocationUnits.${NM}:$SNMP_STRING@$HOST"
echo "Title[${IDENT}]: $HOST - Storage: ${DESC} : / $MAXSIZE_TITLE"
echo "PageTop[${IDENT}]: <h1>$HOST - Storage: ${DESC} Report / $MAXSIZE_TITLE</h1>"
echo "Kilo[${IDENT}]: 1024"
echo "MaxBytes[${IDENT}]: $MAXSIZE_BITS"
echo "ShortLegend[${IDENT}]: iB"
echo "YLegend[${IDENT}]: Bytes"
echo "Legend1[${IDENT}]: Used"
echo "Legend2[${IDENT}]: Total"
echo "LegendI[${IDENT}]: Used:"
echo "LegendO[${IDENT}]: Total:"
echo "Options[${IDENT}]: gauge,growright,nobanner,nopercent"
done > $CFG_FILE_NAME

if [ -f $CFG_FILE_NAME ];
then
echo -e "$COL_GREEN MRTG CFG file name $CFG_FILE_NAME for $HOST is created ... $COL_RESET"
else
echo -e "$COL_RED ERROR: Unable to create CFG FILEs, check script errors ... $COL_RESET"
fi

echo -e "$COL_GREEN
SCRIPT ENDS HERE ... $COL_RESET"


Run Method:

./querystorage.sh 10.0.0.1

1


CFG Files Example:


Target[stor_c-_label-os__serial_number_b6ff670d]: hrStorageUsed.1&hrStorageSize.1:PUBLIC@10.0.0.1 * hrStorageAllocationUnits.1&hrStorageAllocationUnits.1:PUBLIC@10.0.0.1
Title[stor_c-_label-os__serial_number_b6ff670d]: 10.0.0.1 - Storage: C: Label:OS Serial Number b6ff670d : / MAX Size in GB = 278.14
PageTop[stor_c-_label-os__serial_number_b6ff670d]: <h1>10.0.0.1 - Storage: C: Label:OS Serial Number b6ff670d Report / MAX Size in GB = 278.14</h1>
Kilo[stor_c-_label-os__serial_number_b6ff670d]: 1024
MaxBytes[stor_c-_label-os__serial_number_b6ff670d]: 2389226520576
ShortLegend[stor_c-_label-os__serial_number_b6ff670d]: iB
YLegend[stor_c-_label-os__serial_number_b6ff670d]: Bytes
Legend1[stor_c-_label-os__serial_number_b6ff670d]: Used
Legend2[stor_c-_label-os__serial_number_b6ff670d]: Total
LegendI[stor_c-_label-os__serial_number_b6ff670d]: Used:
LegendO[stor_c-_label-os__serial_number_b6ff670d]: Total:
Options[stor_c-_label-os__serial_number_b6ff670d]: gauge,growright,nobanner,nopercent

Target[stor_d-_label-Data__serial_number_f40779eb]: hrStorageUsed.2&hrStorageSize.2:PUBLIC@10.0.0.1 * hrStorageAllocationUnits.2&hrStorageAllocationUnits.2:PUBLIC@10.0.0.1
Title[stor_d-_label-Data__serial_number_f40779eb]: 10.0.0.1 - Storage: D: Label:Data Serial Number f40779eb : / MAX Size in TB = 1.11
PageTop[stor_d-_label-Data__serial_number_f40779eb]: <h1>10.0.0.1 - Storage: D: Label:Data Serial Number f40779eb Report / MAX Size in TB = 1.11</h1>
Kilo[stor_d-_label-Data__serial_number_f40779eb]: 1024
MaxBytes[stor_d-_label-Data__serial_number_f40779eb]: 9566888624128
ShortLegend[stor_d-_label-Data__serial_number_f40779eb]: iB
YLegend[stor_d-_label-Data__serial_number_f40779eb]: Bytes
Legend1[stor_d-_label-Data__serial_number_f40779eb]: Used
Legend2[stor_d-_label-Data__serial_number_f40779eb]: Total
LegendI[stor_d-_label-Data__serial_number_f40779eb]: Used:
LegendO[stor_d-_label-Data__serial_number_f40779eb]: Total:
Options[stor_d-_label-Data__serial_number_f40779eb]: gauge,growright,nobanner,nopercent

Target[stor_physical_memory]: hrStorageUsed.5&hrStorageSize.5:PUBLIC@10.0.0.1 * hrStorageAllocationUnits.5&hrStorageAllocationUnits.5:PUBLIC@10.0.0.1
Title[stor_physical_memory]: 10.0.0.1 - Storage: Physical Memory : / MAX Size in GB = 31.81
PageTop[stor_physical_memory]: <h1>10.0.0.1 - Storage: Physical Memory Report / MAX Size in GB = 31.81</h1>
Kilo[stor_physical_memory]: 1024
MaxBytes[stor_physical_memory]: 273308712960
ShortLegend[stor_physical_memory]: iB
YLegend[stor_physical_memory]: Bytes
Legend1[stor_physical_memory]: Used
Legend2[stor_physical_memory]: Total
LegendI[stor_physical_memory]: Used:
LegendO[stor_physical_memory]: Total:
Options[stor_physical_memory]: gauge,growright,nobanner,nopercent


Graph Examples:

2

Jz!

December 19, 2016

Incorrect key file for table ‘./conntrack/xxxx@xxxxxx@xxxxxx.MYI’; try to repair it

Filed under: Radius Manager, Uncategorized — Tags: , , — Syed Jahanzaib / Pinochio~:) @ 1:05 PM

corruption

Incorrect key file for table ‘./conntrack/2016@002d12@002d16.MYI’; try to repair it

If you see the above error while accessing Connection Tracking Reports in Radius Manager then …

Recommendations:

  • Make sure you aave plenty of Disk Space. Storage drive should be fast for high load servers preferably SSD or RAID based storage ,
  • Plenty of Memory is usually a good idea for DB systems ,
  • If its a heavy production server, try to move connection tracking to separate host as it takes lots of space and it adds good amount of payload to the CPU as well.
  • Perform tuning to enhance the mysql engine

To repair table …

Goto the conntrack folder [Ubuntu]
cd /var/lib/mysql/conntrack/
service mysql stop
# Change the file number as shown in the error 
myisamchk -r -v -f 2016@002d12@002d16.MYI

Once repair is done, start mysql / restart apache2 services , and test the desired tracking report again.

Regard’s
~Syed Jahanzaib~

Tik: 9 wan pcc with vpn server

Filed under: Mikrotik Related — Syed Jahanzaib / Pinochio~:) @ 10:12 AM

~ There are no absolute answers in this universe, only assumptions, guesses, Jeopardies
Syed Jahanzaib !


9 wan pcc.png


 

Following is just a reference post. This configuration contains PCC and PPtP server. (to provide net access to local users via dialer) , You may need to tweak in order to make it work.

Disclaimer: 
The script in this post is made for reference purposes only. This is no way a COPY PASTE material which you can use it as a whole. every network is different and should be build accordingly. Modify the config as per local requirements and then implement it. You may need to play a bit or tweak it in order to make it Workable config.


Scenario:

Hardware Used : Mikrotik – Rb1100ahx2

  • 9 DSL (ptcl) routers are connected with the RB1100ahx2.
  • Each DSL modem is in router mode, so the gateway ip are in series like 192.168.1,1 or 192.168.2.1 and so on …
  • Ports name have been renamed to friendlier label for easy marking.
    Example Port 1-9 are renamed as WANx , and Port 10 is marked as Local
  • VPN Server is configured on same RB, and users dials in to this server in order to access internet.
  • No DHCP is being used on this setup as OP prefers to use static ips due to some specific circumstances.

the scriptO!

# 9 wan PCC load balancing script along with PPtP config
# Make sure to adjust it as per your setup
# Syed Jahanzaib / aacable at hotmail dot com
# http:// aacable . wordpress . com
# Made in 2016 / Pakistan

# Local Interface connected with the Users Switch
/ip address
add address=10.0.0.1/24 interface=Local network=10.0.0.0

# WAN interfaces IP addresses, which are connected with ptcl dsl routers
/ip address
add address=192.168.1.2/24 interface=WAN1 network=192.168.1.0
add address=192.168.2.2/24 interface=WAN2 network=192.168.2.0
add address=192.168.3.2/24 interface=WAN3 network=192.168.3.0
add address=192.168.4.2/24 interface=WAN4 network=192.168.4.0
add address=192.168.5.2/24 interface=WAN5 network=192.168.5.0
add address=192.168.6.2/24 interface=WAN6 network=192.168.6.0
add address=192.168.7.2/24 interface=WAN7 network=192.168.7.0
add address=192.168.8.2/24 interface=WAN8 network=192.168.8.0
add address=192.168.9.2/24 interface=WAN9 network=192.168.9.0

# Add IP pool for VPN dialer users, which will be allowed to use internet
/ip pool
add name=vpn-pool ranges=172.16.0.1-172.16.0.255

# Add VPN Profile for users , example 1mb per user profile
/ppp profile
add change-tcp-mss=yes dns-server=110.0.0.1,8.8.8.8 local-address=10.0.0.1 name=vpn-1mb only-one=yes rate-limit=1024k/1024k remote-address=vpn-pool use-encryption=yes

/interface pptp-server server set authentication=pap,chap,mschap1,mschap2 default-profile=vpn-1mb enabled=yes

# Enable DNS server
/ip dns
set allow-remote-requests=yes servers=8.8.8.8

/ip firewall address-list
add address=172.16.0.1-172.16.0.255 list=local_vpn_users_internet_allowed_list

# This is a local sharing server
add address=192.168.10.1 list=local_sharing_server

/ip firewall mangle

# Bypass Local Media Sharing server from PCC, so user can access it / Adjust it according to your need/ Jz
add action=accept chain=prerouting comment="Allow access to local sharing server / bypass them from the PCC" dst-address-list=local_sharing_server

# Accept traffic going to DSL Routers / Adjust it according to your need/ Jz
add action=accept chain=prerouting dst-address=192.168.1.0/24
add action=accept chain=prerouting dst-address=192.168.1.0/24
add action=accept chain=prerouting dst-address=192.168.2.0/24
add action=accept chain=prerouting dst-address=192.168.3.0/24
add action=accept chain=prerouting dst-address=192.168.4.0/24
add action=accept chain=prerouting dst-address=192.168.5.0/24
add action=accept chain=prerouting dst-address=192.168.6.0/24
add action=accept chain=prerouting dst-address=192.168.7.0/24
add action=accept chain=prerouting dst-address=192.168.8.0/24
add action=accept chain=prerouting dst-address=192.168.9.0/24

# Mark connections using PCC for 9 WAN / Adjust it according to your need / Jz
add action=mark-connection chain=prerouting dst-address-type=!local new-connection-mark=WAN1_conn passthrough=yes per-connection-classifier=both-addresses-and-ports:9/0 src-address-list=local_vpn_users_internet_allowed_list
add action=mark-connection chain=prerouting dst-address-type=!local new-connection-mark=WAN2_conn passthrough=yes per-connection-classifier=both-addresses-and-ports:9/1 src-address-list=local_vpn_users_internet_allowed_list
add action=mark-connection chain=prerouting dst-address-type=!local new-connection-mark=WAN3_conn passthrough=yes per-connection-classifier=both-addresses-and-ports:9/2 src-address-list=local_vpn_users_internet_allowed_list
add action=mark-connection chain=prerouting dst-address-type=!local new-connection-mark=WAN4_conn passthrough=yes per-connection-classifier=both-addresses-and-ports:9/3 src-address-list=local_vpn_users_internet_allowed_list
add action=mark-connection chain=prerouting dst-address-type=!local new-connection-mark=WAN5_conn passthrough=yes per-connection-classifier=both-addresses-and-ports:9/4 src-address-list=local_vpn_users_internet_allowed_list
add action=mark-connection chain=prerouting dst-address-type=!local new-connection-mark=WAN6_conn passthrough=yes per-connection-classifier=both-addresses-and-ports:9/5 src-address-list=local_vpn_users_internet_allowed_list
add action=mark-connection chain=prerouting dst-address-type=!local new-connection-mark=WAN7_conn passthrough=yes per-connection-classifier=both-addresses-and-ports:9/6 src-address-list=local_vpn_users_internet_allowed_list
add action=mark-connection chain=prerouting dst-address-type=!local new-connection-mark=WAN8_conn passthrough=yes per-connection-classifier=both-addresses-and-ports:9/7 src-address-list=local_vpn_users_internet_allowed_list
add action=mark-connection chain=prerouting dst-address-type=!local new-connection-mark=WAN9_conn passthrough=yes per-connection-classifier=both-addresses-and-ports:9/8 src-address-list=local_vpn_users_internet_allowed_list

# Mark routing for above marked connections, so that it can be used in ROUTE section / Adjust it according to your need/ Jz
add action=mark-routing chain=prerouting connection-mark=WAN1_conn new-routing-mark=to_WAN1 passthrough=yes
add action=mark-routing chain=prerouting connection-mark=WAN2_conn new-routing-mark=to_WAN2 passthrough=yes
add action=mark-routing chain=prerouting connection-mark=WAN3_conn new-routing-mark=to_WAN3 passthrough=yes
add action=mark-routing chain=prerouting connection-mark=WAN4_conn new-routing-mark=to_WAN4 passthrough=yes
add action=mark-routing chain=prerouting connection-mark=WAN5_conn new-routing-mark=to_WAN5 passthrough=yes
add action=mark-routing chain=prerouting connection-mark=WAN6_conn new-routing-mark=to_WAN6 passthrough=yes
add action=mark-routing chain=prerouting connection-mark=WAN7_conn new-routing-mark=to_WAN7 passthrough=yes
add action=mark-routing chain=prerouting connection-mark=WAN8_conn new-routing-mark=to_WAN8 passthrough=yes
add action=mark-routing chain=prerouting connection-mark=WAN9_conn new-routing-mark=to_WAN9 passthrough=yes

# Add NAT/MASQUERADE rule allowing only allowed users, restricted to allowed users only
add action=masquerade chain=srcnat comment="Allow Local Sharing Servers / NATING" dst-address-list=local_sharing_server
add action=masquerade chain=srcnat comment="WAN-1 / Allow Internet Access - For VPN Users only" out-interface=WAN1 src-address-list=local_vpn_users_internet_allowed_list
add action=masquerade chain=srcnat comment="WAN-2 / Allow Internet Access - For VPN Users only" out-interface=WAN2 src-address-list=local_vpn_users_internet_allowed_list
add action=masquerade chain=srcnat comment="WAN-3 / Allow Internet Access - For VPN Users only" out-interface=WAN3 src-address-list=local_vpn_users_internet_allowed_list
add action=masquerade chain=srcnat comment="WAN-4 / Allow Internet Access - For VPN Users only" out-interface=WAN4 src-address-list=local_vpn_users_internet_allowed_list
add action=masquerade chain=srcnat comment="WAN-5 / Allow Internet Access - For VPN Users only" out-interface=WAN5 src-address-list=local_vpn_users_internet_allowed_list
add action=masquerade chain=srcnat comment="WAN-6 / Allow Internet Access - For VPN Users only" out-interface=WAN6 src-address-list=local_vpn_users_internet_allowed_list
add action=masquerade chain=srcnat comment="WAN-7 / Allow Internet Access - For VPN Users only" out-interface=WAN7 src-address-list=local_vpn_users_internet_allowed_list
add action=masquerade chain=srcnat comment="WAN-8 / Allow Internet Access - For VPN Users only" out-interface=WAN8 src-address-list=local_vpn_users_internet_allowed_list
add action=masquerade chain=srcnat comment="WAN-9 / Allow Internet Access - For VPN Users only" out-interface=WAN9 src-address-list=local_vpn_users_internet_allowed_list

# Adding routes for marked traffic
# Each DSL router ip is in series like 192.168.1.1 / 2.1 / 3.1 and so on

/ip route
add check-gateway=ping distance=1 gateway=192.168.1.1 routing-mark=to_WAN1
add check-gateway=ping distance=1 gateway=192.168.2.1 routing-mark=to_WAN2
add check-gateway=ping distance=1 gateway=192.168.3.1 routing-mark=to_WAN3
add check-gateway=ping distance=1 gateway=192.168.4.1 routing-mark=to_WAN4
add check-gateway=ping distance=1 gateway=192.168.5.1 routing-mark=to_WAN5
add check-gateway=ping distance=1 gateway=192.168.6.1 routing-mark=to_WAN6
add check-gateway=ping distance=1 gateway=192.168.7.1 routing-mark=to_WAN7
add check-gateway=ping distance=1 gateway=192.168.8.1 routing-mark=to_WAN8
add check-gateway=ping distance=1 gateway=192.168.9.1 routing-mark=to_WAN9

# Adding routes for default routes, so that if any WAN goes down, those packets should go via MAIN table : ) kind of fail over/ Jz
add check-gateway=ping comment="WAN-1 / DEFAULT ROUTE" distance=1 gateway=192.168.1.1
add check-gateway=ping comment="WAN-2 / DEFAULT ROUTE" distance=2 gateway=192.168.2.1
add check-gateway=ping comment="WAN-3 / DEFAULT ROUTE" distance=3 gateway=192.168.3.1
add check-gateway=ping comment="WAN-4 / DEFAULT ROUTE" distance=4 gateway=192.168.4.1
add check-gateway=ping comment="WAN-5 / DEFAULT ROUTE" distance=5 gateway=192.168.5.1
add check-gateway=ping comment="WAN-6 / DEFAULT ROUTE" distance=6 gateway=192.168.6.1
add check-gateway=ping comment="WAN-7 / DEFAULT ROUTE" distance=7 gateway=192.168.7.1
add check-gateway=ping comment="WAN-8 / DEFAULT ROUTE" distance=8 gateway=192.168.8.1
add check-gateway=ping comment="WAN-9 / DEFAULT ROUTE" distance=9 gateway=192.168.9.1

W/Salam

December 15, 2016

Craziness with the MRTG along with BASH

Filed under: Linux Related, Uncategorized — Tags: , , , — Syed Jahanzaib / Pinochio~:) @ 9:16 AM

 


City vs Data Center Temperature !

Following is a temperature graph to compare difference between City temperature vs Data Center temperature. I made it for some local presentation purposes. Since I had no external sensor available for outside temperature monitoring, therefore I used external bash script to gather data from the internet using ‘Pakistan Meteorological Department PMD‘ website  and then after filtering , output only required data.  For NOC I used internal UPS sensor snmp query.

http://www.pmd.gov.pk/FFD/cp/pcurrenttemp.asp

1-noc-vs-karachi-temperature

 

 

#cat /temp/weather.sh


#!/bin/sh
#set -x
# Script to download KARACHI city temperature from Pakistan MET Dept web site &nbsp;and output only temperature related information
# It will also query the NCO room temperature using UPS sensor via snmp query
# I made this script to create City temperature vs NOC temperature comparison MRTG graph
# Created : 9th-DEC-2016
# Syed Jahanzaib
# aacable[at]hotmail[dot]com
# http://aacableDOTwordpressDOTcom

####### Various Variables #########

# City temperature temporary holders in /tmp folder
CITY_TEMPR_HOLDER="/tmp/khiweather.txt"
CITY_TEMPR_4_OFFLINE="/tmp/khiweather_offline.txt"
# Variables for UPS IP and SNMP community string. It ilwl be used to acquire data center temperature using UPS sensor
UPS_IP="10.0.0.10"
UPS_SNMP_STR="public"
# OID for temperature sensor using USP SNMP card/sendor
UPS_OID="1.3.6.1.4.1.13400.2.62.2.1.2.0"
URL="http://www.pmd.gov.pk/FFD/cp/pcurrenttemp.asp"

############################################################################
####### PART - 1 , DATA CENTER Temperature query via UPS SNMP enabled sensor
############################################################################

# Store DATA Center temperature queries result in buffer
NOC_TEMPR=`snmpwalk -v1 -c $UPS_SNMP_STR $UPS_IP -Onqv $UPS_OID`

# Divide stored buffer by 100 to get human readable format in Celsius
NOC_TEMPR_FINAL=`echo $(($NOC_TEMPR/100))`

# Validate if temperature is not valid, liek url not accessible, or other errors
# If error found, then PRINT ZERO 0 VALUE , else print the acquired result
NOC_TEMPR_FINAL_VALID=`echo ${#NOC_TEMPR_FINAL}`
if [ $NOC_TEMPR_FINAL_VALID -eq 2 ]; then
echo "$NOC_TEMPR_FINAL"
else
echo "0"
fi

###########################################################################
####### PART - 2 , QUERY KARACHI CITY TEMPERATURE FORM THE INTERNET
# USING PAKISTAN MET DEPt for KARACHI website, than TRIM THE RESULT #######
###########################################################################

CITY_TEMPR=`lynx -cache=1 -dump $URL &gt; $CITY_TEMPR_HOLDER`
CITY_TEMPR_VALUE=`grep -A 1 "Karachi" $CITY_TEMPR_HOLDER |sed '2q;d' | awk '{print $1}'`
CITY_TEMPR_VALID=`echo ${#CITY_TEMPR_VALUE}`

# Validate if temperature is not valid, like URL not accessible, OR other errors
# If error found, then PRINT last valid VALUE
if [ $CITY_TEMPR_VALID -eq 2 ]; then
#CITY_TEMPR_VALUE_FINAL=`echo $(($CITY_TEMPR_VALUE - 1))`
echo "$CITY_TEMPR_VALUE"
echo "$CITY_TEMPR_VALUE" &gt; $CITY_TEMPR_4_OFFLINE
else
cat $CITY_TEMPR_4_OFFLINE
fi

###################
####### END #######
###################


MRTG CFG file for weather

WorkDir:/var/www/mrtg
### MONITORING KARACHI Temprature vs our DATA Center ###
Target[KARACHI_CITY_vs_NOC_tempr]: `/temp/weather.sh`
Title[KARACHI_CITY_vs_NOC_tempr]: Temprature Monitoring / Data Center vs Karachi City using PAK MET Site by zaib
PageTop[KARACHI_CITY_vs_NOC_tempr]: &lt;h1&gt;Temprature Monitoring / Data Center vs Karachi City using PAK MET Site by zaib&lt;/h1&gt;
Options[KARACHI_CITY_vs_NOC_tempr]: gauge, growright, nopercent
MaxBytes[KARACHI_CITY_vs_NOC_tempr]: 60
Colours[KARACHI_CITY_vs_NOC_tempr]: B#467EEE,R#FF0000,BLUE#2184FF,RED#ff4f27
YLegend[KARACHI_CITY_vs_NOC_tempr]: Temprature
ShortLegend[KARACHI_CITY_vs_NOC_tempr]: c
LegendI[KARACHI_CITY_vs_NOC_tempr]: NOC Temprature
LegendO[KARACHI_CITY_vs_NOC_tempr]: City Temprature
Legend1[KARACHI_CITY_vs_NOC_tempr]: NOC Temprature
Legend2[KARACHI_CITY_vs_NOC_tempr]: City Temprature
#Unscaled[KARACHI_CITY_vs_NOC_tempr]: dwmy

 

 


Data Center Room Temperature & Humidity !

2-noc-tempr-vs-humidity

Above graph was made using Emerson Liebert UPS sensor using following OID’s and MRTG CFG

Temperature: 1.3.6.1.4.1.13400.2.62.2.1.2.0
Humidity: 1.3.6.1.4.1.13400.2.62.2.1.3.0


WorkDir:/var/www/mrtg
### MONITORING NOC ROOM TEMP ###
Target[noc_room_temp]: 1.3.6.1.4.1.13400.2.62.2.1.2.0&amp;1.3.6.1.4.1.13400.2.62.2.1.3.0:public@10.0.0.1 / 100
Options[noc_room_temp]: gauge, growright, nopercent
MaxBytes[noc_room_temp]: 100
Colours[noc_room_temp]: B#467EEE,R#FF0000,RED#ff4f27,DIRTY YELLOW#E6B420
#Unscaled[noc_room_temp]: dwmy
YLegend[noc_room_temp]: NOC Room Temprature/Humidity
Title[noc_room_temp]: NOC Room Tempr/Humidity
PageTop[noc_room_temp]: &lt;h1&gt;NOC Room Tempr/Humidity&lt;/h1&gt;
ShortLegend[noc_room_temp]: c/%
LegendI[noc_room_temp]: Temprature
LegendO[noc_room_temp]: Humidity
Legend1[noc_room_temp]: C NOC_Room Temp
Legend2[noc_room_temp]: Humidity


I will add more graphs later …

Regard’s

zaib!

December 8, 2016

Plotting Negative Value in rrdtool graph

Filed under: Linux Related — Tags: , — Syed Jahanzaib / Pinochio~:) @ 3:30 PM

Recently I was configuring an mrtg/rrd graph Where I had to display negative value as well along with others, but as per my findings mrtg/rrd graph doesn’t allow plotting Negative value. Let’s say we want to plot the temperature where we get both plus and negative values at different time of the day/night.

To do so, we have to tune the required rrd file to allow such storing.

Example: we have test.rrd file.
First get info by rrdtool

rrdtool info test.rrd |grep ds

you may see following

rrdtool info test.rrd |grep ds
ds[ds0].index = 0
ds[ds0].type = "GAUGE"
ds[ds0].minimal_heartbeat = 600
ds[ds0].min = 0.0000000000e+00
ds[ds0].max = 1.0000000000e+02
ds[ds0].last_ds = "0"
ds[ds0].value = 0.0000000000e+00
ds[ds0].unknown_sec = 0
ds[ds1].index = 1
ds[ds1].type = "GAUGE"
ds[ds1].minimal_heartbeat = 600
ds[ds1].min = 0.0000000000e+00
ds[ds1].max = 1.0000000000e+02
ds[ds1].last_ds = "0"
ds[ds1].value = 0.0000000000e+00
ds[ds1].unknown_sec = 0

now modify it by

rrdtool tune test.rrd --minimum ds0:-100

Now query rrdtool info again

rrdtool info test.rrd |grep ds
ds[ds0].index = 0
ds[ds0].type = "GAUGE"
ds[ds0].minimal_heartbeat = 600
ds[ds0].min = -1.0000000000e+02
ds[ds0].max = 1.0000000000e+02
ds[ds0].last_ds = "0"
ds[ds0].value = 0.0000000000e+00
ds[ds0].unknown_sec = 0
ds[ds1].index = 1
ds[ds1].type = "GAUGE"
ds[ds1].minimal_heartbeat = 600
ds[ds1].min = 0.0000000000e+00
ds[ds1].max = 1.0000000000e+02
ds[ds1].last_ds = "0"
ds[ds1].value = 0.0000000000e+00
ds[ds1].unknown_sec = 0

You will see the difference in ds[ds0].min value. Now we are good to go with negative plotting.

An example on how to plot negative values.

negative tempr.PNG


Regard’s
Syed Jahanzaib

December 7, 2016

Fighting with Ransomware !

Filed under: Microsoft Related, Symentec Related — Tags: , , , , , , — Syed Jahanzaib / Pinochio~:) @ 11:22 AM

ransomware

What is Ransomware 

Quite a HOT topic Now a days. Every email server administrator must be well familiarized with this malware and they try even harder to protect their users from this malware attack called locky (and many other similar variants) which encrypts users word/excel/etc documents and asks for money to restore them).

Our company users got hitted by this most smart malware repeatedly / several times resulting in great loss. Luckily most users data got recovered from Tape backup. This malware which usually comes by email , posted itself to be some valid / legitimate payment query & no matter how many times we provide users with education/warning about this matter, user stills open it considering it as valid email resulting in lost (encrypt/inaccessible) of all word/excel files.

We are using IBM Lotus Domino Email System along with Symantec Mail Security for Domino. With lots of R&D I am still unable to block this ransomware which comes in .JS files hidden inside .ZIP container. If I block .JS file inside the ZIP container, it will block legitimate PDF files as well. How frustrating ! The symantec should post some simple update to fix this issue. This issue is well discussed over here.

https://www.symantec.com/connect/ideas/exceptions-file-name-rule-smsmse


Workaround ! [Use Domain Group Policy to alter File Association Open with for .JS extension]

DISCLAIMER: THIS IS NOT A SOLUTION ! BUT JUST A `WORKAROUND` YOU CAN REFER TO.

THE PROPER SOLUTION WOULD BE TO USE SOME INTELLIGENT / UPDATED ANTISPAM/FILTRATION SYSTEM FOR YOUR EMAIL SYSTEM.

Since we cannot change our Symantec enterprise protection suite as it is covered under 3 years renewal (till 2018) . therefore aftering conducting lot of R&D I finally made a workaround for our DOMAIN USERS which is working Good so far.

I changed the .JS file extension OPEN WITH policy pointed to NOTEPAD.
[via Group_Policy ]

This way even if the user try to opens the .JS file, it will be open by notepad.
(instead of Windows Scripting Host)

I made changes to our domain controller in Windows 2008 R2

  • Login to Domain Controller PC
  • Open Group Policy (or by issuing following command)
    %SystemRoot%\system32\mmc.exe %SystemRoot%\system32\gpmc.msc
  • Edit the Default Domain Policy (or any custom you may have)
  • Goto User Configuration > Preferences > Control Panel Settings > Folder Options
  • Now Right click on Folder Options > New > Open With
  • Now use the below defined method as a reference to Update/Create the file extension

As shown in below image …

group policy.png

  • Action: Update
  • Files Extension: js
  • Assoticated Progra: %windir%\system32\notepad.exe
  • Set As Default : Select Tick on it

 

At client either issue gpupdate /force or restart the client pc or wait for the policy update.

Now try to open any .JS file and it will be opened in NOTEPAD (instead by windows scripting host program) and thus it will do no harm to user computer 😀 😀 😀

Please test this method and let us know your feedback on it 🙂

Note: you can use the same method to block / alter the file extension using Local Group POlicy


Alhamdolillah !

Regard’s
Syed Jahanzaib

 

December 6, 2016

SNMP on Centos missing few disk in snmp query

Filed under: Linux Related — Tags: , , , — Syed Jahanzaib / Pinochio~:) @ 9:43 AM

Image result for knowledge is power

If you have done a deep dive into the Ubuntu Ocean, and then start using Centos, you may realize that a quote “Ubuntu: made for Humans” is quite true indeed. z@ib

Recently I was configuring rrdtool/mrtg for remote Centos servers to to graphs disk storage , and found the difference between  MIb/OID of Windows/Ubuntu and Centos structure, therefore just sharing some notes for personnel references.

The problem I was getting in centos snmp querying that it was unable to see htStorageUsed.x counters. plus all mounted disks were not showing, only single disk was appearing in the for query result.

[for centos] To show all the disks , first edit the snmpd config file

nano /etc/snmp/snmpd.conf

add the following in end

disk /
includeAllDisks 10%

Restart the snmp service by

service snmpd restart

after a break, query the disk and you will find your missing disks 🙂

(Showing relevant Data only)

#df -h
/dev/sdX1 829G 310G 519G 38% /X/folder1
/dev/sdX2 3.6T 69M 3.4T 1% /X/folder2
/dev/sdX3 1.9T 1.9T 4.7G 100% /X/folder3

#snmpwalk -v1 -c PUBLIC localhost .1.3.6.1.4.1.2021 |grep dskDevice
UCD-SNMP-MIB::dskDevice.8  = STRING: /dev/sdX1
UCD-SNMP-MIB::dskDevice.10 = STRING: /dev/sdX2
UCD-SNMP-MIB::dskDevice.11 = STRING: /dev/sdX3


# snmpwalk -v1 -c PUBLIC -m /cfg/mibs/UCD-SNMP-MIB 192.168.0.1 dskPercent
UCD-SNMP-MIB::dskPercent.8 = INTEGER: 96
UCD-SNMP-MIB::dskPercent.10 = INTEGER: 58
UCD-SNMP-MIB::dskPercent.11 = INTEGER: 12


CFG File Examples :

I used 2 different methods to to plot disk storage.


# 192.168.200.1 / 4 TB disk
Target[192.168.200.1_4tb]: ( dskUsed.10&dskUsed.10:public@192.168.200.1 ) * 100 / ( dskTotal.10&dskTotal.10:public@192.168.200.1 ) / 8
Title[192.168.200.1_4tb]: Disk usage for FTP Portal 192.168.200.1 / 4 TB Disk
PageTop[192.168.200.1_4tb]: <H1> Disk usage for FTP Portal 192.168.200.1 / 4 TB Disk</H1>
MaxBytes[192.168.200.1_4tb]: 100
AbsMax[192.168.200.1_4tb]: 100
ShortLegend[192.168.200.1_4tb]: %
YLegend[192.168.200.1_4tb]: % of DISK
Legend1[192.168.200.1_4tb]: Used DISK
LegendI[192.168.200.1_4tb]: Used :
LegendO[192.168.200.1_4tb]:
Options[192.168.200.1_4tb]: growright,gauge,integer,nobanner,printrouter,pngdate,nopercent
#Unscaled[192.168.200.1_4tb]: ymwd

# 192.168.200.1 / 2 TB disk - dskPercent.x
Target[192.168.200.1_2tb]: dskPercent.8&dskPercent.8:public@192.168.200.1 / 8
Title[192.168.200.1_2tb]: Disk usage for FTP Portal 192.168.200.1 / 2 TB Disk / FOLDER1
PageTop[192.168.200.1_2tb]: <H1> Disk usage for FTP Portal 192.168.200.1 / 2 TB Disk / FOLDER1</H1>
MaxBytes[192.168.200.1_2tb]: 100
AbsMax[192.168.200.1_2tb]: 100
ShortLegend[192.168.200.1_2tb]: %
YLegend[192.168.200.1_2tb]: % of DISK
Legend1[192.168.200.1_2tb]: Used DISK
LegendI[192.168.200.1_2tb]: Used :
LegendO[192.168.200.1_2tb]:
Options[192.168.200.1_2tb]: growright,gauge,integer,nobanner,printrouter,pngdate,nopercent
#Unscaled[192.168.200.1_2tb]: ymwd


Graphs Example:

ftp-disk-usage

combined


 

December 1, 2016

rrdtool: MRTG next level graphing

Filed under: Linux Related, Mikrotik Related — Tags: , , , , , , , — Syed Jahanzaib / Pinochio~:) @ 10:56 AM

DRAFT VERSION: This is incomplete Post ! Some points may be missing, I will update them later ..

rrdtool

We all know what is MRTG. You can graph so many information including temperature humidity, speed, voltage, uptime, routers, active numbers of users,  number of printouts and sometimes out of the box graphing/zaib.

In this post, I am just posting reference material on how to move plain mrtg graphs to RRD. The advantage of RRD over MRTG is that using RRD you can generate the graphs on the fly, as opposed as MRTG that generates the graphs all the time, no matter that nobody sees the generated HTML pages or not. we can use RRD to make graphs with one minute interval, whereas in plain MRTG, we have to use 5 minutes interval which is not good to monitor jerks or sensitive devices.

For initial / basic level of MRTG installation on Ubuntu Server , refer to the inernet or my previous post at

https://aacable.wordpress.com/tag/mrtg-installation-on-ubuntu/


Sample CFG Files:

main MRTG.CFG file

cat /etc/mrtg.cfg


#########################
# START OF /etc/mrtg.cfg#
#########################
# Author: Syed Jahanzaib
# Email : aacable@hotmail.com
# Web : https://aacable.wordpress.com

WorkDir: /var/www/mrtg
Options[_]: growright,nobanner,pngdate,noinfo,nobanner

XSize[_]: 600
YSize[_]: 200
EnableIPv6: no
RunAsDaemon: no
Interval: 1
Logformat: rrdtool
#Use MIBS as per your local config, make sure you download the mibs as mentioned here
# https://aacable.wordpress.com/tag/mrtg-installation-on-ubuntu/
LoadMIBs: /cfg/mibs/HOST-RESOURCES-MIB /cfg/mibs/IF-MIB /cfg/mibs/UCD-SNMP-MIB
PageFoot[^]: Page managed by SYED JAHANZAIB
AddHead[_]:
<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-wp-preserve="%3Cstyle%20type%3D%22text%2Fcss%22%3E%20%3C!.%20a%20%7B%20color%3A%20%23263F66%3B%20text-decoration%3A%20none%3B%20%7D%20a%3Ahover%20%7B%20color%3A%20%23785B41%3B%20text-decoration%3A%20none%3B%20%7D%20body%20%7B%20color%3A%20black%3B%20font%3A%208pt%20Verdana%2C%20Geneva%2C%20Arial%2C%20Helvetica%2C%20sans-serif%3B%20%7D%20h1%20%7B%20font%3A%20bold%2016pt%20Verdana%2C%20Geneva%2C%20Arial%2C%20Helvetica%2C%20sans-serif%3B%20color%3A%20%23342A21%3B%20%7D%20h2%20%7B%20color%3A%20%23666666%3B%20font%3A%20bold%2012pt%20Verdana%2C%20Geneva%2C%20Arial%2C%20Helvetica%2C%20sans-serif%3B%20%7D%20h3%20%7B%20color%3A%20black%3B%20font%3A%20bold%209pt%20Verdana%2C%20Geneva%2C%20Arial%2C%20Helvetica%2C%20sans-serif%3B%20%7D%20table%20%7B%20border%3A%200%3B%20%7D%20td%20%7B%20background-color%3A%20%23E7DDD3%3B%20border%3A%200px%20solid%20%23FFFFFF%3B%20color%3A%20Black%3B%20font%3A%208pt%20Verdana%2C%20Geneva%2C%20Arial%2C%20Helvetica%2C%20sans-serif%3B%20vertical-align%3A%20top%3B%20%7D%20th%20%7B%20background-color%3A%20%23735A4A%3B%20color%3A%20White%3B%20font%3A%2011px%20Verdana%2C%20arial%2C%20geneva%2C%20helvetica%2C%20sans-serif%3B%20border%3A%200%3B%20font-weight%3A%20bold%3B%20text-align%3A%20left%3B%20%7D%20.%3E%20%3C%2Fstyle%3E" data-mce-resize="false" data-mce-placeholder="1" class="mce-object" width="20" height="20" alt="&lt;style&gt;" title="&lt;style&gt;" />

Background[_]: #F6F1EE

# Change it as required , it means mrtg will read following file and will create graphs based on its contents
# ADD remove them as required, they are added for reference purposes only
#Include: /cfg/temp.cfg
Include: /cfg/kesc.cfg
Include: /cfg/lanwan.cfg
Include: /cfg/radius.cfg
Include: /cfg/mt.cfg
Include: /cfg/ping.cfg
#Include: /cfg/vlan.cfg

##################
# END OF /etc/mrtg.cfg #
##################


radius.cfg


# Created by
# /usr/bin/cfgmaker public@10.0.0.1

# or for NT
WorkDir: /var/www/mrtg

### Interface 2 >> Descr: 'eth0' | Name: 'eth0' | Ip: '1' | Eth: '00' ###

Target[10.0.0.1_eth0]: #eth0:public@10.0.0.1:
SetEnv[10.0.0.1_eth0]: MRTG_INT_IP="10.0.0.1" MRTG_INT_DESCR="eth0"
MaxBytes[10.0.0.1_eth0]: 125000000
Title[10.0.0.1_eth0]: Traffic Analysis for eth0 -- BILLING
PageTop[10.0.0.1_eth0]:
<h1>Traffic Analysis for eth0 -- BILLING</h1>
<div id="sysdetails">
<table>
<tr>
<td>System:</td>
<td>in "BILLING"</td>
</tr>
<tr>
<td>Maintainer:</td>
<td>aacable at hotmail dot com</td>
</tr>
<tr>
<td>Description:</td>
<td>eth0</td>
</tr>
<tr>
<td>ifType:</td>
<td>ethernetCsmacd (6)</td>
</tr>
<tr>
<td>ifName:</td>
<td>eth0</td>
</tr>
<tr>
<td>Max Speed:</td>
<td>125.0 MBytes/s</td>
</tr>
<tr>
<td>Ip:</td>
<td>10.0.0.1 (click.onmypc.net)</td>
</tr>
</table>
</div>
#Percent of memory used
Target[radius_server_mem_ram]: ( hrStorageUsed.1&hrStorageUsed.1:public@10.0.0.1) * 100 / ( hrStorageSize.1&hrStorageSize.1:public@10.0.0.1 ) / 10
Title[radius_server_mem_ram]: Memory usage for Radius Server
PageTop[radius_server_mem_ram]:
<H1> Memory usage for Radius Server </H1>

MaxBytes[radius_server_mem_ram]: 100
AbsMax[radius_server_mem_ram]: 100
ShortLegend[radius_server_mem_ram]: %
YLegend[radius_server_mem_ram]: % of Memory
Legend1[radius_server_mem_ram]: Used Memory
LegendI[radius_server_mem_ram]: Used :
LegendO[radius_server_mem_ram]:
Options[radius_server_mem_ram]: growright,nopercent,gauge,integer,nobanner,printrouter,pngdate,noo
#Unscaled[radius_server_mem_ram]: ymwd

Target[linux_server_dis_usage]: ( hrStorageUsed.31&hrStorageUsed.31:public@10.0.0.1 ) * 100 / ( hrStorageSize.31&hrStorageSize.31:public@10.0.0.1 ) / 8
Title[linux_server_dis_usage]: Disk usage for Linux Server
PageTop[linux_server_dis_usage]:
<H1> Disk usage for Linux Server </H1>

MaxBytes[linux_server_dis_usage]: 100
AbsMax[linux_server_dis_usage]: 100
ShortLegend[linux_server_dis_usage]: %
YLegend[linux_server_dis_usage]: % of RM_DISK
Legend1[linux_server_dis_usage]: Used RM_DISK
LegendI[linux_server_dis_usage]: Used :
LegendO[linux_server_dis_usage]:
Options[linux_server_dis_usage]: growright,gauge,integer,nobanner,printrouter,pngdate,noo,nopercent,logscale
#Unscaled[linux_server_dis_usage]: ymwd


Mikrotik Sample CFG File


workdir: /var/www/mrtg/
#Options[_]: growright,nopercent

# Z_CCR_MIKROTIK CCR_1036 PPPoE ACTIVE Users
Target[mtPPPoEusers]: 1.3.6.1.4.1.9.9.150.1.1.1.0&1.3.6.1.4.1.9.9.150.1.1.1.0:public@10.0.0.1 / 8
Title[mtPPPoEusers]: Active PPPoE Users on Z_CCR_MIKROTIK CCR_1036
PageTop[mtPPPoEusers]:
<H1>Active PPPoE Users on Z_CCR_MIKROTIK CCR_1036</H1>

MaxBytes[mtPPPoEusers]: 2000
Colours[mtPPPoEusers]: B#8888ff,B#8888ff,B#5398ff,B#5398ff
Options[mtPPPoEusers]: growright,nopercent,gauge,integer,nobanner,printrouter,pngdate,noo
LegendI[mtPPPoEusers]: Active PPPoE Users on MT
LegendO[mtPPPoEusers]:
YLegend[mtPPPoEusers]: Active PPPoE Users on MT
Legend1[mtPPPoEusers]: Active PPPoE Users on MT
Legend2[mtPPPoEusers]:
#Unscaled[mtPPPoEusers]: dwmy

### Z_CCR_MIKROTIK CCR_1036 192.168.100.2 CPU load ###
Target[192.168.100.2_cpu]: 1.3.6.1.2.1.25.3.3.1.2.1&1.3.6.1.2.1.25.3.3.1.2.1:public@10.0.0.1 / 8
AbsMax[192.168.100.2_cpu]: 100
MaxBytes[192.168.100.2_cpu]: 100
Title[192.168.100.2_cpu]: Z_CCR_MIKROTIK CCR_1036 CPU load
PageTop[192.168.100.2_cpu]:
<H1>Z_CCR_MIKROTIK CCR_1036 CPU load</H1>

Options[192.168.100.2_cpu]: growright,gauge,integer,nobanner,printrouter,pngdate,noo,nopercent
Legend1[192.168.100.2_cpu]: CPU load
YLegend[192.168.100.2_cpu]: CPU load
ShortLegend[192.168.100.2_cpu]: %
LegendI[192.168.100.2_cpu]: CPU load (percentage)
#Unscaled[192.168.100.2_cpu]: y

### MONITORING Z_CCR_MIKROTIK CCR_1036 CPU TEMP ###
Target[mt.cpu.temp]: 1.3.6.1.4.1.14988.1.1.3.11.0&1.3.6.1.4.1.14988.1.1.3.11.0:public@10.0.0.1 / 100
Options[mt.cpu.temp]: gauge, growright, nopercent, noinfo
MaxBytes[mt.cpu.temp]: 100
Colours[mt.cpu.temp]: RED#ff4f27,Y#fffb15,RED#ff4f27,RED#fffb15
#Unscaled[mt.cpu.temp]: dwmy
YLegend[mt.cpu.temp]: CPU Temprature
Title[mt.cpu.temp]: Z_CCR_MIKROTIK CCR_1036 RB CPU Temprature
PageTop[mt.cpu.temp]:
<H1>Z_CCR_MIKROTIK CCR_1036 RB CPU Temprature</H1>

ShortLegend[mt.cpu.temp]: c
LegendI[mt.cpu.temp]:
LegendO[mt.cpu.temp]: CPU Temp
Legend1[mt.cpu.temp]: CPU Temprature
Legend2[mt.cpu.temp]: CPU Temprature

### MONITORING Z_CCR_MIKROTIK CCR_1036 RB TEMP ###
Target[mt.rb.temp]: 1.3.6.1.4.1.14988.1.1.3.10.0&1.3.6.1.4.1.14988.1.1.3.10.0:public@10.0.0.1 / 100
Options[mt.rb.temp]: gauge, growright, nopercent, noinfo
MaxBytes[mt.rb.temp]: 100
Colours[mt.rb.temp]: RED#ff4f27,Y#fffb15,RED#ff4f27,RED#fffb15
#Unscaled[mt.rb.temp]: dwmy
YLegend[mt.rb.temp]: RB Temprature
Title[mt.rb.temp]: Z_CCR_MIKROTIK CCR_1036 Router Board Temprature
PageTop[mt.rb.temp]:
<H1>Z_CCR_MIKROTIK CCR_1036 Router Board Temprature</H1>

ShortLegend[mt.rb.temp]: c
LegendI[mt.rb.temp]:
LegendO[mt.rb.temp]: RB Temp
Legend1[mt.rb.temp]: RB Temprature
Legend2[mt.rb.temp]: RB Temprature

### MONITORING Z_CCR_MIKROTIK CCR_1036 VOLTAGE Monitor ###
Target[mt-voltage]: 1.3.6.1.4.1.14988.1.1.3.8.0&1.3.6.1.4.1.14988.1.1.3.8.0:public@10.0.0.1 / 8
Options[mt-voltage]: growright,nopercent,gauge,integer,nobanner,printrouter,pngdate
MaxBytes[mt-voltage]: 30
Colours[mt-voltage]: RED#ff4f27,Y#fffb15,RED#ff4f27,RED#fffb15
Unscaled[mt-voltage]: dwmy
YLegend[mt-voltage]: Voltaeg Monitor
Title[mt-voltage]: Z_CCR_MIKROTIK CCR_1036 Cloudcore RB VOLTAGE Monitor
PageTop[mt-voltage]:
<H1>Z_CCR_MIKROTIK CCR_1036 Cloudcore RB VOLTAGE Monitor</H1>

ShortLegend[mt-voltage]: v
LegendI[mt-voltage]:
LegendO[mt-voltage]: Voltage
Legend1[mt-voltage]: Voltage
Legend2[mt-voltage]: Voltage

### MONITORING Z_CCR_MIKROTIK CCR_1036 power.consumption Watt Usage Monitor ###
Target[mt-powerconsumption]: .1.3.6.1.4.1.14988.1.1.3.12.0&.1.3.6.1.4.1.14988.1.1.3.12.0:public@10.0.0.1 / 100
Options[mt-powerconsumption]: gauge, growright, nopercent, noinfo
MaxBytes[mt-powerconsumption]: 1000
Colours[mt-powerconsumption]: RED#ff4f27,Y#fffb15,RED#ff4f27,RED#fffb15
#Unscaled[mt-powerconsumption]: dwmy
YLegend[mt-powerconsumption]: Watts USAGE Monitor
Title[mt-powerconsumption]: Z_CCR_MIKROTIK CCR_1036 Cloudcore RB Watts Usage Monitor
PageTop[mt-powerconsumption]:
<H1>Z_CCR_MIKROTIK CCR_1036 Cloudcore RB Watts Usage Monitor</H1>

ShortLegend[mt-powerconsumption]: W
LegendI[mt-powerconsumption]:
LegendO[mt-powerconsumption]: power.consumption.wts
Legend1[mt-powerconsumption]: power.consumption.wts
Legend2[mt-powerconsumption]: power.consumption.wts

### MONITORING Z_CCR_MIKROTIK CCR_1036 FAN-2 Speed Monitor ###
Target[mt-FAN2-speed]: 1.3.6.1.4.1.14988.1.1.3.18.0&1.3.6.1.4.1.14988.1.1.3.18.0:public@10.0.0.1 / 8
Options[mt-FAN2-speed]: growright,nopercent,gauge,integer,nobanner,printrouter,pngdate,logscale,noi
MaxBytes[mt-FAN2-speed]: 10000
Colours[mt-FAN2-speed]: RED#ff4f27,Y#fffb15,RED#ff4f27,RED#fffb15
#Unscaled[mt-FAN2-speed]: dwmy
YLegend[mt-FAN2-speed]: FAN-2 RPM
Title[mt-FAN2-speed]: Z_CCR_MIKROTIK CCR_1036 Cloudcore RB FAN-2 Speed Monitor
PageTop[mt-FAN2-speed]:
<H1>Z_CCR_MIKROTIK CCR_1036 Cloudcore RB FAN-2 Speed Monitor</H1>

ShortLegend[mt-FAN2-speed]: RPM
LegendI[mt-FAN2-speed]:
LegendO[mt-FAN2-speed]: fan-2.rpm.speed
Legend1[mt-FAN2-speed]: fan-2.rpm.speed
Legend2[mt-FAN2-speed]: fan-2.rpm.speed

### MONITORING Z_CCR_MIKROTIK CCR_1036 AMP Monitor ###
Target[mt-amp-mon]: 1.3.6.1.4.1.14988.1.1.3.13.0&1.3.6.1.4.1.14988.1.1.3.13.0:public@10.0.0.1 / 10000
Options[mt-amp-mon]: gauge,growright,nopercent,pngdate,nobanner
MaxBytes[mt-amp-mon]: 30
Colours[mt-amp-mon]: RED#ff4f27,Y#fffb15,RED#ff4f27,RED#fffb15
#Unscaled[mt-amp-mon]: dwmy
YLegend[mt-amp-mon]: AMP USAGE Monitor
Title[mt-amp-mon]: Z_CCR_MIKROTIK CCR_1036 Cloudcore RB AMP Monitor
PageTop[mt-amp-mon]:
<H1>Z_CCR_MIKROTIK CCR_1036 Cloudcore RB AMP Monitor</H1>

ShortLegend[mt-amp-mon]: amp
LegendI[mt-amp-mon]:
LegendO[mt-amp-mon]: amps
Legend1[mt-amp-mon]: amps
Legend2[mt-amp-mon]: amps


ping.cfg


WorkDir: /var/www/mrtg
### ping.cfg
# 10.0.0.1 MIKROTIK NAS SERVERPING GRAPH
Title[mikrotik.ping]: MIKROTIK NAS SERVER PING RTT / Pkt LOSS Report
PageTop[mikrotik.ping]:
<H1>MIKROTIK NAS SERVER PING RTT / Pkt LOSS Report</H1>

Target[mikrotik.ping]: `/cfg/norping.sh 10.0.0.1`
Colours[mikrotik.ping]: R#f75712,G#04bf27,G#70ff53,R#70ff53
MaxBytes[mikrotik.ping]: 100
AbsMax[mikrotik.ping]: 100
Options[mikrotik.ping]: growright,gauge,pngdate,printrouter,nopercent,noinfo,logscale
#growright,nopercent,gauge
LegendI[mikrotik.ping]: Pkt LOSS
LegendO[mikrotik.ping]: Active Round Trip Time
YLegend[mikrotik.ping]: RTT
Legend1[mikrotik.ping]: Pkt LOSS
Legend2[mikrotik.ping]: Active RTT

# 8.8.8.8 GOOGLE SERVERPING GRAPH
Title[8.8.8.8.ping]: GOOGLE DNS PING RTT / Pkt LOSS Report
PageTop[8.8.8.8.ping]:
<H1>GOOGLE DNS PING RTT / Pkt LOSS Report</H1>

Target[8.8.8.8.ping]: `/cfg/norping.sh 8.8.8.8`
Colours[8.8.8.8.ping]: R#f75712,G#04bf27,G#70ff53,R#70ff53
MaxBytes[8.8.8.8.ping]: 100
AbsMax[8.8.8.8.ping]: 100
Options[8.8.8.8.ping]: growright,gauge,pngdate,printrouter,nopercent,noinfo,logscale
#growright,nopercent,gauge
LegendI[8.8.8.8.ping]: Pkt LOSS
LegendO[8.8.8.8.ping]: Active Round Trip Time
YLegend[8.8.8.8.ping]: RTT
Legend1[8.8.8.8.ping]: Pkt LOSS
Legend2[8.8.8.8.ping]: Active RTT


kesc.cfg


WorkDir: /var/www/mrtg

# 10.0.0.2 MIKROTIK AP FOR KESC RPING GRAPH
Title[kesc.ping]: K.E.S.C LIGHT FAILURE GRAPH / MRTG GRAPH
PageTop[kesc.ping]:
<H1>K.E.S.C LIGHT FAILURE / MRTG GRAPH Report ! z@iB</H1>

Target[kesc.ping]: `/cfg/kping.sh 10.0.0.2`
Colours[kesc.ping]: RED#ff4f27,GREEN#00eb0c,RED#ff4f27,RED#fffb15
MaxBytes[kesc.ping]: 100
AbsMax[kesc.ping]: 100
Options[kesc.ping]: growright,gauge,pngdate,printrouter,nopercent,noinfo,logscale
ShortLegend[kesc.ping]: %
LegendI[kesc.ping]: K.E Light Loss
LegendO[kesc.ping]: K.E Availability
YLegend[kesc.ping]: Red Bar Shows Failure (:)


norping.sh


#!/bin/bash
HOST=$1
ping -c 3 $HOST > /dev/null
DATA=`ping -c 3 $1 -q `
if [ $? -eq 0 ]
then
echo "0"
echo $DATA | awk -F/ '{print $6 }'

else
echo "100
0"
fi


APACHE / WEB SERVER Section

To enable cgi execution in /var/www/mrtg folder, edit the apache config file, and

nano /etc/apache2/sites-enabled/000-default

and paste following so that the last section of file should be like below …


<Directory /var/www/mrtg>
AddHandler cgi-script .cgi
Options +ExecCGI +Indexes
DirectoryIndex index.cgi
</Directory>
</VirtualHost>


mrtg-rrd.cgi or index.cgi to graph creation

Following CGI file will create MRTG graph on the fly (on demand)


#!/usr/bin/perl -w
# $Id: mrtg-rrd.cgi,v 1.35 2003/08/18 15:58:57 kas Exp $
# mrtg-rrd.cgi: The script for generating graphs for MRTG statistics.
# Loosely modelled after the Rainer.Bawidamann@informatik.uni-ulm.de's
# 14all.cgi
use strict;
use POSIX qw(strftime);
use Time::Local;
# The %.1f should work on 5.005+. There may be other problems, though.
# I've tested this on 5.8.0 only, so mind the gap!
require 5.005;
# Location of RRDs.pm, if it is not in @INC
# use lib '/usr/lib/perl5/5.00503/i386-linux';
use RRDs;
use vars qw(@config_files @all_config_files %targets $config_time
%directories $version $imagetype);

# EDIT THIS to reflect all your MRTG config files
BEGIN { @config_files = qw(/etc/mrtg.cfg); }

$version = '0.7';
# This depends on what image format your libgd (and rrdtool) uses
$imagetype = 'png'; # or make this 'gif';
# strftime(3) compatibility test
my $percent_h = '%-H';
$percent_h = '%H' if (strftime('%-H', gmtime(0)) !~ /^\d+$/);
sub handler ($)
{
my ($q) = @_;
try_read_config($q->url());
my $path = $q->path_info();
$path =~ s/^\///;
$path =~ s/\/$//;
if (defined $directories{$path}) {
if ($q->path_info() =~ /\/$/) {
print_dir($path);
} else {
print "Location: ", $q->url(-path_info=>1), "/\n\n";
}
return;
}

my ($dir, $stat, $ext) = ($q->path_info() =~
/^(.*)\/([^\/]+)(\.html|-(day|week|month|year)\.$imagetype)$/);

$dir =~ s/^\///;

print_error("Undefined statistics")
unless defined $targets{$stat};

print_error("Incorrect directory")
unless defined $targets{$stat}{directory} || $targets{$stat}{directory} eq $dir;

my $tgt = $targets{$stat};

common_args($stat, $tgt, $q);

# We may be running under mod_perl or something. Do not destroy
# the original settings of timezone.
my $oldtz;
if (defined $tgt->{timezone}) {
$oldtz = $ENV{TZ};
$ENV{TZ} = $tgt->{timezone};
}

if ($ext eq '.html') {
do_html($tgt);
} elsif ($ext eq '-day.' . $imagetype) {
do_image($tgt, 'day');
} elsif ($ext eq '-week.' . $imagetype) {
do_image($tgt, 'week');
} elsif ($ext eq '-month.' . $imagetype) {
do_image($tgt, 'month');
} elsif ($ext eq '-year.' . $imagetype) {
do_image($tgt, 'year');
} else {
print_error("Unknown extension");
}
$ENV{TZ} = $oldtz
if defined $oldtz;
}

sub do_html($)
{
my ($tgt) = @_;

my @day = do_image($tgt, 'day');
my @week = do_image($tgt, 'week');
my @month = do_image($tgt, 'month');
my @year = do_image($tgt, 'year');

http_headers('text/html', $tgt->{config});
print <<'EOF';
<HTML>
<HEAD>
<TITLE>
EOF
print $tgt->{title} if defined $tgt->{title};
print "</TITLE>\n";

html_comments($tgt, 'd', @{$day[0]}) if $#day != -1;
html_comments($tgt, 'w', @{$week[0]}) if $#week != -1;
html_comments($tgt, 'm', @{$month[0]}) if $#month != -1;
html_comments($tgt, 'y', @{$year[0]}) if $#year != -1;

print $tgt->{addhead} if defined $tgt->{addhead};

print "</HEAD>\n", $tgt->{bodytag}, "\n";

print $tgt->{pagetop} if defined $tgt->{pagetop};

unless (defined $tgt->{options}{noinfo}) {
my @st = stat $tgt->{rrd};

print "

<hr>

\nThe statistics were last updated ",
strftime("<B>%A, %d %B, %H:%M:%S %Z</B>\n",
localtime($st[9]));
}

my $dayavg = $tgt->{config}->{interval};

html_graph($tgt, 'day', 'Daily', $dayavg . ' Minute', \@day);
html_graph($tgt, 'week', 'Weekly', '30 Minute', \@week);
html_graph($tgt, 'month', 'Monthly', '2 Hour', \@month);
html_graph($tgt, 'year', 'Yearly', '1 Day', \@year);

unless (defined $tgt->{options}{nolegend}) {
print <<EOF;

<hr>

<table WIDTH=500 BORDER=0 CELLPADDING=4 CELLSPACING=0>
EOF
print <<EOF unless ($tgt->{options}{noi});
<tr>
<td ALIGN=RIGHT><font SIZE=-1 COLOR="$tgt->{col1}">
<b>$tgt->{colname1} ###</b></font></td>
<td><font SIZE=-1>$tgt->{legend1}</font></td>
</tr>
EOF
print <<EOF unless ($tgt->{options}{noo});
<tr>
<td ALIGN=RIGHT><font SIZE=-1 COLOR="$tgt->{col2}">
<b>$tgt->{colname2} ###</b></font></td>
<td><font SIZE=-1>$tgt->{legend2}</font></td>
</tr>
EOF
if ($tgt->{withpeak} ne '') {
print <<EOF unless ($tgt->{options}{noi});
<tr>
<td ALIGN=RIGHT><font SIZE=-1 COLOR="$tgt->{col3}">
<b>$tgt->{colname3} ###</b></font></td>
<td><font SIZE=-1>$tgt->{legend3}</font></td>
</tr>
EOF
print <<EOF unless ($tgt->{options}{noo});
<tr>
<td ALIGN=RIGHT><font SIZE=-1 COLOR="$tgt->{col4}">
<b>$tgt->{colname4} ###</b></font></td>
<td><font SIZE=-1>$tgt->{legend4}</font></td>
</tr>
EOF
}
print <<EOF;</table>
EOF
}

print_banner($tgt->{config})
unless defined $tgt->{options}{nobanner};

print $tgt->{pagefoot} if defined $tgt->{pagefoot};
print "\n", <<'EOF';
</body>
</html>
EOF

}

sub html_comments($$@)
{
my ($tgt, $letter, @val) = @_;

return if $#val == -1;

unless ($tgt->{options}{noi}) {
print "<!-- maxin $letter ", $val[1], " -->\n";
print "<!-- avin $letter ", $val[3], " -->\n";
print "<!-- cuin $letter ", $val[5], " -->\n";
}
unless ($tgt->{options}{noo}) {
print "<!-- maxout $letter ", $val[0], " -->\n";
print "<!-- avout $letter ", $val[2], " -->\n";
print "<!-- cuout $letter ", $val[4], " -->\n";
}
}
sub html_graph($$$$$)
{
my ($tgt, $ext, $freq, $period, $params) = @_;

return unless defined $tgt->{$ext};

my @values = @{$params->[0]};
my $x = $params->[1];
my $y = $params->[2];

$x *= $tgt->{xzoom} if defined $tgt->{xzoom};
$y *= $tgt->{yzoom} if defined $tgt->{yzoom};

my $kilo = $tgt->{kilo};
my @kmg = split(',', $tgt->{kmg});

my $fmt;
if (defined $tgt->{options}{integer}) {
$fmt = '%d';
} else {
$fmt = '%.1f';
}

my @percent = do_percent($tgt, \@values);
my @relpercent = do_relpercent($tgt, \@values);

my @nv;
for my $val (@values) {
if (@kmg == 0) { # kMG[target]: <empty>
push @nv, sprintf($fmt, $val);
next;
}
for my $si (@kmg) {
if ($val < 10000) {
push @nv, sprintf($fmt, $val) . " $si";
last;
}
$val /= $kilo;
}
}
@values = @nv;

print "

<hr>

\n<B>\`$freq\' Graph ($period Average)</B>
\n";

print '<IMG SRC="', $tgt->{url}, '-', $ext, '.' . $imagetype .
'" WIDTH=', $x, ' HEIGHT=', $y, ' ALT="', $freq,
' Graph" VSPACE=10 ALIGN=TOP>
', "\n";
print '
<TABLE CELLPADDING=0 CELLSPACING=0>';
print <<EOF if $tgt->{legendi} ne '' && !$tgt->{options}{noi};
<TR>
<TD ALIGN=RIGHT><SMALL>Max <FONT COLOR="$tgt->{col1}">$tgt->{legendi}</FONT></SMALL></TD>
<TD ALIGN=RIGHT><SMALL>&nbsp;$values[1]$tgt->{shortlegend}$percent[1]</SMALL></TD>
<TD WIDTH=5></TD>
<TD ALIGN=RIGHT><SMALL>Average <FONT COLOR="$tgt->{col1}">$tgt->{legendi}</FONT></SMALL></TD>
<TD ALIGN=RIGHT><SMALL>&nbsp;$values[3]$tgt->{shortlegend}$percent[3]</SMALL></TD>
<TD WIDTH=5></TD>
<TD ALIGN=RIGHT><SMALL>Current <FONT COLOR="$tgt->{col1}">$tgt->{legendi}</FONT></SMALL></TD>
<TD ALIGN=RIGHT><SMALL>&nbsp;$values[5]$tgt->{shortlegend}$percent[5]</SMALL></TD>
</TR>

EOF
print <<EOF if $tgt->{legendo} ne '' && !$tgt->{options}{noo};
<TR>
<TD ALIGN=RIGHT><SMALL>Max <FONT COLOR="$tgt->{col2}">$tgt->{legendo}</FONT></SMALL></TD>
<TD ALIGN=RIGHT><SMALL>&nbsp;$values[0]$tgt->{shortlegend}$percent[0]</SMALL></TD>
<TD WIDTH=5></TD>
<TD ALIGN=RIGHT><SMALL>Average <FONT COLOR="$tgt->{col2}">$tgt->{legendo}</FONT></SMALL></TD>
<TD ALIGN=RIGHT><SMALL>&nbsp;$values[2]$tgt->{shortlegend}$percent[2]</SMALL></TD>
<TD WIDTH=5></TD>
<TD ALIGN=RIGHT><SMALL>Current <FONT COLOR="$tgt->{col2}">$tgt->{legendo}</FONT></SMALL></TD>
<TD ALIGN=RIGHT><SMALL>&nbsp;$values[4]$tgt->{shortlegend}$percent[4]</SMALL></TD>

EOF
if (defined $tgt->{options}{dorelpercent}) {
print <<"EOF";
</TR>
<TR>
<TD ALIGN=RIGHT><SMALL>Max <FONT COLOR="$tgt->{col5}">&nbsp;Percentage:</FONT></SMALL></TD>
<TD ALIGN=RIGHT><SMALL>&nbsp;$relpercent[0]</SMALL></TD>
<TD WIDTH=5></TD>
<TD ALIGN=RIGHT><SMALL>Average <FONT COLOR="$tgt->{col5}">&nbsp;Percentage:</FONT></SMALL></TD>
<TD ALIGN=RIGHT><SMALL>&nbsp;$relpercent[1]</SMALL></TD>
<TD WIDTH=5></TD>
<TD ALIGN=RIGHT><SMALL>Current <FONT COLOR="$tgt->{col5}">&nbsp;Percentage:</FONT></SMALL></TD>
<TD ALIGN=RIGHT><SMALL>&nbsp;$relpercent[2]</SMALL></TD>

EOF
}
print <<'EOF';
</TR>
</TABLE>

EOF
}

sub do_percent($$)
{
my ($tgt, $values) = @_;

my @percent = ('', '', '', '', '', '');

return @percent if defined $tgt->{options}{nopercent};

for my $val (0..$#$values) {
my $mx = ($val % 2 == 1) ? $tgt->{maxbytes1} : $tgt->{maxbytes2};
next unless defined $mx;
my $p = sprintf("%.1f", $values->[$val]*100/$mx);
$percent[$val] = ' (' . $p . '%)';
}

@percent;
}

sub do_relpercent($$)
{
my ($tgt, $values) = @_;

my @percent = ('', '', '');

return @percent unless defined $tgt->{options}{dorelpercent};

for my $val (0..2) {
$percent[$val] = sprintf("%.1f",
$values->[2*$val+1] * 100 / $values->[2*$val])
if $values->[2*$val] > 0;
$percent[$val] ||= 0;
$percent[$val] .= ' %';
}

@percent;
}

sub http_headers($$)
{
my ($content_type, $cfg) = @_;

print <<"EOF"; Content-Type: $content_type Refresh: $cfg->{refresh}
Pragma: no-cache
EOF
# Expires header calculation stolen from CGI.pm
print strftime("Expires: %a, %d %b %Y %H:%M:%S GMT\n",
gmtime(time+60*$cfg->{interval}));

print "\n";
}

sub do_image($$)
{
my ($target, $ext) = @_;

my $file = $target->{$ext};

return unless defined $file;

# Now the vertical rule at the end of the day
my @t = localtime(time);
$t[0] = $t[1] = $t[2] = 0;

my $seconds;
my $oldsec;
my $back;
my $xgrid;

my $unscaled;
my $withpeak;

my $noi = 1 if $target->{options}{noi};
my $noo = 1 if $target->{options}{noo};

if ($ext eq 'day') {
$seconds = timelocal(@t);
$back = 30*3600; # 30 hours
$oldsec = $seconds - 86400;
$unscaled = 1 if $target->{unscaled} =~ /d/;
$withpeak = 1 if $target->{withpeak} =~ /d/;
# We need this only for day graph. The other ones
# are magically correct.
$xgrid = 'HOUR:1:HOUR:6:HOUR:2:0:' . $percent_h;
} elsif ($ext eq 'week') {
$seconds = timelocal(@t);
$t[6] = ($t[6]+6) % 7;
$seconds -= $t[6]*86400;
$back = 8*86400; # 8 days
$oldsec = $seconds - 7*86400;
$unscaled = 1 if $target->{unscaled} =~ /w/;
$withpeak = 1 if $target->{withpeak} =~ /w/;
} elsif ($ext eq 'month') {
$t[3] = 1;
$seconds = timelocal(@t);
$back = 36*86400; # 36 days
$oldsec = $seconds - 30*86400; # FIXME (the right # of days!!)
$unscaled = 1 if $target->{unscaled} =~ /m/;
$withpeak = 1 if $target->{withpeak} =~ /m/;
} elsif ($ext eq 'year') {
$t[3] = 1;
$t[4] = 0;
$seconds = timelocal(@t);
$back = 396*86400; # 365 + 31 days
$oldsec = $seconds - 365*86400; # FIXME (the right # of days!!)
$unscaled = 1 if $target->{unscaled} =~ /y/;
$withpeak = 1 if $target->{withpeak} =~ /y/;
} else {
print_error("Unknown file extension: $ext");
}

my @local_args;

if ($unscaled) {
@local_args = ('-u', $target->{maxbytes1});
push @local_args, '--rigid' unless defined $target->{absmax};
}

if ($xgrid) {
push @local_args, '-x', $xgrid;
}

my @local_args_end;

if ($withpeak) {
push @local_args_end, 'LINE1:maxin'.$target->{col3}.':MaxIn'
unless $noi;
push @local_args_end, 'LINE1:maxout'.$target->{col4}.':MaxOut'
unless $noo;
}

my @rv = RRDs::graph($file, '-s', "-$back", @local_args,
@{$target->{args}}, "VRULE:$oldsec#ff0000",
"VRULE:$seconds#ff0000", @local_args_end);

my $rrd_error = RRDs::error;
print_error("RRDs::graph failed, $rrd_error") if defined $rrd_error;

# In array context just return the values
if (wantarray) {
if (defined $target->{factor}) {
@{$rv[0]} = map { $_ * $target->{factor} } @{$rv[0]};
}
if ($noi) {
return ([$rv[0][0], 0, $rv[0][1], 0, $rv[0][2], 0],
$rv[1], $rv[2]);
} elsif ($noo) {
return ([0, $rv[0][0], 0, $rv[0][1], 0, $rv[0][2]],
$rv[1], $rv[2]);
} else {
return @rv;
}
}

# Not in array context ==> print out the PNG file.
open PNG, "<$file" or print_error("Can't open $file: $!"); binmode PNG; http_headers("image/$imagetype", $target->{config});

my $buf;
# could be sendfile in Linux 😉
while(sysread PNG, $buf, 8192) {
print $buf;
}
close PNG;
}

sub common_args($$$)
{
my ($name, $target, $q) = @_;

return @{$target->{args}} if defined @{$target->{args}};

my $noi = 1 if $target->{options}{noi};
my $noo = 1 if $target->{options}{noo};

$target->{name} = $name;

$target->{directory} = ''
unless defined $target->{directory};

my $tdir = $target->{directory};
$tdir .= '/'
unless $tdir eq '' || $tdir =~ /\/$/;

$target->{url} = $q->url . '/' . $tdir . $name;

my $cfg = $target->{config};

my $dir = $cfg->{workdir};
$dir = $cfg->{logdir}
if defined $cfg->{logdir};

$target->{rrd} = $dir . '/' . $tdir . $name . '.rrd';

%{$target->{options}} = ()
unless defined %{$target->{options}};

$dir = $cfg->{workdir};
$dir = $cfg->{imagedir}
if defined $cfg->{imagedir};

$target->{suppress} ||= '';

$target->{day} = $dir . '/' . $tdir . $name
. '-day.' . $imagetype unless $target->{suppress} =~ /d/;
$target->{week} = $dir . '/' . $tdir . $name
. '-week.' . $imagetype unless $target->{suppress} =~ /w/;
$target->{month} = $dir . '/' . $tdir . $name
. '-month.' . $imagetype unless $target->{suppress} =~ /m/;
$target->{year} = $dir . '/' . $tdir . $name
. '-year.' . $imagetype unless $target->{suppress} =~ /y/;

$target->{maxbytes1} = $target->{maxbytes}
if defined $target->{maxbytes} && !defined $target->{maxbytes1};

$target->{maxbytes2} = $target->{maxbytes1}
if defined $target->{maxbytes1} && !defined $target->{maxbytes2};

my @args = ();

push @args, '--lazy', '-c', 'FONT#000000', '-c',
'MGRID#000000', '-c', 'FRAME#000000',
'-g', '-l', '0';

$target->{background} = '#f5f5f5'
unless defined $target->{background};

push @args, '-c', 'BACK'. $target->{background};

push @args, '-c', 'SHADEA' . $target->{background},
'-c', 'SHADEB' . $target->{background}
if defined $target->{options}{noborder};

if (defined $target->{options}{noarrow}) {
push @args, '-c', 'ARROW' . $target->{background};
} else {
push @args, '-c', 'ARROW#000000';
}

push @args, '-b', $target->{kilo}
if defined $target->{kilo};

if (defined $target->{xsize}) {
if (defined $target->{xscale}) {
push @args, '-w', $target->{xsize}*$target->{xscale};
} else {
push @args, '-w', $target->{xsize};
}
}

if (defined $target->{ysize}) {
if (defined $target->{yscale}) {
push @args, '-h', $target->{ysize}*$target->{yscale};
} else {
push @args, '-h', $target->{ysize};
}
}

my $scale = 1;

if (defined $target->{options}->{perminute}) {
$scale *= 60;
} elsif (defined $target->{options}->{perhour}) {
$scale *= 3600;
}

if (defined $target->{options}->{bits}) {
$scale *= 8;
$target->{ylegend} = 'Bits per second'
unless defined $target->{ylegend};
$target->{legend1} = 'Incoming Traffic in Bits per Second'
unless defined $target->{legend1};
$target->{legend2} = 'Outgoing Traffic in Bits per Second'
unless defined $target->{legend2};
$target->{legend3} = 'Peak Incoming Traffic in Bits per Second'
unless defined $target->{legend3};
$target->{legend4} = 'Peak Outgoing Traffic in Bits per Second'
unless defined $target->{legend4};
$target->{shortlegend} = 'b/s'
unless defined $target->{shortlegend};
} else {
$target->{ylegend} = 'Bytes per second'
unless defined $target->{ylegend};
$target->{legend1} = 'Incoming Traffic in Bytes per Second'
unless defined $target->{legend1};
$target->{legend2} = 'Outgoing Traffic in Bytes per Second'
unless defined $target->{legend2};
$target->{legend3} = 'Peak Incoming Traffic in Bytes per Second'
unless defined $target->{legend3};
$target->{legend4} = 'Peak Outgoing Traffic in Bytes per Second'
unless defined $target->{legend4};
$target->{shortlegend} = 'B/s'
unless defined $target->{shortlegend};
}

if ($scale > 1) {
push @args, "DEF:in0=$target->{rrd}:ds0:AVERAGE",
"CDEF:in=in0,$scale,*",
"DEF:maxin0=$target->{rrd}:ds0:MAX",
"CDEF:maxin=maxin0,$scale,*"
unless $noi;
push @args, "DEF:out0=$target->{rrd}:ds1:AVERAGE",
"CDEF:out=out0,$scale,*",
"DEF:maxout0=$target->{rrd}:ds1:MAX",
"CDEF:maxout=maxout0,$scale,*"
unless $noo;
} else {
push @args, "DEF:in=$target->{rrd}:ds0:AVERAGE",
"DEF:maxin=$target->{rrd}:ds0:MAX"
unless $noi;
push @args, "DEF:out=$target->{rrd}:ds1:AVERAGE",
"DEF:maxout=$target->{rrd}:ds1:MAX"
unless $noo;
}

my $i=1;
for my $coltext (split(/,/, $target->{colours})) {
my ($text, $rgb) = ($coltext =~ /^([^#]+)(#[0-9a-fA-F]{6})$/);
$target->{'col'.$i} = $rgb;
$target->{'colname'.$i} = $text;
$i++;
}

push @args, '-v', $target->{ylegend};

push @args, 'AREA:in' . $target->{col1} . ':In',
unless $noi;
push @args, 'LINE2:out' . $target->{col2} . ':Out'
unless $noo;

push @args, 'PRINT:out:MAX:%.1lf' unless $noo;
push @args, 'PRINT:in:MAX:%.1lf' unless $noi;
push @args, 'PRINT:out:AVERAGE:%.1lf' unless $noo;
push @args, 'PRINT:in:AVERAGE:%.1lf' unless $noi;
push @args, 'PRINT:out:LAST:%.1lf' unless $noo;
push @args, 'PRINT:in:LAST:%.1lf' unless $noi;

if (defined $target->{maxbytes1}) {
$target->{maxbytes1} *= $scale;
push @args, 'HRULE:' . $target->{maxbytes1} . '#cc0000';
}

if (defined $target->{maxbytes2}) {
$target->{maxbytes2} *= $scale;
push @args, 'HRULE:' . $target->{maxbytes2} . '#cccc00'
if $target->{maxbytes2} != $target->{maxbytes1};
}

@{$target->{args}} = @args;

@args;
}

sub try_read_config($)
{
my ($prefix) = (@_);
$prefix =~ s/\/[^\/]*$//;

# Verify the version of RRDtool:
if (!defined $RRDs::VERSION || $RRDs::VERSION < 1.000331) {
print_error("Please install more up-to date RRDtool - need at least 1.000331");
}

my $read_cfg;
if (!defined $config_time) {
$read_cfg = 1;
} else {
for my $file (@all_config_files) {
my @stat = stat $file;
if ($config_time < $stat[9]) { $read_cfg = 1; last; } } } return unless $read_cfg; my %defaults = ( xsize => 400,
ysize => 100,
kmg => ',k,M,G,T,P',
kilo => 1000,
bodytag => "<BODY BGCOLOR=#ffffff>\n",
colours => 'GREEN#00cc00,BLUE#0000ff,DARK GREEN#006600,MAGENTA#ff00ff,AMBER#ef9f4f',
legendi => '&nbsp;In:',
legendo => '&nbsp;Out:',
unscaled => '',
withpeak => '',
directory => '',
);

%targets = ();

@all_config_files = @config_files;

my $order = 0;
for my $cfgfile (@config_files) {
%{$targets{_}} = %defaults;
%{$targets{'^'}} = ();
%{$targets{'$'}} = ();

my $cfgref = {
refresh => 300,
interval => 5,
icondir => $prefix
};

read_mrtg_config($cfgfile, \%defaults, $cfgref, \$order);
}

delete $targets{'^'};
delete $targets{_};
delete $targets{'$'};

parse_directories();

$config_time = time;
}

sub read_mrtg_config($$$$);

sub read_mrtg_config($$$$)
{
my ($file, $def, $cfgref, $order) = @_;

my %defaults = %$def;

my @lines;

open(CFG, "<$file") || print_error("Cannot open config file: $!");
while (<CFG>) {
chomp; # remove newline
s/\s+$//; # remove trailing space
s/\s+/ /g; # collapse white spaces to ' '
next if /^ *\#/; # skip comment lines
next if /^\s*$/; # skip empty lines
if (/^ \S/) { # multiline options
$lines[$#lines] .= $_;
} else {
push @lines, $_;
}
}
close CFG;

foreach (@lines) {
if (/^\s*([\w\d]+)\[(\S+)\]\s*:\s*(.*)$/) {
my ($tgt, $opt, $val) = (lc($2), lc($1), $3);
unless (exists $targets{$tgt}) {
# pre-set defaults constructed on all of ^, _, and $
for my $key (%{$targets{'^'}}) {
$targets{$tgt}{$key} = $targets{'^'}{$key};
}
for my $key (%{$targets{'$'}}) {
$targets{$tgt}{$key} .= $targets{'$'}{$key};
}
# WARNING: Tobi explicitly said that when all ^, _, and $
# options are set, the result should be just the value
# of the _ option (when the option itself is not explicitly
# defined. I do not agree with him here but I respect this
# and will try to be compatible with MRTG.
for my $key (%{$targets{'_'}}) {
$targets{$tgt}{$key} = $targets{'_'}{$key};
}

# anonymous hash ref - need copy, not ref
delete $targets{$tgt}{options};
# The same as above - we need to create this
# based on [^], [_], and [$] values
%{$targets{$tgt}{options}} = ();
%{$targets{$tgt}{options}} = %{$targets{'^'}{options}}
if defined $targets{'^'}{options};
%{$targets{$tgt}{options}} = (%{$targets{$tgt}{options}},
%{$targets{'_'}{options}})
if defined $targets{'_'}{options};
%{$targets{$tgt}{options}} = (%{$targets{$tgt}{options}},
%{$targets{'$'}{options}})
if defined $targets{'$'}{options};

$targets{$tgt}{order} = ++$$order;
$targets{$tgt}{config} = $cfgref;
}
if ($tgt eq '_' && $val eq '') {
if (defined $defaults{$opt}) {
$targets{_}{$opt} = $defaults{$opt};
} else {
delete $targets{_}{$opt};
}
} elsif (($tgt eq '^' || $tgt eq '$') && $val eq '') {
delete $targets{$tgt}{$opt};
} elsif ($opt eq 'options') {
# Do not forget defaults [^] and [$]
delete $targets{$tgt}{options};
%{$targets{$tgt}{options}} = %{$targets{'^'}{options}}
if defined $targets{'^'}{options};
$val = lc($val);
map { $targets{$tgt}{options}{$_} = 1 } ($val =~ m/([a-z]+)/g);
%{$targets{$tgt}{options}} = (%{$targets{$tgt}{options}},
%{$targets{'$'}{options}})
if defined $targets{'$'}{options};
} else {
my $pre = $targets{'^'}{$opt}
if defined $targets{'^'}{$opt};
$pre ||= '';
$targets{$tgt}{$opt} = $pre.$val;
$targets{$tgt}{$opt} .= $targets{'$'}{$opt}
if defined $targets{'$'}{$opt};
}
next;
} elsif (/^Include\s*:\s*(\S*)$/) {
push @all_config_files, $1;
read_mrtg_config($1, $def, $cfgref, $order);
next;
} elsif (/^([\w\d]+)\s*:\s*(\S.*)$/) {
my ($opt, $val) = (lc($1), $2);
$cfgref->{$opt} = $val;
next;
}
print_error("Parse error in $file near $_");
}

if (defined $cfgref->{pathadd}) {
$ENV{PATH} .= ':'.$cfgref->{pathadd};
}

# if (defined $cfgref->{libadd}) {
# use lib $cfgref->{libadd}
# }
}

sub parse_directories {
%directories = ();

# FIXME: the sort is expensive
for my $name (sort { $targets{$a}{order} <=> $targets{$b}{order} } keys %targets) {
my $dir = $targets{$name}{directory}
if defined $targets{$name}{directory};
$dir = '' unless defined $dir;

my $prefix = '';
for my $component (split /\/+/, $dir) {
unless (defined $directories{$prefix.$component}) {
push (@{$directories{$prefix}{subdir}},
$component);

# For the directory, get the global parameters
# from the # config of the first item of the
# directory:
$directories{$prefix}{config} =
$targets{$name}{config};
$directories{$prefix}{bodytag} =
$targets{$name}{bodytag};
}
$prefix .= $component . '/';
}
unless (defined $directories{$dir}) {
$directories{$dir}{config} =
$targets{$name}{config};
$directories{$dir}{bodytag} =
$targets{$name}{bodytag};
}

push (@{$directories{$dir}{target}}, $name);
}
}

sub print_dir($) {
my ($dir) = @_;

my $dir1 = $dir . '/';

http_headers('text/html', $directories{$dir}{config});

print <<EOF;
<HTML>
<HEAD>
<TITLE>MRTG: Directory $dir1</TITLE>
</HEAD>
EOF
print $directories{$dir}{bodytag};

my $subdirs_printed;
if (defined @{$directories{$dir}{subdir}}) {
$subdirs_printed = 1;
print <<EOF;
<H1>MRTG subdirectories in the directory $dir1</H1>
<UL>
EOF
for my $item (@{$directories{$dir}{subdir}}) {
print "
<LI><A HREF=\"$item/\">$item/</A>\n";
}

print "</UL>

\n";
}
if (defined @{$directories{$dir}{target}}) {
print "

<hr>

\n" if defined $subdirs_printed;
print <<EOF;
<H1>MRTG graphs in the directory $dir1</H1>
<TABLE BORDER=0 WIDTH=100%>
EOF
my $odd;
for my $item (@{$directories{$dir}{target}}) {
my $itemname = $item;
$itemname = $targets{$item}{title}
if defined $targets{$item}{title};
print "
<TR>\n" unless $odd;
print <<EOF;
<TD><A HREF="$item.html">$itemname
<IMG SRC="$item-day.$imagetype" BORDER=0 ALIGN=TOP VSPACE=10 ALT="$item">
</A><BR CLEAR=ALL>
</TD>

EOF
print " </TR>

\n" if $odd;
$odd = !$odd;
}
print " </TR>

\n</TABLE>

\n";
}

print_banner($directories{$dir}{config});
print "</BODY>\n</HTML>\n";
}

sub print_banner($) {
my $cfg = shift;

print <<EOF;

<hr>

<table BORDER=0 CELLSPACING=0 CELLPADDING=0>
<tr>
<td WIDTH=63><a ALT="MRTG" HREF="http://ee-staff.ethz.ch/~oetiker/webtools/mrtg/mrtg.html"><img BORDER=0 SRC="$cfg->{icondir}/mrtg-l.$imagetype"></a></td>
<td WIDTH=25><a ALT="" HREF="http://ee-staff.ethz.ch/~oetiker/webtools/mrtg/mrtg.html"><img BORDER=0 SRC="$cfg->{icondir}/mrtg-m.$imagetype"></a></td>
<td WIDTH=388><a ALT="" HREF="http://ee-staff.ethz.ch/~oetiker/webtools/mrtg/mrtg.html"><img BORDER=0 SRC="$cfg->{icondir}/mrtg-r.$imagetype"></a></td>
</tr>
</table>
<spacer TYPE=VERTICAL SIZE=4>
<table BORDER=0 CELLSPACING=0 CELLPADDING=0 WIDTH=476>
<tr VALIGN=top>
<td ALIGN=LEFT><font FACE="Arial,Helvetica" SIZE=2>
version 2.9.17</font></td>
<td ALIGN=RIGHT><font FACE="Arial,Helvetica" SIZE=2>
<a HREF="http://ee-staff.ethz.ch/~oetiker/">Tobias Oetiker</a>
<a HREF="mailto:oetiker\@ee.ethz.ch">&lt;oetiker\@ee.ethz.ch&gt;</a>
</font></td>
</tr>
<tr>
<td></td>
<td ALIGN=RIGHT><font FACE="Arial,Helvetica" SIZE=2>
and&nbsp;<a HREF="http://www.bungi.com">Dave&nbsp;Rand</a>&nbsp;<a HREF="mailto:dlr\@bungi.com">&lt;dlr\@bungi.com&gt;</a></font></td>
<tr VALIGN=top>
<td ALIGN=LEFT><font FACE="Arial,Helvetica" SIZE=2>
<A HREF=http://www.fi.muni.cz/~kas/mrtg-rrd/>mrtg-rrd.cgi version $version</A>
</font></td>
<td ALIGN=RIGHT><font FACE="Arial,Helvetica" SIZE=2>
<A HREF="http://www.fi.muni.cz/~kas/">Jan "Yenya" Kasprzak</A>
<A HREF="mailto:kas\@fi.muni.cz">&lt;kas\@fi.muni.cz&gt;</A>
</font></td>
</tr>
</table>
EOF
print '<!--$Id: mrtg-rrd.cgi,v 1.35 2003/08/18 15:58:57 kas Exp $-->', "\n";
}

sub dump_targets() {
for my $tgt (keys %targets) {
print "Target $tgt:\n";
for my $opt (keys %{$targets{$tgt}}) {
if ($opt eq 'options') {
print "\toptions: ";
for my $o1 (keys %{$targets{$tgt}{options}}) {
print $o1, ",";
}
print "\n";
next;
}
print "\t$opt: ", $targets{$tgt}{$opt}, "\n";
}
}
}

sub dump_directories {
print "Directories:\n";

for my $dir (keys %directories) {
print "Directory $dir:\n";
for my $item (@{$directories{$dir}}) {
print "\t$item\n";
}
}
}

sub print_error(@)
{
print "Content-Type: text/plain\n\nError: ", join(' ', @_), "\n";
exit 0;
}

#--BEGIN CGI--
#For CGI, use this:

use CGI;
my $q = new CGI;

# thttpd fix up by Akihiro Sagawa
if ($q->server_software() =~ m|^thttpd/|) {
my $path = $q->path_info();
$path .= '/' if ($q->script_name=~ m|/$|);
$q->path_info($path);
}

handler($q);

#--END CGI--
#--BEGIN FCGI--
# For FastCGI, uncomment this and comment out the above:
#-# use FCGI;
#-# use CGI;
#-#
#-# my $req = FCGI::Request();
#-#
#-# while ($req->Accept >= 0) {
#-# my $q = new CGI;
#-#
#-# # thttpd fix up by Akihiro Sagawa
#-# if ($q->server_software() =~ m|^thttpd/|) {
#-# my $path = $q->path_info();
#-# $path .= '/' if ($q->script_name=~ m|/$|);
#-# $q->path_info($path);
#-# }
#-#
#-# handler($q);
#-# }
#--END FCGI--

1;


Few Tips

Make sure you install rrdtool before using it 🙂

apt-get -y install rrdtool

To execute MRTG with command manually

env LANG=C mrtg /etc/mrtg.cfg

To assign apache www-data users full rights to /var/www/mrtg folder

chown -R www-data /var/www/mrtg/

SNMPWALK sample command to query any OID from snmp enabled target machine

snmpwalk -v1 -c gt 10.0.0.1  .1.3.6.1.2.1.25.2.3.1.6.65536

CFGMAKER command to create interface commands (this will support acquiring data larget then 120 M limit) as explained here. ( https://aacable.wordpress.com/tag/mrtg-120m-limit/ )

cfgmaker public@10.0.0.1:::::2 > temp.cfg

MRTG crontab sample (1 minute interval when using RRD)

*/1 * * * * env LANG=C mrtg /etc/mrtg.cfg –logging /var/log/mrtg.log

Enable CGI

sudo a2enmod cgi

Can’t locate RRDs.pm in @INC

SOLUTION:

sudo apt-get install librrds-perl


Some Sample Outputs !

WAN Usage: [Below …]

1-wan

Noc Room Temperature

1- noc room temp.PNG

Disk Space Used in Percent %

2- disk space of mail.PNG

Active PPP Users on CCR_1036

2-active-pppoe

CPU Usage of CCR_1036

3-mt-cpu-load

PING to Google DNS via CCR_1036

4-ping

Memory Usage of CCR_1036

5-memory

RB Temperature of CCR_1036

6-ccr-1036-rb-board-temperature

RB Voltage history of CCR_1036

7-rb-ccr-1036-voltage

SERVER UPTIME

3- server uptime.PNG

Memory Usage of Linux System

8-radius-memory


Regard’s
~ Syed Jahanza!B ~

Kannel SMS gateway with multiple smsc/modems & CMS Err 330

Filed under: Linux Related — Tags: , , , — Syed Jahanzaib / Pinochio~:) @ 10:33 AM

kannellogo

 

Following are reference guide on how you can run Kannel with multiple modems / smsc.
For basic / initial level of KANNEL configuration, please refer to the internet or my previous post at …

https://aacable.wordpress.com/2012/11/26/howto-configure-your-local-http-gateway-using-kannel-on-ubuntu/


Scenario:

Kannel is working as an SMS gateway to send/receive SMS. There is one Serial Modem connected with it using ttyS0 port. Another USB GSM Modem have been added recently which is installed as ttyUSB2.

Now we want to send SMS some specific announcement base messages via Modem#1 and some complaint system messages via Modem#2.


Hardware Used:

OS = Ubuntu 12.4 / Server Edition / x86 [Its support may end in 2017]

SMS Gateway App = Kannel 1.4.3

Modems:

1# Teltonika Modem Model = ModemCOM-G10 [Reliable & solid in performance, serial modems are good and easily configurable]
http://www.teltonika.lt/product/modemcom-g10/

modemcom-g10

 

2# TP-Link MA260 USB GSM Modem [Problematic, avoid using such cheap brands like tplink/dlink etc]
http://www.tp-link.com/en/products/details/cat-5090_MA260.html

 

ma260-01


KANNEL.CONF  Sample


# KANNEL config sample for multiple modem / SMSC
# Syed Jahanzaib

# MODEM 1 / Teltonika Brand / Type : Serial
group = smsc
smsc = at
smsc-id = zaibgsmid1
modemtype = teltonika
device = /dev/ttyS0
transceiver-mode = true
speed = 115200
# MODEM 2 / TP-LINK MA260 Brand / Type : USB
group = smsc
smsc = at
smsc-id = zaibgsmid2
modemtype = teltonika
device = /dev/ttyUSB2
transceiver-mode = true
speed = 115200
# for other models/modems adjust the INIT strings accordingly
group = modems
id = teltonika
name = "Teltonika E12"
detect-string = "Undefined"
enable-mms = true
#init-string = "AT+CNMI=2,2,0,1,1"
init-string = "ATQ0 V1 E1 S0=0 &C1 &D2 +FCLASS=0;+CNMI=1,3,2,2,1;+CMEE=1;+CPMS="SM","SM","SM";+CMGF=0"
speed = 115200
message-storage = "SM"

Make sure to restart the Kannel service and watch the bearerbox.log available at /var/log/kannel for any errors.


Howto send SMS via specific SMSC / MODEM

Now to send SMS using HTTP API method , via modem # 1 or 2, we will use its smsc ID as shown in example below … focus on smsc= part

MODEM#1

http://KANNEL-IP:13013/cgi-bin/sendsms?smsc=zaibgsmid1&username=KANNELID&password=KANNEL-PASSWORD&to=MOBILENO&text=TEST+MSG+FROM+MODEM+1

MODEM#2

http://KANNEL-IP:13013/cgi-bin/sendsms?smsc=zaibgsmid2&username=KANNELID&password=KANNEL-PASSWORD&to=MOBILENO&text=TEST+MSG+FROM+MODEM+2

 


CMS ERROR 330

I was getting cms error 330 in bearerbox.log when sending SMS with specific model of TP-LINK MA260 ,
As shown below …

cms-error

2016-12-01 08:24:05 [13727] [6] DEBUG: AT2[zaibgsmid1]: <– +CMS ERROR: 330
2016-12-01 08:24:05 [13727] [6] ERROR: AT2[zaibgsmid1]: CMS ERROR: +CMS ERROR: 330
2016-12-01 08:24:05 [13727] [6] ERROR: AT2[zaibgsmid1]: CMS ERROR: SMSC address unknown (330)

With some troubleshooting using minicom, I found out that the message center service number was not set, Strange, it should get the value auto (which is normal with other modems) , any way I sort this issue as following

(For ZONG SIM)

AT+CSCA=”+923040000011″

# now Query CSCA number

AT+CSCA?

and you should get the center number fine.

Now send sms using minicom AT commands

# Sets text mode
AT+CMGF=1  
# Now input the msg we want to send to recipient
AT+CMGS=”03333021909″
# Press Enter, and type your desired msg
TEST MSG FROM ZAIB
# Press CTRL+Z and it will send the SMS to the specified number

Some other useful minicom / AT commands with minicom

# To configure Modem ports/etc
minicom -s

General Check
AT

Getting IMEI
AT+CGSN
AT+CIMI

Getting Signal quality and battery charge status
AT+CSQ
AT+CBC

Model Inquiry
AT+CGMI

MINICOM USSD
T+CUSD=1,”your_service_code”,15

so for your case

AT+CUSD=1,”*555*87*1234#
and don’t forget the 15 at the end , this question helped me to solve the problem.

5 Modem At Command Examples in Linux (How to Configure Minicom)


Regard’s
Syed Jahanzaib

« Newer PostsOlder Posts »

Create a free website or blog at WordPress.com.

%d bloggers like this: