# Monitoring Script - MikroTik Script RouterOS

    Actually there are two scripts. The first one is the main script for monitoring arbitrary RouterOS parameters. It uses the second auxiliary script for logging.

    Add both scripts to your RouterOS. Make sure they are named as "monitoring" and "log-up-down". Add the monitoring script to the system scheduler:

    /system scheduler add name=monitoring on-event=monitoring interval=5s start-date=jan/01/1970 start-time=00:00:00
    Check the log messages. You will see the following lines:

    17:17:05 script,info Monitoring started
    17:17:05 script,info ISP1 is down (uptime=00:00:00)
    17:17:05 script,info ISP2 is down (uptime=00:00:00)
    17:17:05 script,info Internet is up (downtime=00:00:00)
    Edit the monitoring script to adjust it for your own RouterOS configuration. By default the script monitors the state of three routes and makes log entries when the state is changed, assuming that a failover between two ISP connections is configured. But you can monitor arbitrary parameters and do other actions than just logging.

    If you want to receive monitoring notifications by e-mail, just set up RouterOS system logging for that.

    ############################################################################
    # Script name:   monitoring
    # Last changed:  25 Feb 2011
    # ROS version:   5.0rc10
    # Author:        Vadim Guchenko [yhw at relost dot net]
    #
    # Monitors one or more parameters of RouterOS and performs specified actions
    # when parameters change their values. A parameter is any expression of the
    # RouterOS scripting language that can return a value of any data type to
    # which the = operator can be applied. When the parameter value is changed,
    # the specified action is executed. An action is any statement of the
    # RouterOS scripting language that doesn't return a value (usually it's
    # invocation of another script). Before executing an action the following
    # global variables are set:
    #
    #   monParamName         The name of the parameter that has been changed.
    #                        Can be used to distinguish different parameters in
    #                        one action script.
    #   monParamOldValue     The old parameter value.
    #   monParamNewValue     The new parameter value.
    #   monParamOldValueAge  How long (seconds) the parameter had the old value.
    #                        Calculated without using the system clock.
    #
    # This script must be run from the scheduler at small intervals. If a
    # parameter value is changed to a new one and then changed to the old value
    # again between two script invocations, these changes will not be detected
    # by the script and no action will be executed.
    #
    # When the script is run for the first time after RouterOS is booted up, it
    # considers that every parameter has the old value of type nil (nothing).
    # As far as parameter values normally have a type other than nil, the script
    # will consider that all parameter values are just changed and therefore it
    # will immediately execute actions for all the parameters.
    #
    ############################################################################
    # Make your changes here:
    ############################################################################
    #
    # The interval, in seconds, at which this script is run from the scheduler.
    :local runInterval 5
    #
    # Don't change the following statement. It checks if another copy of this
    # script is already running.
    :if ([:len [/system script job find script=monitoring]] > 1) do={
            :global monTimeCounter
            :set monTimeCounter ($monTimeCounter + $runInterval)
            :log warning "Another copy of monitoring script is running"
            :error
    }
    #
    # The names of the parameters. Every array element corresponds to an
    # individual parameter. Dimensions of the arrays "paramNames", "paramValues"
    # and "paramActions" must be the same.
    :local paramNames {
            "ISP1"
            "ISP2"
            "Internet"
    }
    #
    # The expressions to compute parameter values. Note that the expressions
    # must NOT be enclosed in double quotes.
    :local paramValues {
            ([/ip route find dst-address=127.127.127.1/32 active] != "")
            ([/ip route find dst-address=127.127.127.2/32 active] != "")
            ([/ip route find dst-address=0.0.0.0/0 active] != "")
    }
    #
    # The actions to be executed when parameter values are changed. Note that
    # all actions must be enclosed in double quotes.
    :local paramActions {
            "/system script run log-up-down"
            "/system script run log-up-down"
            "/system script run log-up-down"
    }
    #
    # The action to be executed when the script is run for the first time after
    # RouterOS is booted up.
    :local initAction ":log info \"Monitoring started\""
    #
    ############################################################################
    # Don't change anything below this line.
    ############################################################################
    :global monTimeCounter
    :global monParamValues
    :global monParamValuesChangedAt
    :local newParamValues
    :local newParamValuesChangedAt
    :if ($monTimeCounter > 0) do={
    } else={
            :set monTimeCounter 0
            :local action [:parse $initAction]
            $action
    }
    :for i from=0 to=([:len $paramNames] - 1) do={
            :if ([:pick $paramValues $i] = [:pick $monParamValues $i]) do={
                    :set newParamValues ($newParamValues, [:pick $monParamValues $i])
                    :set newParamValuesChangedAt ($newParamValuesChangedAt, [:pick $monParamValuesChangedAt $i])
            } else={
                    :set newParamValues ($newParamValues, [:pick $paramValues $i])
                    :set newParamValuesChangedAt ($newParamValuesChangedAt, $monTimeCounter)
                    :global monParamName [:pick $paramNames $i]
                    :global monParamOldValue [:pick $monParamValues $i]
                    :global monParamNewValue [:pick $paramValues $i]
                    :global monParamOldValueAge ($monTimeCounter - [:pick $monParamValuesChangedAt $i])
                    :local action [:parse [:pick $paramActions $i]]
                    $action
            }
    }

    :set monTimeCounter ($monTimeCounter + $runInterval)
    :set monParamValues $newParamValues
    :set monParamValuesChangedAt $newParamValuesChangedAt
    ############################################################################
    # Script name:   log-up-down
    # Last changed:  25 Feb 2011
    # ROS version:   5.0rc10
    # Author:        Vadim Guchenko [yhw at relost dot net]
    #
    # Logs the new value of the parameter in terms of "up" and "down". Also logs
    # uptime/downtime. Used in conjunction with the monitoring script.
    #
    # There is nothing to configure.
    ############################################################################
    :global monParamName
    :global monParamNewValue
    :global monParamOldValueAge
    :local status
    :local time
    :if ($monParamNewValue = true) do={
            :set status "up"
            :set time "downtime"
    } else={
            :set status "down"
            :set time "uptime"
    }
    :log info "$monParamName is $status ($time=$[:totime $monParamOldValueAge])"
    Credit: wiki.mikrotik.com