mirror of
https://github.com/beeyev/Mikrotik-RouterOS-automatic-backup-and-update.git
synced 2025-06-23 21:58:39 +02:00
315 lines
14 KiB
Text
315 lines
14 KiB
Text
|
# Script name: BackupAndUpdate
|
||
|
#
|
||
|
#----------SCRIPT INFORMATION---------------------------------------------------
|
||
|
#
|
||
|
# Script: Mikrotik RouterOS automatic backup & update
|
||
|
# Version: 20.01.20
|
||
|
# Created: 07/08/2018
|
||
|
# Updated: 20/01/2020
|
||
|
# Author: Alexander Tebiev
|
||
|
# Website: https://github.com/beeyev
|
||
|
# You can contact me by e-mail at tebiev@mail.com
|
||
|
#
|
||
|
# IMPORTANT!
|
||
|
# Minimum supported RouterOS version is v6.43.7
|
||
|
#
|
||
|
#----------MODIFY THIS SECTION AS NEEDED----------------------------------------
|
||
|
## Notification e-mail
|
||
|
## (Make sure you have configurated Email settings in Tools -> Email)
|
||
|
:local emailAddress "yourmail@example.com";
|
||
|
|
||
|
## Script mode, possible values: backup, osupdate, osnotify.
|
||
|
# backup - only backup will be perfomed. (default value, if none provided)
|
||
|
# osupdate - script will make a backup and install new RouterOS if it is available.
|
||
|
# osnotify - script will make a backup and notify about new RouterOS version.
|
||
|
:local scriptMode "osnotify";
|
||
|
|
||
|
## Backup encryption password, no encryption if no password.
|
||
|
:local backupPassword ""
|
||
|
|
||
|
## If true, passwords will be included in exported config.
|
||
|
:local sensetiveDataInConfig false;
|
||
|
|
||
|
## Update channel. Possible values: stable, long-term, testing, development
|
||
|
:local updateChannel "stable";
|
||
|
|
||
|
## Install only patch versions of RouterOS updates.
|
||
|
## Works only if you set scriptMode to "osupdate"
|
||
|
## Means that new update will be installed only if MAJOR and MINOR version numbers remained the same as currently installed RouterOS.
|
||
|
## Example: v6.43.6 => major.minor.PATCH
|
||
|
## Script will send information if new version is greater than just patch.
|
||
|
:local installOnlyPatchUpdates false;
|
||
|
##------------------------------------------------------------------------------------------##
|
||
|
# !!!! DO NOT CHANGE ANYTHING BELOW THIS LINE, IF YOU ARE NOT SURE WHAT YOU ARE DOING !!!! #
|
||
|
##------------------------------------------------------------------------------------------##
|
||
|
|
||
|
:log info "\r\nBkp&Upd: script \"Mikrotik RouterOS automatic backup & update\" started.";
|
||
|
|
||
|
#Check proper email config
|
||
|
:if ([:len $emailAddress] = 0 or [:len [/tool e-mail get address]] = 0 or [:len [/tool e-mail get from]] = 0) do={
|
||
|
:log error ("Bkp&Upd: Email configuration is not correct, please check Tools -> Email. Script stopped.");
|
||
|
:error "Bkp&Upd: bye!";
|
||
|
}
|
||
|
|
||
|
############### vvvvvvvvv GLOBALS vvvvvvvvv ###############
|
||
|
# Function converts standard mikrotik build versions to the number.
|
||
|
# Possible arguments: osVer
|
||
|
# Example:
|
||
|
# :put [$brGlobalFuncGetOsVerNum osVer=[/system routerboard get current-RouterOS]];
|
||
|
# result will be: 64301, because current RouterOS version is: 6.43.1
|
||
|
:global brGlobalFuncGetOsVerNum do={
|
||
|
:local osVerNum;
|
||
|
:local osVerMicroPart;
|
||
|
:local zro 0;
|
||
|
:local tmp;
|
||
|
|
||
|
:local dotPos1 [:find $osVer "." 0];
|
||
|
|
||
|
:if ($dotPos1 > 0) do={
|
||
|
|
||
|
# AA
|
||
|
:set osVerNum [:pick $osVer 0 $dotPos1];
|
||
|
|
||
|
:local dotPos2 [:find $osVer "." $dotPos1];
|
||
|
#Taking minor version, everything after first dot
|
||
|
:if ([:len $dotPos2] = 0) do={:set tmp [:pick $osVer ($dotPos1+1) [:len $osVer]];}
|
||
|
#Taking minor version, everything between first and second dots
|
||
|
:if ($dotPos2 > 0) do={:set tmp [:pick $osVer ($dotPos1+1) $dotPos2];}
|
||
|
|
||
|
# AA 0B
|
||
|
:if ([:len $tmp] = 1) do={:set osVerNum "$osVerNum$zro$tmp";}
|
||
|
# AA BB
|
||
|
:if ([:len $tmp] = 2) do={:set osVerNum "$osVerNum$tmp";}
|
||
|
|
||
|
:if ($dotPos2 > 0) do={
|
||
|
:set tmp [:pick $osVer ($dotPos2+1) [:len $osVer]];
|
||
|
# AA BB 0C
|
||
|
:if ([:len $tmp] = 1) do={:set osVerNum "$osVerNum$zro$tmp";}
|
||
|
# AA BB CC
|
||
|
:if ([:len $tmp] = 2) do={:set osVerNum "$osVerNum$tmp";}
|
||
|
} else={
|
||
|
# AA BB 00
|
||
|
:set osVerNum "$osVerNum$zro$zro";
|
||
|
}
|
||
|
} else={
|
||
|
# AA 00 00
|
||
|
:set osVerNum "$osVer$zro$zro$zro$zro";
|
||
|
}
|
||
|
|
||
|
:return $osVerNum;
|
||
|
}
|
||
|
|
||
|
:global brGlobalVarUpdateStep;
|
||
|
############### ^^^^^^^^^ GLOBALS ^^^^^^^^^ ###############
|
||
|
|
||
|
#Current date time in format: 2020jan15-221324
|
||
|
:local dateTime ([:pick [/system clock get date] 7 11] . [:pick [/system clock get date] 0 3] . [:pick [/system clock get date] 4 6] . "-" . [:pick [/system clock get time] 0 2] . [:pick [/system clock get time] 3 5] . [:pick [/system clock get time] 6 8]);
|
||
|
|
||
|
:local deviceOsVerInst [/system package update get installed-version];
|
||
|
:local deviceOsVerInstNum [$brGlobalFuncGetOsVerNum osVer=$deviceOsVerInst];
|
||
|
:local deviceOsVerAvail "";
|
||
|
:local deviceOsVerAvailNum 0;
|
||
|
:local deviceRbModel [/system routerboard get model];
|
||
|
:local deviceRbSerialNumber [/system routerboard get serial-number];
|
||
|
:local deviceRbCurrentFw [/system routerboard get current-firmware];
|
||
|
:local deviceRbUpgradeFw [/system routerboard get upgrade-firmware];
|
||
|
:local deviceIdentityName [/system identity get name];
|
||
|
:local deviceUpdateChannel [/system package update get channel];
|
||
|
|
||
|
:local isOsUpdateAvailable false;
|
||
|
:local isOsNeedsToBeUpdated false;
|
||
|
|
||
|
:local mailSubject "";
|
||
|
:local mailBody "";
|
||
|
|
||
|
:local mailBodyDeviceInfo "\r\n\r\nDevice information: \r\nIdentity: $deviceIdentityName \r\nModel: $deviceRbModel \r\nSerial number: $deviceRbSerialNumber \r\nCurrent RouterOS: $deviceOsVerInst ($[/system package update get channel]) $[/system resource get build-time] \r\nCurrent routerboard FW: $deviceRbCurrentFw \r\nDevice uptime: $[/system resource get uptime]";
|
||
|
:local mailBodyCopyright "\r\n\r\nMikrotik RouterOS automatic backup & update \r\nhttps://github.com/beeyev/Mikrotik-RouterOS-automatic-backup-and-update";
|
||
|
:local changelogUrl ("Check RouterOS changelog: https://mikrotik.com/download/changelogs/" . $updateChannel . "-release-tree");
|
||
|
|
||
|
:local mailAttachments [:toarray ""];
|
||
|
|
||
|
:local updateStep $brGlobalVarUpdateStep;
|
||
|
:do {/system script environment remove brGlobalVarUpdateStep;} on-error={}
|
||
|
:if ([:len $updateStep] = 0) do={
|
||
|
:set updateStep 1;
|
||
|
}
|
||
|
|
||
|
|
||
|
## STEP ONE: Creating backups, checking for new RouterOs version and sending email with backups,
|
||
|
## steps 2 and 3 are fired only if script is set to automatically update device and if new RouterOs is available.
|
||
|
:if ($updateStep = 1) do={
|
||
|
:log info ("Bkp&Upd: Performing the first step.");
|
||
|
|
||
|
# Set email subject and body for the first step
|
||
|
:set mailSubject "Bkp&Upd: Backup completed - $[:pick $deviceIdentityName 0 18].";
|
||
|
:set mailBody "\"$deviceIdentityName\" system backups were created and attached to this email.";
|
||
|
|
||
|
## PREPARE BACKUP DATA
|
||
|
:log info ("Bkp&Upd: Creating system backups.");
|
||
|
|
||
|
:local bname "$deviceIdentityName.$deviceBoardModel.$deviceSerialNumber.v$deviceOsVerInst.$deviceUpdateChannel.$dateTime";
|
||
|
:local backupFileSys "$bname.backup";
|
||
|
:local backupFileConfig "$bname.rsc";
|
||
|
|
||
|
:set mailAttachments {$backupFileSys;$backupFileConfig};
|
||
|
|
||
|
## Make system backup
|
||
|
:if ([:len $backupPassword] = 0) do={
|
||
|
/system backup save dont-encrypt=yes name=$bname;
|
||
|
} else={
|
||
|
/system backup save password=$backupPassword name=$bname;
|
||
|
}
|
||
|
:log info ("Bkp&Upd: System backup created. $backupFileSys");
|
||
|
|
||
|
## Export config file
|
||
|
:if ($sensetiveDataInConfig = true) do={
|
||
|
/export compact file=$bname;
|
||
|
} else={
|
||
|
/export compact hide-sensitive file=$bname;
|
||
|
}
|
||
|
:log info ("Bkp&Upd: Config file was exported. $backupFileConfig");
|
||
|
|
||
|
# Checking for new RouterOS version
|
||
|
if ($scriptMode = "osupdate" or $scriptMode = "osnotify") do={
|
||
|
log info ("Bkp&Upd: Checking for new RouterOS version. Current version is: $deviceOsVerInst");
|
||
|
/system package update set channel=$updateChannel;
|
||
|
/system package update check-for-updates;
|
||
|
:delay 5s;
|
||
|
:set deviceOsVerAvail [/system package update get latest-version];
|
||
|
|
||
|
# If there is a problem getting information about available RouterOS from server
|
||
|
:if ([:len $deviceOsVerAvail] = 0) do={
|
||
|
:log warning ("Bkp&Upd: There is a problem getting information about new RouterOS from server.");
|
||
|
:set mailSubject ($mailSubject . " Error: No data about new RouterOS!")
|
||
|
:set mailBody ($mailBody . "\r\n\r\nError occured! \r\nMikrotik couldn't get any information about new RouterOS from server! \r\nWatch additional information in device logs.")
|
||
|
} else={
|
||
|
#Get numeric version of OS
|
||
|
:set deviceOsVerAvailNum [$brGlobalFuncGetOsVerNum osVer=$deviceOsVerAvail];
|
||
|
|
||
|
# Checking if OS on server is greater than installed one.
|
||
|
:if ($deviceOsVerAvailNum > $deviceOsVerInstNum) do={
|
||
|
:set isOsUpdateAvailable true;
|
||
|
:log info ("Bkp&Upd: New RouterOS is available! $deviceOsVerAvail");
|
||
|
} else={
|
||
|
:set mailSubject ($mailSubject . " No new OS updates.")
|
||
|
:set mailBody ($mailBody . "\r\nYour system is up to date.")
|
||
|
:log info ("Bkp&Upd: System is already up to date.")
|
||
|
}
|
||
|
};
|
||
|
} else={
|
||
|
#Delay after creating backups
|
||
|
:delay 5s;
|
||
|
};
|
||
|
|
||
|
|
||
|
# if new OS version is available to install
|
||
|
if ($isOsUpdateAvailable = true) do={
|
||
|
# If we only need to notify about new available version
|
||
|
if ($scriptMode = "osnotify") do={
|
||
|
:set mailSubject ($mailSubject . " New RouterOS is available! v.$deviceOsVerAvail")
|
||
|
:set mailBody ($mailBody . "\r\n\r\nNew RouterOS version is available to install: v.$deviceOsVerAvail ($updateChannel) \r\n$changelogUrl")
|
||
|
}
|
||
|
|
||
|
# if we need to initiate RouterOs update process
|
||
|
if ($scriptMode = "osupdate") do={
|
||
|
:set isOsNeedsToBeUpdated true;
|
||
|
# if we need to install only patch updates
|
||
|
:if ($installOnlyPatchUpdates = true) do={
|
||
|
#Check if Major and Minor builds are the same.
|
||
|
:if ([:pick $deviceOsVerInstNum 0 ([:len $deviceOsVerInstNum]-2)] = [:pick $deviceOsVerAvailNum 0 ([:len $deviceOsVerAvailNum]-2)]) do={
|
||
|
:log info ("Bkp&Upd: New patch version of RouterOS firmware is available.");
|
||
|
} else={
|
||
|
:log info ("Bkp&Upd: New minor version of RouterOS firmware is available. You need to update it manually.");
|
||
|
:set mailSubject ($mailSubject . " New major RouterOS is available: v.$deviceOsVerAvail!");
|
||
|
:set mailBody ($mailBody . "\r\n\r\nNew major RouterOS version is available to install: v.$deviceOsVerAvail ($updateChannel). \r\nYou chose to automatically install only patch updates, so this major update you need to install manually. \r\n$changelogUrl");
|
||
|
:set isOsNeedsToBeUpdated false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#Check again, because this variable could be changed during checking for installing only patch updats
|
||
|
if ($isOsNeedsToBeUpdated = true) do={
|
||
|
:set mailSubject ($mailSubject . " New RouterOS is going to be installed! v.$deviceOsVerInst -> v.$deviceOsVerAvail");
|
||
|
:set mailBody ($mailBody . "\r\n\r\nYour Mikrotik will be updated to the new RouterOS version from v.$deviceOsVerInst to v.$deviceOsVerAvail (Update channel: $updateChannel) \r\nFinal report with detailed information will be sent when update process is completed. \r\nIf you have not received second email in the next 5 minutes, then probably something went wrong.");
|
||
|
#!! There is more code connected to this part and first step at the end of the script.
|
||
|
}
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
# Combine fisrst step email
|
||
|
:set mailBody ($mailBody . $mailBodyDeviceInfo . $mailBodyCopyright);
|
||
|
:log info ("Bkp&Upd: Sending email with backups in attachment.");
|
||
|
}
|
||
|
|
||
|
# Remove function brGlobalFuncGetOsVerNum from global environment to keep it fresh and clean.
|
||
|
:do {/system script environment remove brGlobalFuncGetOsVerNum;} on-error={}
|
||
|
|
||
|
## STEP TWO: (after first reboot) routerboard firmware upgrade
|
||
|
## steps 2 and 3 are fired only if script is set to automatically update device and if new RouterOs is available.
|
||
|
:if ($updateStep = 2) do={
|
||
|
:log info ("Bkp&Upd: Performing the second step.");
|
||
|
## RouterOS is the latest, let's check for upgraded routerboard firmware
|
||
|
if ($deviceRbCurrentFw != $deviceRbUpgradeFw) do={
|
||
|
:log info "Bkp&Upd: Upgrading routerboard firmware from v.$deviceRbCurrentFw to v.$deviceRbUpgradeFw";
|
||
|
## Start the upgrading process
|
||
|
/system routerboard upgrade;
|
||
|
## Wait until the upgrade is completed
|
||
|
:delay 5s;
|
||
|
:log info "Bkp&Upd: routerboard upgrading process was completed, going to reboot in a moment!";
|
||
|
## Set scheduled task to send final report on the next boot, task will be deleted when is is done. (That is why you should keep original script name)
|
||
|
/system schedule add name=BKPUPD-FINAL-REPORT-ON-NEXT-BOOT on-event=":delay 5s; /system scheduler remove BKPUPD-FINAL-REPORT-ON-NEXT-BOOT; :global brGlobalVarUpdateStep 3; :delay 10s; /system script run BackupAndUpdate;" start-time=startup interval=0;
|
||
|
## Reboot system to boot with new firmware
|
||
|
/system reboot;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
## STEP THREE: Last step (after second reboot) sending final report
|
||
|
## steps 2 and 3 are fired only if script is set to automatically update device and if new RouterOs is available.
|
||
|
:if ($updateStep = 3) do={
|
||
|
:log info "Bkp&Upd: RouterOS and routerboard upgrading process of was completed. New RouterOS version: v.$deviceOsVerInst, routerboard firmware: v.$deviceRbCurrentFw.";
|
||
|
:set mailSubject "Bkp&Upd: Router - $[:pick $deviceIdentityName 0 18] has been upgraded to the new RouterOS v.$deviceOsVerInst!";
|
||
|
:set mailBody "RouterOS and routerboard upgrading process was completed. \r\nNew RouterOS version: v.$deviceOsVerInst, routerboard firmware: v.$deviceRbCurrentFw. \r\n$changelogUrl $mailBodyDeviceInfo $mailBodyCopyright";
|
||
|
}
|
||
|
|
||
|
##
|
||
|
## SENDING EMAIL
|
||
|
##
|
||
|
# Trying to send email with backups in attachment.
|
||
|
:if ($updateStep = 1 or $updateStep = 3) do={
|
||
|
:do {/tool e-mail send to=$emailAddress subject=$mailSubject body=$mailBody file=$mailAttachments;} on-error={
|
||
|
:log error "Bkp&Upd: could not send email message ($[/tool e-mail get last-status]). Going to try it again in a while."
|
||
|
:delay 5m;
|
||
|
:do {/tool e-mail send to=$emailAddress subject=$mailSubject body=$mailBody file=$mailAttachments;} on-error={
|
||
|
:log error "Bkp&Upd: could not send email message ($[/tool e-mail get last-status]) for the second time."
|
||
|
|
||
|
if ($isOsNeedsToBeUpdated = true) do={
|
||
|
:log warning "Bkp&Upd: script didn't initialise update process due to inability to send backups to email."
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
:delay 5s;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
## Remove backups which we have already sent during first step
|
||
|
:if ($updateStep = 1 and [/tool e-mail get last-status] = "succeeded") do={
|
||
|
:log info "Bkp&Upd: File system cleanup."
|
||
|
/file remove $mailAttachments;
|
||
|
:delay 2s;
|
||
|
|
||
|
# Fire update process only if backups were successfully sent
|
||
|
if ($isOsNeedsToBeUpdated = true) do={
|
||
|
|
||
|
## Set scheduled task to upgrade routerboard firmware on the next boot, task will be deleted when upgrade is done. (That is why you should keep original script name)
|
||
|
/system schedule add name=BKPUPD-UPGRADE-ON-NEXT-BOOT on-event=":delay 5s; /system scheduler remove BKPUPD-UPGRADE-ON-NEXT-BOOT; :global brGlobalVarUpdateStep 2; :delay 10s; /system script run BackupAndUpdate;" start-time=startup interval=0;
|
||
|
|
||
|
:log info "Bkp&Upd: everything is ready to install new RouterOS, going to reboot in a moment!"
|
||
|
## command is reincarnation of the "upgrade" command - doing exactly the same but under a different name
|
||
|
/system package update install;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
:log info "Bkp&Upd: script \"Mikrotik RouterOS automatic backup & update\" completed it's job.\r\n";
|