Keywords in logs to activate script

Is it possible to activate a script if certain keywords are mentioned in logs, for example “wrong peer state” or “master flag=false”.

Something like this should be easily modified to do what you’re asking: http://forum.mikrotik.com/t/is-it-possible-to-run-a-script-on-login/55422/1

You’ll have to schedule it to run as often as you want to check for new log items.

Thank you, I will edit and try, I was attempting to give Karma for the helpful post but cannot which is a pity as anyone who helps should be.

Tried the script but even after editing my email credentials, it did not send a email using the keywords included “login failure” and there several login failures listed in the logs, using both Ver5.20+ 6.2?

# Script to check for specific new logs and send email alerts
# Tested on RouterOS v5.7+

# container to keep track of the last time stamp detected
:global lastTime;

# find log entries where the message contains "logged in" or "login failure"
:local currentBuf [ :toarray [ /log find message~"logged in" || message~"login failure" ] ] ;
# get number of log entries
:local currentLineCount [ :len $currentBuf ] ;

# if any logs were found, proceed
if ($currentLineCount > 0) do={
# based on number of entries, get time of last entry
   :local currentTime "$[ /log get [ :pick $currentBuf ($currentLineCount -1) ] time ]";

# check currentTime length, if length is 15, log is from a previous day and begins with month/day
   :if ([:len $currentTime] = 15 ) do={
# trim currentTime so we are left only with time xx:xx:xx
      :set currentTime [ :pick $currentTime 7 15 ];
   }
   
# the output for the body of the email, includes time stamp and log message
   :local output "$currentTime $[/log get [ :pick $currentBuf ($currentLineCount-1) ] message ]";
   
# email function
   :local sndEmail [:parse "/tool e-mail send to=email@domain.com subject=\"MikroTik alert $currentTime\" body=\"$output\" tls=yes"];

# beep function
   :local doBeep [:parse ":beep;:delay 150ms;:beep;"];


# if the last time stamp has not been set, length will be 0 (after reboot, etc)
   :if ([:len $lastTime] < 1 ) do={
# update lastTime to match currentTime
      :set lastTime $currentTime ;
# send email and beep
      $sndEmail;
      $doBeep;
# if lastTime has been set, continue
   } else={
# if lastTime does not match time stamp of the latest
      :if ( $lastTime != $currentTime ) do={
# update lastTime to match currentTime
         :set lastTime $currentTime ;
# send email and beep
         $sndEmail;
         $doBeep;
      }
   }
}

Run script at login.png

Do you need the email functionality? If you only want to run a script when keywords are found, the email function can be replaced with whatever script you want to run. If you want the email to work, make sure you have configured “/tool e-mail” settings…

I did some testing of the script on v6.2 and for whatever reason, the [:parse] functions were not working, so I removed them in the revised example below. Change this line to run your own script, or just replace it with whatever code you want:
/system script run myScript:global lastTime;

:local currentBuf [ :toarray [ /log find message~“wrong peer state” || message~“master flag=false” ] ] ;
:local currentLineCount [ :len $currentBuf ] ;

if ($currentLineCount > 0) do={
:local currentTime “$[ /log get [ :pick $currentBuf ($currentLineCount -1) ] time ]”;

:if ([:len $currentTime] = 15 ) do={
:set currentTime [ :pick $currentTime 7 15 ];
}

:local output “$currentTime $[/log get [ :pick $currentBuf ($currentLineCount-1) ] message ]”;

:if (([:len $lastTime] < 1) || (([:len $lastTime] > 0) && ($lastTime != $currentTime))) do={
:set lastTime $currentTime ;
/system script run myScript
}
}

@skot Thank you for assisting

First I setup the email script which works correctly and sends log.0.txt from files

tool e-mail send server=xxx.xxx.xxx.xxx port=25 from=name@XXX.com file=log.0.txt to=name@xxx.com subject=( "RouterError", [/system identity get name],[/system clock get time],[ /system clock get date]) body="RouterError"

Saved this script as “RouterError”

I tried the revised code but it not picking up the keywords for example, from log.0.txt it has enteries like
Oct/05/2013 14:10:39 route,ospf,info new master flag=false
Sep/24/2013 03:22:57 system,error,critical login failure for user XXXXXX
and tried keyword “failure” as well



:global lastTime;
 
:local currentBuf [ :toarray [ /log find message~"new master flag=false" || message~"Failure" ] ] ;
:local currentLineCount [ :len $currentBuf ] ;
 
if ($currentLineCount > 0) do={
   :local currentTime "$[ /log get [ :pick $currentBuf ($currentLineCount -1) ] time ]";
 
   :if ([:len $currentTime] = 15 ) do={
      :set currentTime [ :pick $currentTime 7 15 ];
   }
    
   :local output "$currentTime $[/log get [ :pick $currentBuf ($currentLineCount-1) ] message ]";
    
   :if (([:len $lastTime] < 1) || (([:len $lastTime] > 0) && ($lastTime != $currentTime))) do={
      :set lastTime $currentTime ;
      /system script run RouterError
   }
}
  1. Check the System > Scripts > Environment tab. Does the lastTime variable show up? If so, remove it, and run the script again. Each time to run the script, if it finds a matching log with a different time stamp, this variable will change. If there are no “new” matching logs, then this will stay the same and no emails will be sent, so by removing it, it resets the process. For testing, you’ll need to 1) remove this before each time you run the script or 2) generate a new matching log entry.
    env.png

  2. Another option is to replace the " /system script run RouterError" line with something like “/log info blah” for testing.

  3. You can also put your email code directly into the script. The example below also searches for Failure and failure, and it emails the $output variable (the actual log message) as the email body (if you want that).
    :global lastTime;

:local currentBuf [ :toarray [ /log find message~“new master flag=false” || message~“[Ff]ailure” ] ] ;
:local currentLineCount [ :len $currentBuf ] ;

if ($currentLineCount > 0) do={
:local currentTime “$[ /log get [ :pick $currentBuf ($currentLineCount -1) ] time ]”;

:if ([:len $currentTime] = 15 ) do={
:set currentTime [ :pick $currentTime 7 15 ];
}

:local output “$currentTime $[/log get [ :pick $currentBuf ($currentLineCount-1) ] message ]”;

:if (([:len $lastTime] < 1) || (([:len $lastTime] > 0) && ($lastTime != $currentTime))) do={
:set lastTime $currentTime ;
tool e-mail send server=xxx.xxx.xxx.xxx port=25 from=fromEmailAddress file=log.0.txt to=toEmailAddress subject=( “RouterError”, [/system identity get name],[/system clock get time],[ /system clock get date]) body=“$output”
}
}HTH

I really wish i could give Karma for all your help?

The script works OK now - Many thanks for your efforts on this,

Originally I thought if i had a script to detect keywords in the log to
(1) email
(2) reboot

But I am concerned the router on reboot could find the keywords again and go into reboot cycle even I had added delay after reboot?

I have set my logging of 1000 lines to disk and not memory,

  1. Check the System > Scripts > Environment tab. Does the lastTime variable show up? If so, remove it, and run the script again. Each time to run the script, if it finds a matching log with a different time stamp, this variable will change. If there are no “new” matching logs, then this will stay the same and no emails will be sent, so by removing it, it resets the process. For testing, you’ll need to 1) remove this before each time you run the script or 2) generate a new matching log entry.

Am I correct that if I have a reboot action on this script it not go into reboot loop if there is no new keywords are detected since time stamp of script > Environment tab

From email sent, it tells me time of keyword and with attached log file to examine for other issues,

14:21:56 new master flag=false,PTP_F30,21:07:44,oct/08/2013

The global variable is stored in memory, so a reboot will clear it. So, I think it will go into a reboot loop.

This could be fixed by saving the time stamp in the comment of some permanent item (a user account comment, interface comment, wherever). Then the time stamp would survive a reboot. Example below, edited on line 1 and line 16.
:local lastTime [/user get [find name=“userName”] comment];

:local currentBuf [ :toarray [ /log find message~“new master flag=false” || message~“[Ff]ailure” ] ] ;
:local currentLineCount [ :len $currentBuf ] ;

if ($currentLineCount > 0) do={
:local currentTime “$[ /log get [ :pick $currentBuf ($currentLineCount -1) ] time ]”;

:if ([:len $currentTime] = 15 ) do={
:set currentTime [ :pick $currentTime 7 15 ];
}

:local output “$currentTime $[/log get [ :pick $currentBuf ($currentLineCount-1) ] message ]”;

:if (([:len $lastTime] < 1) || (([:len $lastTime] > 0) && ($lastTime != $currentTime))) do={
/user set [find name=“userName”] comment=$currentTime
tool e-mail send server=xxx.xxx.xxx.xxx port=25 from=fromEmailAddress file=log.0.txt to=toEmailAddress subject=( “RouterError”, [/system identity get name],[/system clock get time],[ /system clock get date]) body=“$output”
}
}

The script appears to working OK and i added a second email address should primary not send, and thank you skot once again
If using user=admin ensure there is no comment already there like “Default User”, clear this comment and leave blank.

To increase the possiblity of important log file keywords being received i used two email accounts.

I had planned to also add reboot router to script when keywords were listed in the logs but I now discover that while the script works,

But on a router which has several issue like no PPPoE profile local-address or DNS errors “No route to host” or OSPF "OSPFv2 neighbor 10.111.XX.XX: state change from full to 2-way
This occurs on APs which have used version V5.20 , V5.25, V6.1,

A simple reboot normally solves this but I am more concerned why this occuring in the first place - Time for a different post?
But the good news this time is that I currently have a test AP with these issues and have not rebooted,
So far as i have only mac-telnet access, i ran /system sup-output which has created supout.rif file,
What other tests can be done before i reboot to help MT support to fix this issue(s)?

:global lastTime [/user get [find name="admin"] comment];
  
:local currentBuf [ :toarray [ /log find message~"new master flag=false" || message~"wrong peer state" || message~"login failure" ] ] ;
:local currentLineCount [ :len $currentBuf ] ;
  
if ($currentLineCount > 0) do={
   :local currentTime "$[ /log get [ :pick $currentBuf ($currentLineCount -1) ] time ]";
  
   :if ([:len $currentTime] = 15 ) do={
      :set currentTime [ :pick $currentTime 7 15 ];
   }
    
   :local output "$currentTime $[/log get [ :pick $currentBuf ($currentLineCount-1) ] message ]";
    
   :if (([:len $lastTime] < 1) || (([:len $lastTime] > 0) && ($lastTime != $currentTime))) do={
      /user set [find name="admin"] comment=$currentTime;
     / tool e-mail send server=xxx.xxx.xxx.xxx port=25 from=fromEmailAddress.com file=log.0.txt to=toEmailAddress.com subject=( "RouterError_EmailA", [/system identity get name],[/system clock get time],[ /system clock get date]) body="$output";
;delay 5s
 /tool e-mail send server=xxx.xxx.xxx.xxx  port=25 from=fromEmailAddress.net file=log.0.txt to=toEmailAddress.com subject=( "RouterError_EmailB", [/system identity get name],[/system clock get time],[ /system clock get date]) body="$output";
   }
}"

I’m not quite understanding the new problem. Is it related to the script? Or something else? It might be good to start a new post…