Backup config to Gmail v1.7

Backup script to send config to Gmail account.

#
# Created Jotne 2024 v1.7
#
# 1.7 Fixed new CHR naming (Credit bp0 & baragoon)
# 1.6 Fixed script for x86 devicews (Credit rextended)
# 1.5 Fixed for router missing serial
# 1.4 Added Router OS version
# 1.3r Revised by rextended
# 1.3 / 1.2 try to fix v6/v7 compability
# 1.1 added "show-sensitive"
# 1.0 initial release
#
# Takes two different backup and send then to email
#
# backup.rsc readable backup
# Certificates, the Dude and Usermanager are also NOT exported or backed up fully and should be backed up separately
# Can be used to restore config to different routers
#
# backup.bin binary backup
# Binary backup that can only be used to fully restored the same router.
#


:local email "<your mail>@gmail.com"
:local rscfn "backup"
:local bakfn "bin"

/system
:local date [clock get date]
:local time [clock get time]
:local info [identity get name]
:local board [resource get board-name]
:local files "$rscfn.rsc,$bakfn.backup"
:local Version [resource get version]

/system
:local serial "undefined"
:if (!($board~"(x86|CHR)")) do={
    :global testrbsn "NO RouterBOARD"
    :execute ":global testrbsn; :set testrbsn [/system routerboard get serial-number]"
    :delay 1s
    :set serial $testrbsn
    :set testrbsn
} else={
    :if ($board="x86") do={:set serial [license get software-id]}
    :if ($board~"CHR") do={:set serial [license get system-id]}
}

:if ($Version~"^7") do={
	[:parse "/export show-sensitive file=$rscfn.rsc"]
} else={
	/export file="$rscfn.rsc"
}
:delay 2s

/system backup save name="$bakfn"
:delay 2s

/tool e-mail send to="$email" subject="Mikrotik: Backup $info $Version $serial" file="$files" body="Automatic Backup of $info $serial at $date $time"
:delay 20s
:execute "/file remove $files"
:log info "Backup router=$info serial=$serial ok"

PS Since gmail are free, I suggest you make a new email for your backup files.


Use Splunk> to log/monitor your MikroTik Router(s). See link below. :mrgreen:

MikroTik->Splunk

Their syntax checker kicks in… But you could still cheat with [:parse “:export …”].

{
:local vermajor [:tonum [:pick [/system resource get version] 0 1]]
:if ($vermajor > 6) do={ [:parse "export show-sensitive file=backup.rsc"] } else={ :export file=backup.rsc }
}

I always thought it strange they didn’t just add “show-sensitive” as option in the V6 codeline, even if it’s implied in V6. That wouldn’t break annoying thing in V6, but avoid needing a stupid [:parse “”] thing for a common task. (and yes, I’m sure they need to deal with BOTH show-sensitive and hide-sensitive in V6, but scripts would then be portable between V6/V7)

Perfect. Did learn some new today, so thank you for the help :slight_smile:

Was just what I needed and have tested the script on various version and works fine.

#
# Created Jotne 2022 v1.3
#
# 1.1 Added "show-sensitive"
# 1.3 Fixed v6/v7 compability
#
# Takes two different backup and send then to email
#
# backup.rsc readable backup
# Certificates, the Dude and Usermanager are also NOT exported or backed up fully and should be backed up separately.  Can be used to restore config to different routers
#
# backup.bin binary backup
# Binary backup that can only be used to fully restored the same router.
#

:local email "<your mail>@gmail.com"

:if ([:tonum [:pick [/system resource get version] 0 1]] > 6) do={
	[:parse "export show-sensitive file=backup.rsc"]
} else={
	:export file=backup.rsc
}

:delay 2s
/system backup save name=bin
:delay 2s
:local date [/system clock get date]
:local time [/system clock get time]
:local info [/system identity get name]
:local serial [/system routerboard get serial-number]

:local files "backup.rsc,bin.backup"
/tool e-mail send to="$email" subject="Mikrotik: Backup $info $serial" file=$files body="Automatic Backup of $info $serial at $date $time."
:delay 20s
/file remove backup.rsc
/file remove bin.backup
:log info message="Backup router=$info serial=$serial ok"

[:parse “export show-sensitive file=backup.rsc”]
cause error on v6 because the presence of show-sensitive

edit: never cut with “…” again, cause confusion

Created Jotne 2022 v1.3r

1.3r Revised by REX

1.3 / 1.2 try to fix v6/v7 compability

1.1 added “show-sensitive”

1.0 initial release

Takes two different backup and send then to email

backup.rsc readable backup

Certificates, the Dude and Usermanager are also NOT exported or backed up fully and should be backed up separately

Can be used to restore config to different routers

backup.bin binary backup

Binary backup that can only be used to fully restored the same router.

{

:local email “@gmail.com
:local rscfn “backup”
:local bakfn “bin”

/system
:local date [clock get date]
:local time [clock get time]
:local info [identity get name]
:local serial [routerboard get serial-number]
:local files “$rscfn.rsc,$bakfn.backup”

/system resource
:if ([get version]~“^7”) do={
[:parse “/export show-sensitive file=$rscfn.rsc”]
} else={
/export file=“$rscfn.rsc”
}
:delay 2s

/system backup save name=“$bakfn”
:delay 2s

/tool e-mail send to=“$email” subject=“Mikrotik: Backup $info $serial” file=“$files” body=“Automatic Backup of $info $serial at $date $time”
:delay 20s
:execute “/file remove $files”
:log info “Backup router=$info serial=$serial ok”

}
Edit: put back the on :parse for v7 (invalid syntax but, thank to “if”, never executed on v6)

Related:
(not tested on v7)

save and restore global variables on reboot
http://forum.mikrotik.com/t/persistent-environment-variables/145326/6

Save RouterBOARD full backup of everything [configuration, certificates, host key, router users (no passwords), user-manager, dude, other files]
http://forum.mikrotik.com/t/router-crashes-are-wiping-the-config/149189/7


eidt:added note not tested on v7

Does not work. Tested in 7.1.2

Pasting this to terminal, does not give anything.

:parse "/export show-sensitive file=test.rsc"

But this works:

[:parse "/export show-sensitive file=test.rsc"]

We wouldn’t be here if either V7 or V6 just ignored a meaningless “hide-sensitive” or “show-sensitive” – that seem like something MT should fix somehow…


“:parse” alone creates a :typeof “code”, at “runtime”. But the context that :parse used matters, since it acts more like a script do={} function – so it’s more confusing than it appears. You can see the “code” type here:

:put [:parse "/ip address print"]  
#(eval /ip address print)

:put [:typeof [:parse "/ip address print"]]
# code

Before my time in RouterOS, but believe “:parse” was a way to create functions before the “:global fn do={}” way. So if you view that “:parse <string_script>” is same as do={<actual_script>}, then " :parse" is a definition of something runnable, why :parse at CLI doesn’t run anything.

My version do work at both 6 and 7. What do I need to make rextendeds script to work on 7.x?

@Jonte, which one, and what problem you having? I can offer what see in @rextended’s examples below, but can’t vouch that’s all the V7 issues.


I didn’t try this one, but I DO know it won’t detect functions right in V7. “eval” is now “evl”, here no :parse be needed, just different string to look for in V7 vs V6 to fix that one.

:global x do={:put "blah"}

# Version 7 it's ";evl(" that need to be :find 
/system script environment print detail where name=x
	# 3 name="x" value=";(evl (evl /putmessage=blah))" 

# But in Version 6, it's ";eval" that's @rextended uses
/system script environment print detail where name=x
	# 1 name="x" value=";(eval (eval /putmessage=blah))"

Basically those are :typeof str, but represent the “compiled script” which why @rextended excludes them. Only issue how he’s identifying them similar “:if ($majorversion>6) do={} else={}” thing.


Save RouterBOARD full backup of everything [configuration, certificates, host key, router users (no passwords), user-manager, dude, other files]
Router crashes are wiping the config - #7 by rextended

This one has a different problem. I don’t know exactly why but the “$byemail …” lines need be wrapped in a parenthesis. Only did a quick test, but changing the ALL the $byemail lines like this:

# did not work in V7
  $bymail $dsubj="Certificate $certname $date $time" $dfile="auto_$certname.p12"
# works in V7
 ($bymail $dsubj="Certificate $certname $date $time" $dfile="auto_$certname.p12")
 
# NOTE: I'm not sure the $ in $dsubj= needed

I’ve found being using a “command subdirectory” to then “short form” find/get/set’s sometimes causes odd issues in V7. Do something like “/certificate”, then your code does make the script more human readable – but RouterOS “script compiler” seems to needs more help to figure stuff out when you do that. So putting commands or functions with parameters in parenthesis and/or brackets often helps MT’s hidden script compiler. In theory, I wouldn’t say you should need them, but the ($bymail …) fixed @rextended’s backup script on v7.2rc4 in my quick test.

@Jonte, which one, and what problem you having? I can offer what see in @rextended’s examples below, but can’t vouch that’s all the V7 issues.

My latest postet script do work on both 6 and 7, but version rextended posted does not work on v7.

(I have edited previous post)
The “related” link are not fully tested on v7 (see the dates of the posts…)

Ok, I understand why you do not understand:

The code itself is formally valid until not executed,
(for be more precise, is invalid the “show-sensitive” inside, not the use of the )
the condition is never meet and never executed on v6
Put back on my “revision” work again on v7

My revision is only a hint for explain some “shortcut” or better style of coding…

For example: put / in front of export, because “export” export only current section.
:parse and :execute both consider / as start point, but if on future thath change, script is already ready…

Another example
all this

if ([:tonum [:pick [/system resource get version] 0 1]] > 6) do={
# translated: pick one character from the start of the version string, convert it to a number, if the resulting number is greater than 6 do ...

can be replaced with simpler and fastly readable

/system resource
:if ([get version]~"^7") do={
# translated: if the version string contains "7" at the beginning do ...

it work until version 70.x do not come out on year 2345 (for fixit on year 2345, simply add . at the end, if someone of us is stil alive…)
If sometime on the future 8.x come out, probably the syntax change again, but if on 8, 9, 10 etc, is identical, use something like “^(7|8|9|10)”


For precision (tested on 6.47.10):
:parse “export file=backup.rsc” on v6 do not work like on v7
[:parse “export file=backup.rsc”] this work on both (but on v7 the new default do not export the sensitive data)
[:parse “export show-sensitive file=backup.rsc”] work only on v7 and NOT on v6, because have show-sensitive inside, not recognized on v6

probably the fix for work on both v6 and v7 is to replace
:if ([:typeof [:find $vvalue "(eval " -1]] = “nil”) do={
with
:if (([:typeof [:find $vvalue "(eval " -1]] = “nil”) and ([:typeof [:find $vvalue "(evl " -1]] = “nil”)) do={

Thanks.

The correct syntax is without $ in front of dsubj and dfile,
(caused for make consistant name of variables using replace $oldvarname with $newvarname, without removing $ when is not to be placed)
AND if used $var inside the strings, parenthesys ( ) must be used.
no need to use ( ) when the string not contain $varname
Thanks to you I just discover this strange behaviour.

Correct lines are (I have corrected the original script)

$bymail dsubj=("Certificate $certname $date $time") dfile=("auto_$certname.p12")
$bymail dsubj=("Host Key $date $time") dfile="auto_host-key_dsa,auto_host-key_dsa.pub,auto_host-key_rsa,auto_host-key_rsa.pub"
$bymail dsubj=("User Export $date $time") dfile="auto_user_export.rsc"
$bymail dsubj=("Backup $date $time") dfile="auto_backup.backup"
$bymail dsubj=("Database User-Manager $date $time") dfile="auto_user-manager.umb"
$bymail dsubj=("Database The Dude $date $time") dfile="auto_thedude.db"

I need to use this on v6

:if ($vtype~"^(ip-prefix|ip6-prefix)\$") do={:execute ":global $vname [[:parse \":return $vvalue\"]]"}

because someone on the past broken the “:toip” function and for convert 1.1.1.0/27 to ip-prefix variable type I need to use this hack…
[rex@MATRIX] > :global test 1.1.1.0/24
[rex@MATRIX] > :put [:typeof $test]
ip-prefix

[rex@MATRIX] > :global test “1.1.1.0/24”
[rex@MATRIX] > :put [:typeof $test]
str

[rex@MATRIX] > :global test [:toip “1.1.1.0/24”]
[rex@MATRIX] > :put [:typeof $test]
nil

[rex@MATRIX] > :global test [[:parse “:return 1.1.1.0/24”]]
[rex@MATRIX] > :put [:typeof $test]
ip-prefix

Thanks for the update and explanation rextended :slight_smile:
Now it work both on 7.x and 6.x

Sound familiar: http://forum.mikrotik.com/t/changed-scripting-coding-between-v6-and-v7/152004/1

It was a long time age…even before the Russian war.

Yeah it not only “:export XXXX-sensitive” attributes that differ subtle ways. I’ve been using V7 as excuse to re-writing my V6 scripts as functions, which has worked out well so far: basically everything is a parameterized function. So if you combine [:parse] WITH a function to apply @rextended’s route table fix in above post…


:global rosmajorver [:tonum [:pick [/system resource get version] 0 1]]
:global rtlookup
:set $rtlookup do={
    :if ($rosmajorver>6) do={
        :return [[:parse "/routing table find where name=$1"]]
    } else={
        :return $1
    }
}

# >>  :put [$rtlookup main]
#    *0

With that above your firewall script, like so:

/ip firewall nat find where routing-mark=[$rtlookup "main"]

The function will hide the “ugly” :parse, and in theory you can use extend the above function to validate the route table for V6 etc. But using functions is how I’ve generically solve any some of oddities without a lot of “:if () do={}”'s everywhere.

Note: I know the code works for “main”, but didn’t test too much – more example of an approach to the next “show-sensitive”.

Oh that’s a fun one! In the: “very cleaver solution, but annoying it’s needed” category – but be a long wait for some “:toip-prefix” (or fixing/paramerizing :toip and other :toX) built-in… Quite the path:
a :execute “background script”, that’s generated dynamically via :parse, to update a global variable used in the current – all because only a “:global” type definition will actually do a convert from string to a “ip[6]-prefix” type, BUT where you can define a global is limited. Somehow @rextended approach here does works, pretty nifty.

Script updated to v1.4

Now also sends router version information in the subject. Faster to see when router was upgraded.

#
# Created Jotne 2022 v1.4
#
# 1.4 Added Router OS version
# 1.3r Revised by REX
# 1.3 / 1.2 try to fix v6/v7 compability
# 1.1 added "show-sensitive"
# 1.0 initial release
#
# Takes two different backup and send then to email
#
# backup.rsc readable backup
# Certificates, the Dude and Usermanager are also NOT exported or backed up fully and should be backed up separately
# Can be used to restore config to different routers
#
# backup.bin binary backup
# Binary backup that can only be used to fully restored the same router.
#


:local email "<your mail>@gmail.com"
:local rscfn "backup"
:local bakfn "bin"

/system
:local date [clock get date]
:local time [clock get time]
:local info [identity get name]
:local serial [routerboard get serial-number]
:local files "$rscfn.rsc,$bakfn.backup"
:local Version [resource get version]

:if ($Version~"^7") do={
	[:parse "/export show-sensitive file=$rscfn.rsc"]
} else={
	/export file="$rscfn.rsc"
}
:delay 2s

/system backup save name="$bakfn"
:delay 2s

/tool e-mail send to="$email" subject="Mikrotik: Backup $info $Version $serial" file="$files" body="Automatic Backup of $info $serial at $date $time"
:delay 20s
:execute "/file remove $files"
:log info "Backup router=$info serial=$serial ok"