Would someone please help me make this script snippet append the new data to the file (instead of overwriting it):
:local voltage (([/system ups monitor 0 once as-value]->"line-voltage")/100)
:if (([/system/ups/monitor 0 once as-value]->"line-voltage") < 11500) do={
:log info "UPS input voltage is $voltage"
:local date [ :system clock get date ]
:local time [ :system clock get time ]
/file print file=upsvoltagelow.txt
:delay 2s
:file set "upsvoltagelow.txt" contents=""
:file set "upsvoltagelow.txt" contents="$date $time $voltage"
Unfortunately, there is no way to append data. Something as basic and simple as output redirection in Linux is not available in RouterOS. You must read the old data first, then write it back, both old and new contents. Watch out for file size limits if you are working with large amount of data.
Looking at your example, it might be a lot easier just to create a logging rule to save this particular data to a separate log file. It will even take care of the timestamps for you.
You can append it pretty simply, you just read the file when you add new data:
/file set "upsvoltagelow.txt" contents="$[/file get "upsvoltagelow.txt" contents]\n$date $time $voltage"
Now your issue is at some point the file will get too big. Thus, @anserkâs suggest that to do something like /log info "UPS $date $time $voltage" is a better one.
You can just log all script output from /log info "msg" to a file using /system/logging. You can add action to use a file name script (which becomes scriptlog.txt or scriptlog.0.txt), and will have all output from scripts (so not just UPS). In V7, youâd be able to use a regex to find only the UPS ones⌠but alas I recall your still on V6.
Thatâs the basic of using logging instead. The benefit is with /log you get plenty of control over the file size, and RouterOS will roll them for you (i.e. so most recent ones are always present, with you controlling how much disk/files to save in /system/logging/action. Merely appending to an existing file, youâll eventually hit the file size limit and have to manually delete entries or save old file etc.
I added the :log line and the script fails to execute.
:local voltage (([/system ups monitor 0 once as-value]->"line-voltage")/100)
:if (([/system/ups/monitor 0 once as-value]->"line-voltage") < 11500) do={
:log info "UPS input voltage is $voltage"
:log ups "UPS input voltage is $voltage"
I tried with the topic set up as âscriptâ also.
There is no such topic like ups for :log command. There are only info, warning and error (there is also debug, but Iâm not sure about its usage, doesnât matter). Thatâs why you have an error. You canât generate a log message with ups topic by yourself from a script, only RouterOS can add such log messages. Everything, that comes out from a script will appear with script topic in the log. So, this /system logging add action=diskups topics=ups is useless for your script. You need to use regexp to filter out your log messages.
I would suggest you to use '[UPS]: â prefix for ALL log messages, that you gonna add from your script, so they will be clearly distinguishable from others.
It will look like that:
:local upsPrefix "[UPS]:"
# ...
:local voltage (([/system ups monitor 0 once as-value]->"line-voltage")/100)
:if ($voltage < 115) do={
:log info "$upsPrefix UPS input voltage is $voltage"
}
# ...
I also removed double data reading from your code, it looks useless.
So, if your script adds a message, it will appear in the log like this, for example: [date&time] script,info [UPS]: UPS input voltage is 110
To filter out these messages and put them in a separate log file, you need to add a new action with regexp:
I thought that the âINFOâ in â:log infoâ was the topic and could be any of the available topics in the dropdown. I still donât really understand how this works.
For example, I donât understand how all the many defined topics work.
I understand your elegant solution (basically), and just tried it out and it works beautifully.
I really canât believe how bad the online manual is. I think the degree of incomprehensibility is invisible to those who understand these things.
The problem with the documentation is exactly that: The correct info is there, itâs just encrypted by mixing it in among lots and lots of noise.
For all those who think Iâm just whining, consider that it would make reasonable sense to go here to get the answer, and find things that sort of, almost, could be useful info, but doesnât address the entirety of the solution:
The page you linked is the documentation for the /logmenu.
When you write scripts that use :resolve, do you expect to find the documentation for that under the help page of /ip dns? The answer is obviously âNoâ.
I do understand that, but I think you proved my point: To you it makes perfect sense to look in the scripting docs for how to use the :log command. To the masses, we would (incorrectly) think to look in the logging docs.
But the underlying problem is that if you donât know what youâre doing, thereâs no use in AIâŚ
.
Examples:
If youâve already done the monitor to get the value, why ask for it again?
:local voltage (([/system ups monitor 0 once as-value]->"line-voltage")/100)
:if (([/system/ups/monitor 0 once as-value]->"line-voltage") < 11500) do={
If itâs a matter of âaestheticsâ for the /100, just do it when saving the log.
.
Why write to the file twice?
The first time to set the content to ââ
The second time to set the content to ââŚâ
:file set "upsvoltagelow.txt" contents=""
:file set "upsvoltagelow.txt" contents="$date $time $voltage"
You can simply set the content to âââŚ" just once.
.
Missing check whether file exists.
Use / and not : when are sections and not commandsâŚ
Also âmonitor 0â is wrong, but I do not have ups to test the correct syntax,
what is the name of â0â?..
NEVER use same variable name date for what value read get date
.
Anyway, you simply need to do this for âsimpleâ file:
/file remove [find where name="upsvoltagelow.txt"]
/file add name="upsvoltagelow.txt" contents=(([/system ups monitor 0 once as-value]->"line-voltage")/100)
and the date and time can be read in the file propertiesâŚ
:local rawvolt ([/system ups monitor 0 once as-value]->"line-voltage")
:local theshold 11500
:local voltage ($rawvolt / 100)
:local cdate [/system clock get date]
:local ctime [/system clock get time]
:local filename "upsvoltagelow.txt"
# NAND flash or XOR flash ?
:if ([:len [/file find where name="flash" and type="disk"]] = 1) do={:set filename "/flash/$filename"}
:if ($rawvolt < $theshold) do={
:log info "UPS input voltage is $voltage"
:local logline "$cdate $ctime $voltage"
:local fileid [/file find where name=$filename]
:local howmany [:len $fileid]
:if ($howmany > 0) do={
# if file exist
:local previouscontent [/file get $fileid contents]
/file set $fileid contents="$previouscontent\r\n$logline"
} else={
# if file do not exist
/file add name=$filename contents=$logline
}
}
âmonitor 0â must be replaced with something like
monitor ([find]->0)
or
monitor [find where name=âupsnameâ]
but I do not have any UPS to test it.
I can see the studentâs review of this professor:
âGreat prof, really knows his stuff, eager to help, crazy high standards for his studentsâ
But seriouslyâŚ
Doesnât âmonitor 0â simply mean the first ups (i.e., the one with id = 0), and if so, what is wrong with calling it that?
The other way (â/system ups monitor SOMEUPSNAME once as-valueâ) requires the creater of the script to (1) know the name of the UPS, and (2) have to go into the script to manually change if the name of the UPS ever changes.
As far as creating all the local variables (rawvolt, threshold, voltage, cdata, ctime, filename), that is clearly neater, more comprehensible approach. I always get held up by my choice of variable names (using a â-â or other special character; or some form of reseved (or used-elsewhere) name).
Your solution to appending to a file is quite elegant, and no doubt will come in handy for many who read this thread.
I know youâre all going to this Iâm being dense, but I know that this is far from clear â I think the point of not using id numers is that they can change. But, it shouldnât be far more work to figure out what is being said than understanding the underlying concept.
Further, is there any merit to my observation that hard coding the UPS name has its own problems?
If you have only one ups and you say its name could change, then using 0 wonât be a problem.
Btw, these docs are quite strange. Why do they say, that the second script will fail? It works fine. What do they mean by â1â? They were using 0 index in the script code and then they write â1â. Is it a typo? Weird.