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
I tried. But none of the things in `/system scripts print` show up on the FTP server.FTP.
I tried. But none of the things in `/system scripts print` show up on the FTP server.FTP.
How would that fit in the workflow?Use export command instead of print.
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.Point 5. Export to file. Then you can grab it by ftp out.
: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)
:foreach scriptId in [/system script find] do={ :local script [/system script get $scriptId]; :put $script }
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"
: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")
}
That fails: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:
...
failure: new contents too long
# 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
So basically you say that `get` should have been like this: `/system script get` right?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).
: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
: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'
[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