Netwatch - log to file

I’ve had problem with my local provider a year back and I had to proove that their service is malfunctioning. At first it seemed random but to verify it i used this netwatch script to log each DOWN and UP event to a file.

Since the logging date format (jul/16/2014) did not meet my requirements i made my own script to log just these events. The only problem is that AFAIK we can’t append data to a file via scripting, so i had to read a log file content then add a line to the local variable storing it’s content and write the new content back to a file. It’s obviously not a good solution but the best i could come up with using built in routeros functionality.

Since file operations on RouterOS take long time (you need to :delay 1 each time you want to use a file you’ve created) you need to configure netwatch interval to 2s (not less) or the down-script may not finish before the next up-script starts.

up-script:local workdir “log/google/”
:local name “GoogleDNS”

:local scl [/system clock get];
:local months {jan=01;feb=02;mar=03;apr=04;may=05;jun=06;jul=07;aug=08;sep=09;oct=10;nov=11;dec=12};
:set ($scl->“y”) [:pick ($scl->“date”) 7 11]
:set ($scl->“mn”) [:pick ($scl->“date”) 0 3]
:set ($scl->“m”) ($months->($scl->“mn”)); :if (($scl->“m”) < 10) do={:set ($scl->“m”) (“0”.($scl->“m”))};
:set ($scl->“d”) [:pick ($scl->“date”) 4 6]
:set ($scl->“H”) [:pick ($scl->“time”) 0 2]
:set ($scl->“M”) [:pick ($scl->“time”) 3 5]
:set ($scl->“S”) [:pick ($scl->“time”) 6 8]
:set ($scl->“timestamp”) (($scl->“y”).“.”.($scl->“m”).“.”.($scl->“d”).“_”.($scl->“H”).“.”.($scl->“M”).“.”.($scl->“S”))

:local tempfile ($workdir.“_”.$name.“.txt”)
:local output (" - UP “.($scl->“timestamp”).”\r\n");

:local newcontent ([file get “$tempfile” contents].$output); :delay 1;
/file set [/file find name=“$tempfile”] contents=$newcontent;down-script:local workdir “log/google/”
:local name “GoogleDNS”

:local scl [/system clock get];
:local months {jan=01;feb=02;mar=03;apr=04;may=05;jun=06;jul=07;aug=08;sep=09;oct=10;nov=11;dec=12};
:set ($scl->“y”) [:pick ($scl->“date”) 7 11]
:set ($scl->“mn”) [:pick ($scl->“date”) 0 3]
:set ($scl->“m”) ($months->($scl->“mn”)); :if (($scl->“m”) < 10) do={:set ($scl->“m”) (“0”.($scl->“m”))};
:set ($scl->“d”) [:pick ($scl->“date”) 4 6]
:set ($scl->“H”) [:pick ($scl->“time”) 0 2]
:set ($scl->“M”) [:pick ($scl->“time”) 3 5]
:set ($scl->“S”) [:pick ($scl->“time”) 6 8]
:set ($scl->“timestamp”) (($scl->“y”).“.”.($scl->“m”).“.”.($scl->“d”).“_”.($scl->“H”).“.”.($scl->“M”).“.”.($scl->“S”))

:local tempfile ($workdir.““.$name.”.txt")
:local logfile ($workdir.$name."
”.($scl->“timestamp”).“.txt”)
:local output ($name." - DOWN ".($scl->“timestamp”));

:if ([:len [/file find where size > “3072” name~$tempfile;]] > 0) do={
:local tempcontent ([file get “$tempfile” contents]);
/file print file=“$logfile”; :delay 1;/file set [/file find name=“$logfile”] contents=$tempcontent;
/file set [/file find name=“$tempfile”] contents=“”;
}

:if ([:len [/file find where name~$tempfile;]] > 0) do={} else={
/file print file=“$tempfile”; :delay 1; /file set “$tempfile” contents=“”;
}

:local newcontent ([file get “$tempfile” contents].$output);
/file set [/file find name=“$tempfile”] contents=$newcontent;P.S.
I hope the above script example prooves that RouterOS’ file management and date format might need some patching/feature upgrade in the future. Also adding a custom topic for each script to log it’s own data would be a nice addition.

Remember: aftere 4096 byte all stop working…

Also if you provide yourself the proof of ISP malfunctioning, is not considered valid, you must use third party assistance for make count any test.

[...]
:local months {jan=01;feb=02;mar=03;apr=04;may=05;jun=06;jul=07;aug=08;sep=09;oct=10;nov=11;dec=12};
[...]
:set ($scl->"m") ($months->($scl->"mn")); :if (($scl->"m") < 10) do={:set ($scl->"m") ("0".($scl->"m"))};
[...]

must be:

[...]
:local months {jan="01";feb="02";mar="03";apr="04";may="05";jun="06";jul="07";aug="08";sep="09";oct="10";nov="11";dec="12"};
[...]
:set ($scl->"m") ($months->($scl->"mn"));
[...]

I could’ve swear jan=“01” was not working properly on one old ROS version, but it works now, thanks for that fix.

BTW.
Can I somehow use the below script to :put only the comment which is from .id=*2?
:local test [/ip address print as-value]; :put $test; :put ($test->“comment”)Output:

id=*1;address=10.0.1.1/24;comment="One";interface=ether1;network=10.0.1.0;.id=*2;address=192.168.0.2/30;comment="Two";interface=ether2;network=192.168.0.0;

value=“print as-value” ???

:put [/ip address get ([/ip address find] -> 1) value-name=comment];

The idea was to have an array with all address information and then point to values in that array. I just wonder if this is possible to use arrays in this way.

Ok, now you have described what you want do.

:global savedarray value=[/ip address print as-value];

:put (($savedarray->1)->"comment");

Thanks.

create logging action:

/system logging action add disk-file-count=100 disk-file-name=netwatch, name=netwatch target=disk

and log this target to file

/system logging add action=netwatch topics=script,info

you can log from script (netwatch) like this:

:log info "testing"

Yes, but my other scripts use script,info for their output. I don’t want to mix them around.