Community discussions

MikroTik App
 
jeroenp
Member Candidate
Member Candidate
Topic Author
Posts: 159
Joined: Mon Mar 17, 2014 11:30 am
Location: Amsterdam
Contact:

[SOLVED] Is there a good way to sync a local directory from the scripts that a Mikrotik has? (No: 4096 byte issue)

Sun May 15, 2016 9:54 pm

My current workflow involves a lot of copy-pasting to keep my local directory and the scripts on a Mikrotik device in sync.

Is there a better way for this?
If so, what?

(Either Mac OS X or Windows based is fine as I run both)

--jeroen
Last edited by jeroenp on Sat May 21, 2016 1:02 pm, edited 1 time in total.
 
User avatar
boen_robot
Forum Guru
Forum Guru
Posts: 2400
Joined: Thu Aug 31, 2006 4:43 pm
Location: europe://Bulgaria/Plovdiv

Re: Is there a good way to sync a local directory from the scripts that a Mikrotik has?

Sun May 15, 2016 10:01 pm

FTP.

Get a text editor that can sync up with FTP, and set up an FTP connection with the router that you then sync on when the editor starts, and when you save.

An example of a text editor that I know can do this would be NetBeans, though it doesn't have any sort of MikroTik specific support, so as it stands, using it is equal to using Notepad... but with FTP syncing in the middle of it. And needless to say there are other editors out there that can do that too (though I haven't personally used any).
 
jeroenp
Member Candidate
Member Candidate
Topic Author
Posts: 159
Joined: Mon Mar 17, 2014 11:30 am
Location: Amsterdam
Contact:

Re: Is there a good way to sync a local directory from the scripts that a Mikrotik has?

Sun May 15, 2016 11:39 pm

FTP.
I tried. But none of the things in `/system scripts print` show up on the FTP server.

What am I missing?
What workflow would you suggest?

--jeroen
 
jeroenp
Member Candidate
Member Candidate
Topic Author
Posts: 159
Joined: Mon Mar 17, 2014 11:30 am
Location: Amsterdam
Contact:

Re: Is there a good way to sync a local directory from the scripts that a Mikrotik has?

Sun May 15, 2016 11:41 pm

FTP.
I tried. But none of the things in `/system scripts print` show up on the FTP server.

What am I missing?
What workflow would you suggest?

My current work-flow is this:

1. in WinBox, edit the script
2. Save it
3. Run it from SSH to it creates the function and is visible in `/system script environment print`
4. Run the function to verify it works (if not, go back to 1.)
5. Copy the script from WinBox to Atom and save it locally in a file with the same name as in WinBox
6. Put the file in a repository


--jeroen
Last edited by jeroenp on Mon May 16, 2016 12:37 am, edited 1 time in total.
 
jarda
Forum Guru
Forum Guru
Posts: 7756
Joined: Mon Oct 22, 2012 4:46 pm

Sun May 15, 2016 11:42 pm

Use export command instead of print.
 
jeroenp
Member Candidate
Member Candidate
Topic Author
Posts: 159
Joined: Mon Mar 17, 2014 11:30 am
Location: Amsterdam
Contact:

Re:

Mon May 16, 2016 12:20 am

Use export command instead of print.
How would that fit in the workflow?

(I must be missing something fundamental here, just not sure what it is yet, so please elaborate).

--jeroen
 
jarda
Forum Guru
Forum Guru
Posts: 7756
Joined: Mon Oct 22, 2012 4:46 pm

Mon May 16, 2016 8:29 am

Point 5. Export to file. Then you can grab it by ftp out.
 
jeroenp
Member Candidate
Member Candidate
Topic Author
Posts: 159
Joined: Mon Mar 17, 2014 11:30 am
Location: Amsterdam
Contact:

Re:

Mon May 16, 2016 9:37 am

Point 5. Export to file. Then you can grab it by ftp out.
I tried and got all scripts in one big file in a format that is not friendly for the syntax highlighting in the various text editors (Atom, Sublime, Notepad++). I picked out one, see below.

What I'm looking for is to export each script in a individual file, preferably in a subdirectory (as that's way easier to sync over FTP: I love Beyond Compare for this) named as they are named in the WinBox script editor and in the same format as that script editor.

With those individual files, I should also be able to get them in a git repository easily.

I also want the other way around: have an updated file from the script repository, FTP it to the Mikrotik then install it.

Any ideas (especially as getting the individual script properties doesn't work, see below)?

I tried getting the script names, but it fails at the `:get`, indicating `bad command name get (line 1 column 114)`
:foreach scriptId in [/system script find] do={ :local script [/system script get $scriptId]; :local scriptName [:get $script name]; :put $scriptName }
bad command name get (line 1 column 114)
The `$script` variable holds each script with their properties, as this dumps all properties:
:foreach scriptId in [/system script find] do={ :local script [/system script get $scriptId]; :put $script }
Example of export (this is a fragment of `/system script export file=scripts.rsc`):
add name=Function.startsWithString.rsc owner=admin policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive source=":global startsWithString do={\r\
    \n  # returns true if \$value starts with \$subString\r\
    \n\r\
    \n#global varDump\r\
    \n\r\
    \n#:put \"value=\"\r\
    \n#\$varDump value=\$value\r\
    \n#:put \"subString=\"\r\
    \n#\$varDump value=\$subString\r\
    \n  \r\
    \n  :local result false\r\
    \n#:put \"result=\"\r\
    \n#\$varDump value=\$result\r\
    \n\r\
    \n  :if ([:typeof \$value] = \"str\") do={\r\
    \n    :if ([:typeof \$subString] = \"str\") do={\r\
    \n      :local valueLength [:len \$value]\r\
    \n      :local subStringLength [:len \$subString]\r\
    \n      :if (\$valueLength > \$subStringLength) do={\r\
    \n# strings start at position zero (0)!\r\
    \n# 01234\r\
    \n# ABCDE -> length 5\r\
    \n# AB -> length 2; positions 0..1\r\
    \n\r\
    \n        :local valueStart (0)\r\
    \n        # bug that won't be fixed: :pick end parameter is 1-based, not 0-based http://forum.mikrotik.com/viewtopic.php\?t=108311\r\
    \n        # :local valueEnd (\$subStringLength - 1)\r\
    \n        :local valueEnd (\$subStringLength - 0)\r\
    \n        :local valuePick [:pick \$value \$valueStart \$valueEnd] \r\
    \n#:put \"valueStart=\"\r\
    \n#\$varDump value=\$valueStart\r\
    \n#:put \"valueEnd=\"\r\
    \n#\$varDump value=\$valueEnd\r\
    \n#:put \"valuePick=\"\r\
    \n#\$varDump value=\$valuePick \r\
    \n        :set \$result (\$subString = \$valuePick)\r\
    \n      }\r\
    \n    }\r\
    \n  };\r\
    \n\r\
    \n#:put \"result=\"\r\
    \n#\$varDump value=\$result\r\
    \n  :return \$result;\r\
    \n}\r\
    \n\r\
    \n# Examples:\r\
    \n# /system script run Function.startsWithString.rsc\r\
    \n# :put [\$startsWithString value=\"ABCDE\"]\r\
    \n# false\r\
    \n# :put [\$startsWithString value=\"ABCDE\" subString=(7)]\r\
    \n# false\r\
    \n# :put [\$startsWithString value=\"ABCDE\" subString=\"DE\"]\r\
    \n# false\r\
    \n# :put [\$startsWithString value=\"ABCDE\" subString=\"AB\"]\r\
    \n# true\r\
    \n"
--jeroen
 
jarda
Forum Guru
Forum Guru
Posts: 7756
Joined: Mon Oct 22, 2012 4:46 pm

Mon May 16, 2016 12:34 pm

I have not tried to solve your task. Maybe user Sinan could help you somehow more practically. He seems to be an enthusiast to the ros scripting...
 
User avatar
boen_robot
Forum Guru
Forum Guru
Posts: 2400
Joined: Thu Aug 31, 2006 4:43 pm
Location: europe://Bulgaria/Plovdiv

Re: Is there a good way to sync a local directory from the scripts that a Mikrotik has?

Mon May 16, 2016 3:02 pm

Any file with extension ".rsc" can be ran by RouterOS using the "/import" command. And as jarda already said, you can use "/export" to generate an ".rsc" file that has everything needed to replicate a router configuration.

If you only have a few scripts, I think you're in a position right now where you can "manually" cut & paste them into ".rsc" files, and after that, at all points you need them, use '/import file="scriptname.rsc"' instead of '/system script run "scriptname"'.

If you have many, you can use something like:
:local scripts [/system script print detail as-value]

#Create pseudo files (RouterOS can't create empty ones at will)
:foreach script in=$scripts do={
    /file print file=(($script->"name") . ".rsc")
}

#Wait for the files to be created "for real"
:delay 2s

#Fill the files with the script's contents
:foreach script in=$scripts do={
    /file set (($script->"name") . ".rsc") contents=($script->"source")
}
Oh, and for why "get" fails... Remember when I said "get" returns the info as an associative array? Well, I'm stupid, so forget that... I was confusing that with "print as-value", which is my preferred method (as above), so I forgot that "get" returns an individual property that you must specify alongside the ID/name of the item you're targeting... Plus, there's no ":get" command (i.e. no "get" command at the root menu; only menu specific "get" ones).
 
jeroenp
Member Candidate
Member Candidate
Topic Author
Posts: 159
Joined: Mon Mar 17, 2014 11:30 am
Location: Amsterdam
Contact:

Re: Is there a good way to sync a local directory from the scripts that a Mikrotik has?

Tue May 17, 2016 8:36 am

Any file with extension ".rsc" can be ran by RouterOS using the "/import" command. And as jarda already said, you can use "/export" to generate an ".rsc" file that has everything needed to replicate a router configuration.

If you only have a few scripts, I think you're in a position right now where you can "manually" cut & paste them into ".rsc" files, and after that, at all points you need them, use '/import file="scriptname.rsc"' instead of '/system script run "scriptname"'.

If you have many, you can use something like:
...
That fails:
failure: new contents too long
Can you show the contents of a few files exported with your above method? As mine look odd, for instance `profile:jeroenp@192.168.71.3?Function.startsWithString.rsc.rsc.txt` looks like this:
# may/17/2016  7:26:37 by RouterOS 6.35.1
# software id = VQR4-7MRH
#
 # NAME                   TYPE                        SIZE CREATION-TIME       
 0 skins                  directory                        jan/01/1970 02:00:03
 1 MikroTik-19700102-0... backup                   16.0KiB jan/02/1970 02:48:23
 2 pub                    directory                        jan/02/1970 02:54:47
 3 crs226-export.rsc      script                       357 jan/02/1970 03:46:45
 4 console-dump.txt       .txt file                16.8KiB may/02/2016 14:53:49
 5 DHCP-DNS-work.rsc      script                    6.1KiB apr/21/2016 22:10:42
 6 WAN0-WAN2.rsc          script                    9.2KiB may/01/2016 11:16:57
 7 helden-static-WAN2-... script                    9.6KiB may/01/2016 16:39:51
 8 dhcp-server-gateway... script                   13.8KiB may/01/2016 20:48:51
 9 apc-dhcp-option-43-... script                   15.6KiB may/02/2016 15:17:02
10 dude                   dude store                       may/03/2016 12:25:48
11 udp-67-dhcp            file                     21.4KiB may/03/2016 16:27:48
12 scripts.rsc            script                   38.1KiB may/16/2016 08:35:43
13 mikrotik-dns-dhcp.s... .txt file                   1270 may/17/2016 07:26:37
14 playground.rsc.txt     .txt file                   1350 may/17/2016 07:26:37
15 Function.escapeStri... .txt file                   1430 may/17/2016 07:26:37
16 Function.stripInval... .txt file                   1510 may/17/2016 07:26:37
17 Function.padLeftStr... .txt file                   1590 may/17/2016 07:26:37
18 Function.varDump.rs... .txt file                   1670 may/17/2016 07:26:37
19 Function.padRightSt... .txt file                   1750 may/17/2016 07:26:37
20 Function.endsWithSt... .txt file                   1830 may/17/2016 07:26:37
21 Function.startsWith... .txt file                      0 may/17/2016 07:26:37
Oh, and for why "get" fails... Remember when I said "get" returns the info as an associative array? Well, I'm stupid, so forget that... I was confusing that with "print as-value", which is my preferred method (as above), so I forgot that "get" returns an individual property that you must specify alongside the ID/name of the item you're targeting... Plus, there's no ":get" command (i.e. no "get" command at the root menu; only menu specific "get" ones).
So basically you say that `get` should have been like this: `/system script get` right?

Lets try that:
:foreach scriptId in [/system script find] do={ :local scriptName [/system script get $scriptId name]; :put $scriptName }                                              
mikrotik-dns-dhcp.script
playground
Function.escapeString.rsc
Function.stripInvalidHostNameCharactersFromString.rsc
Function.padLeftString.rsc
Function.varDump.rsc
Function.padRightString.rsc
Function.endsWithString.rsc
Function.startsWithString.rsc
That works. Yay!

Some stats that might help with the `contents too long`:
:foreach scriptId in [/system script find] do={ :local scriptSource [/system script get $scriptId source]; :local scriptSourceLength [:len $scriptSource];  :local scriptName [/system script get $scriptId name]; :put "$scriptSourceLength bytes: '$scriptName'" } 
3070 bytes: 'mikrotik-dns-dhcp.script'
6528 bytes: 'playground'
8065 bytes: 'Function.escapeString.rsc'
1938 bytes: 'Function.stripInvalidHostNameCharactersFromString.rsc'
1411 bytes: 'Function.padLeftString.rsc'
2422 bytes: 'Function.varDump.rsc'
1418 bytes: 'Function.padRightString.rsc'
1515 bytes: 'Function.endsWithString.rsc'
1507 bytes: 'Function.startsWithString.rsc'
and
[jeroenp@MikroTikCCR1009] > /file print
 # NAME                                                          TYPE                                                                SIZE CREATION-TIME       
 0 skins                                                         directory                                                                jan/01/1970 02:00:03
 1 MikroTik-19700102-0048.backup                                 backup                                                           16.0KiB jan/02/1970 02:48:23
 2 pub                                                           directory                                                                jan/02/1970 02:54:47
 3 crs226-export.rsc                                             script                                                               357 jan/02/1970 03:46:45
 4 console-dump.txt                                              .txt file                                                        16.8KiB may/02/2016 14:53:49
 5 DHCP-DNS-work.rsc                                             script                                                            6.1KiB apr/21/2016 22:10:42
 6 WAN0-WAN2.rsc                                                 script                                                            9.2KiB may/01/2016 11:16:57
 7 helden-static-WAN2-plus-route.rsc                             script                                                            9.6KiB may/01/2016 16:39:51
 8 dhcp-server-gateway-via-tp-link.rsc                           script                                                           13.8KiB may/01/2016 20:48:51
 9 apc-dhcp-option-43-dhcp.rsc                                   script                                                           15.6KiB may/02/2016 15:17:02
10 dude                                                          dude store                                                               may/03/2016 12:25:48
11 udp-67-dhcp                                                   file                                                             21.4KiB may/03/2016 16:27:48
12 scripts.rsc                                                   script                                                           38.1KiB may/16/2016 08:35:43
13 mikrotik-dns-dhcp.script.rsc.txt                              .txt file                                                           3070 may/17/2016 07:26:40
14 playground.rsc.txt                                            .txt file                                                           1350 may/17/2016 07:26:37
15 Function.escapeString.rsc.rsc.txt                             .txt file                                                           1430 may/17/2016 07:26:37
16 Function.stripInvalidHostNameCharactersFromString.rsc.rsc.txt .txt file                                                           1510 may/17/2016 07:26:37
17 Function.padLeftString.rsc.rsc.txt                            .txt file                                                           1590 may/17/2016 07:26:37
18 Function.varDump.rsc.rsc.txt                                  .txt file                                                           1670 may/17/2016 07:26:37
19 Function.padRightString.rsc.rsc.txt                           .txt file                                                           1750 may/17/2016 07:26:37
20 Function.endsWithString.rsc.rsc.txt                           .txt file                                                           1830 may/17/2016 07:26:37
21 Function.startsWithString.rsc.rsc.txt                         .txt file                                                           1910 may/17/2016 07:26:37
--jeroen
Last edited by jeroenp on Tue May 17, 2016 8:46 am, edited 1 time in total.
 
User avatar
boen_robot
Forum Guru
Forum Guru
Posts: 2400
Joined: Thu Aug 31, 2006 4:43 pm
Location: europe://Bulgaria/Plovdiv

Re: Is there a good way to sync a local directory from the scripts that a Mikrotik has?

Tue May 17, 2016 8:45 am

Let me guess... the ones that fail are 'playground' and 'Function.escapeString.rsc', right?

Yeah... there's a restriction of 4096 KiB when creating or writing to files. IIRC, uploading and reading such files is still allowed though.