Script fails to create file

I want to save the number of connected users for each of my wireless interfaces using a script. However, it would seem I messed something up, because it’s not working.

Here is my code, I did some testing and it seems the code gets stuck in an infinite loop inside the “foreach”, on the “else” branch. For some reason, the file just doesn’t get created.


:global ifLastSaved

:local time [:pick [/system/clock/get time] 0 5]
:local day [:pick [/system/clock/get date] 4 6]
:local interfaces "12.1_5g,12.1_ch1,12.2_ch1,12.3_ch6,12.4_ch11,12.5_ch11"
:local ifArr [:toarray $interfaces]

#initialize save time
:if ([:len $ifLastSaved]=0) do={ :set $ifLastSaved [:pick $time 0 2]};

:foreach if in=$ifArr do={

	:local data ($time." ".[:len [/caps-man registration-table find interface=$if]])
	
	:local filename ("resziget/" . $if . "/" . $if . "-" . [:pick [/system/clock/get date] 4 6])
	
	#we have to create a new file every few hours because of the 4096 character limit
	:if ([:pick $time 0 2] > $ifLastSaved +2) do={
		:set $ifLastSaved [:pick $time 0 2]		
		:set $filename ($filename . "-" . [:pick $time 0 2])
		/file print file=$filename
		:while ([:len [/file/find name=$filename]] = 0) do={ :delay 100ms }
		/file set $filename contents=""
	} else={
		:set $filename ($filename . "-" . $ifLastSaved)
		:if ([:len [/file/find name=$filename]] = 0) do={
			/file print file=$filename
			:while ([:len [/file/find name=$filename]] = 0) do={ :delay 100ms }
		}
	}

	#this part returns "no such item"
	/file set $filename contents=([get $filename contents] . $data)

};

If anyone could point out why this happens and how can I fix it, I would be really thankful. I’ve spent the last few hours testing and tweaking the code and I just can’t seem to make any progress.

Edit: I want to run a scheduler with this script. This script would iterate over my CAPs interfaces and extract the number of connected clients from each one. Then it would put the information in a file. We’d add new info at the end of the file for a while (3 hours currently), then we’d create a new file because of the 4096 character limit I heard about. For some reason, the file creation fails. The while-delay loops are supposed to prevent attempting to set a file before it is created. I tried without them, but that also doesn’t seem to work.

Better you describe what you want, instead to ask where is the error…

You are right, sorry. I edited the original post to include the intended functionality.

First step must be create a routine for everything, not only the cap, that create a file,
and backup the contents automatically before adding the new log line go over the max (that is 4095, not 4096).
On reboot is resumed last file.
If the device have Flash, not NAND, the file is created accordingly.

{
:local filename "caphistory"
:local fileext  ".txt" ; # can be only .txt !!!

:global arrMonths {jan="01";feb="02";mar="03";apr="04";may="05";jun="06";jul="07";aug="08";sep="09";oct="10";nov="11";dec="12"}

/system clock
:local ndate  [get date]
:local ntime  [get time]
:local fdname "$[:pick $ndate 7 11]$($arrMonths->[:pick $ndate 0 3])$[:pick $ndate 4 6]$[:pick $ntime 0 2]$[:pick $ntime 3 5]"
:local isonow "$[:pick $ndate 7 11]-$($arrMonths->[:pick $ndate 0 3])-$[:pick $ndate 4 6] $ntime"
:local maxlen 4095

/file
:if ([:len [find where name="flash" and type="disk"]] = 1) do={:set filename "flash/$filename"}
:local wkfilename "$filename$fileext"
:if ([:len [find where name=$wkfilename]] = 0) do={print file="$wkfilename"; :delay 2s; set $wkfilename contents=""; :delay 1s}
:local bkfilename "$filename-$fdname$fileext"

:local filecon [get $wkfilename contents]
:local filelen [:len $filecon]

:local addthis "$isonow: ***test***\r\n"

:local addlen  [:len $addthis]

:if (($filelen + $addlen) > $maxlen) do={
    print file=$bkfilename
    :delay 2s
    set $bkfilename contents=$filecon
    :set filecon ""
    :set filelen 0
}

:set filecon  "$filecon$addthis"
set $wkfilename contents=$filecon
:delay 1s
}

2nd step is create a function

:global arrMonths {jan="01";feb="02";mar="03";apr="04";may="05";jun="06";jul="07";aug="08";sep="09";oct="10";nov="11";dec="12"}
:global addLogToFile do={
:local filename "$1"
:local fileext  ".txt"
/system clock
:local ndate  [get date]
:local ntime  [get time]
:local fdname "$[:pick $ndate 7 11]$($arrMonths->[:pick $ndate 0 3])$[:pick $ndate 4 6]$[:pick $ntime 0 2]$[:pick $ntime 3 5]"
:local isonow "$[:pick $ndate 7 11]-$($arrMonths->[:pick $ndate 0 3])-$[:pick $ndate 4 6] $ntime"
:local maxlen 4095
/file
:if ([:len [find where name="flash" and type="disk"]] = 1) do={:set filename "flash/$filename"}
:local wkfilename "$filename$fileext"
:if ([:len [find where name=$wkfilename]] = 0) do={print file="$wkfilename"; :delay 2s; set $wkfilename contents=""; :delay 1s}
:local bkfilename "$filename-$fdname$fileext"
:local filecon [get $wkfilename contents]
:local filelen [:len $filecon]
:local addthis "$isonow: $2\r\n"
:local addlen  [:len $addthis]
:if (($filelen + $addlen) > $maxlen) do={
    print file=$bkfilename
    :delay 2s
    set $bkfilename contents=$filecon
    :set filecon ""
    :set filelen 0
}
:set filecon  "$filecon$addthis"
set $wkfilename contents=$filecon
:delay 1s
}

Do not work on SMIPS. (for work on SMIPS, manually create the directory structure and commend the smb lines)

3rd step visualizing what is wanted inside the file, and create directory tree:

{
:local interfaces "12.1_5g,12.1_ch1,12.2_ch1,12.3_ch6,12.4_ch11,12.5_ch11"
:local parentdir  "resziget" 

/file
:if ([:len [find where name="flash" and type="disk"]] = 1) do={:set parentdir "flash/$parentdir"}

/ip smb shares remove [find where name="temp"]
/ip smb shares add name="temp" directory=$parentdir

:foreach item in=[:toarray $interfaces] do={
    /ip smb shares remove [find where name="temp"]
    /ip smb shares add name=temp directory="$parentdir/$item"
    :local fname "$parentdir/$item/$item"
    :local logtx [:len [/caps-man registration-table find where interface=$item]]
    :put "file name: \"$fname.txt\" - add this content: \"<DATE> <TIME>: $logtx\""
}

/ip smb shares remove [find where name="temp"]
}

Do not work on SMIPS. (for work on SMIPS, manually create the directory structure and commend the smb lines)

last step, join data & functions and test:

:global arrMonths {jan="01";feb="02";mar="03";apr="04";may="05";jun="06";jul="07";aug="08";sep="09";oct="10";nov="11";dec="12"}
:global addLogToFile do={
:local filename "$1"
:local fileext  ".txt"
/system clock
:local ndate  [get date]
:local ntime  [get time]
:local fdname "$[:pick $ndate 7 11]$($arrMonths->[:pick $ndate 0 3])$[:pick $ndate 4 6]$[:pick $ntime 0 2]$[:pick $ntime 3 5]"
:local isonow "$[:pick $ndate 7 11]-$($arrMonths->[:pick $ndate 0 3])-$[:pick $ndate 4 6] $ntime"
:local maxlen 4095
/file
:if ([:len [find where name="flash" and type="disk"]] = 1) do={:set filename "flash/$filename"}
:local wkfilename "$filename$fileext"
:if ([:len [find where name=$wkfilename]] = 0) do={print file="$wkfilename"; :delay 2s; set $wkfilename contents=""; :delay 1s}
:local bkfilename "$filename-$fdname$fileext"
:local filecon [get $wkfilename contents]
:local filelen [:len $filecon]
:local addthis "$isonow: $2\r\n"
:local addlen  [:len $addthis]
:if (($filelen + $addlen) > $maxlen) do={
    print file=$bkfilename
    :delay 2s
    set $bkfilename contents=$filecon
    :set filecon ""
    :set filelen 0
}
:set filecon  "$filecon$addthis"
set $wkfilename contents=$filecon
:delay 1s
}

{
:local interfaces "12.1_5g,12.1_ch1,12.2_ch1,12.3_ch6,12.4_ch11,12.5_ch11"
:local parentdir  "resziget" 

/file
:if ([:len [find where name="flash" and type="disk"]] = 1) do={:set parentdir "flash/$parentdir"}

/ip smb shares remove [find where name="temp"]
/ip smb shares add name="temp" directory=$parentdir

:foreach item in=[:toarray $interfaces] do={
    /ip smb shares remove [find where name="temp"]
    /ip smb shares add name=temp directory="$parentdir/$item"
    :local fname "$parentdir/$item/$item"
    :local logtx [:len [/caps-man registration-table find where interface=$item]]
#    :put "file name: \"$fname.txt\" - add this content: \"<DATE> <TIME>: $logtx\""
    [$addLogToFile $fname $logtx]
}

/ip smb shares remove [find where name="temp"]
}