Compare commits

...

14 commits

Author SHA1 Message Date
Christian Hesse
32cc55f7d2 introduce firmware-upgrade-reboot
(cherry picked from commit 3c358980cb)
2022-02-10 09:15:21 +01:00
Christian Hesse
c95e816148 netwatch-dns: flush cache on configuration change
(cherry picked from commit a47f5723cc)
2022-02-10 09:15:04 +01:00
Christian Hesse
0c607a8f9c netwatch-notify: nest conditions
The logic here was right, but RouterOS runs the checks simultaneously.
This caused delays even if no resolving was needed.

Nesting the checks fixes this.

(cherry picked from commit 0b46c508dc)
2022-02-10 09:14:49 +01:00
Christian Hesse
c03da561cd netwatch-notify: allow to suppress notification on host down
(cherry picked from commit c6e581d4f9)
2022-02-10 09:14:36 +01:00
Christian Hesse
8d49babb01 doc/netwatch-notify: add sections
(cherry picked from commit 42c203291a)
2022-02-10 09:14:22 +01:00
Christian Hesse
b2f45c0350 doc/packages-update: link backup-cloud
(cherry picked from commit dd19aea362)
2022-02-10 09:14:07 +01:00
Christian Hesse
52bd08b750 packages-update: use correct syntax
(cherry picked from commit 27a81bcbca)
2022-01-30 22:08:31 +01:00
Christian Hesse
221b0409d5 check-routeros-update: use correct syntax
(cherry picked from commit dfe995be27)
2022-01-30 22:08:31 +01:00
Christian Hesse
0a9d0473f3 global-functions: $ScriptInstallUpdate: quote names in log output
(cherry picked from commit 5e32105e7e)
2022-01-20 22:18:07 +01:00
Christian Hesse
9024e20c0b global-functions: $ScriptInstallUpdate: give final url in debug output
(cherry picked from commit b4a5d824a2)
2022-01-20 22:18:07 +01:00
Christian Hesse
5363df3568 global-functions: $DownloadPackage: handle special case with name
For RouterOS 6.x bundled package version and architecture are swapped.

Closes: #21

(cherry picked from commit 1e6931c8e3)
2022-01-17 20:58:03 +01:00
Christian Hesse
25338ca384 global-functions: $DownloadPackage: give url in debug output
(cherry picked from commit 51cd11c803)
2022-01-17 20:57:19 +01:00
Christian Hesse
ee9818e34d global: send notification on 'routeros-v6'
This is mainly to keep the version in 'routeros-v6'
and 'main' in sync...
2022-01-14 09:17:54 +01:00
Christian Hesse
7d5c967995 global-config: add $ScriptUpdatesUrlSuffix in overlay for RouterOS v6 2022-01-14 09:17:54 +01:00
14 changed files with 155 additions and 48 deletions

View file

@ -204,6 +204,7 @@ Available scripts
* [Use wireless network with daily psk](doc/daily-psk.md)
* [Comment DHCP leases with info from access list](doc/dhcp-lease-comment.md)
* [Create DNS records for DHCP leases](doc/dhcp-to-dns.md)
* [Automatically upgrade firmware and reboot](doc/firmware-upgrade-reboot.md)
* [Wait for global functions und modules](doc/global-wait.md)
* [Send GPS position to server](doc/gps-track.md)
* [Use WPA2 network with hotspot credentials](doc/hotspot-to-wpa.md)

View file

@ -108,7 +108,7 @@ $LogPrintExit2 debug $0 ("Checking for updates...") false;
:if ([ $ScriptFromTerminal $0 ] = true) do={
:put ("Do you want to install RouterOS version " . $Update->"latest-version" . "? [y/N]");
:if (([ :terminal inkey timeout=60 ] % 32) = 25) do={
:if (([ / terminal inkey timeout=60 ] % 32) = 25) do={
$DoUpdate;
} else={
:put "Canceled...";

View file

@ -61,6 +61,7 @@ Installing script [packages-update](packages-update.md) gives extra options.
See also
--------
* [Automatically upgrade firmware and reboot](firmware-upgrade-reboot.md)
* [Manage system update](packages-update.md)
---

View file

@ -0,0 +1,36 @@
Automatically upgrade firmware and reboot
=========================================
[◀ Go back to main README](../README.md)
🛈 This script can not be used on its own but requires the base installation.
See [main README](../README.md) for details.
Description
-----------
RouterOS and firmware are upgraded separately, activating the latter
requires an extra reboot. This script handles upgrade and reboot.
⚠️ **Warning**: This *should* be bullet proof, but I can not guarantee. In
worst case it has potential to cause a boot loop, so handle with care!
Requirements and installation
-----------------------------
Just install the script and create a scheduler:
$ScriptInstallUpdate firmware-upgrade-reboot;
/ system scheduler add name=firmware-upgrade-reboot on-event="/ system script run firmware-upgrade-reboot;" start-time=startup;
Enjoy firmware being up to date and in sync with RouterOS.
See also
--------
* [Notify on RouterOS update](check-routeros-update.md)
* [Manage system update](packages-update.md)
---
[◀ Go back to main README](../README.md)
[▲ Go back to top](#top)

View file

@ -38,6 +38,8 @@ The hosts to be checked have to be added to netwatch with specific comment:
/ tool netwatch add comment="notify, hostname=example.com" host=[ :resolve "example.com" ];
### Hooks
It is possible to run an up hook command (`up-hook`) or down hook command
(`down-hook`) when a notification is triggered. This has to be added in
comment, note that some characters need extra escaping:
@ -48,10 +50,14 @@ Also there is a `pre-down-hook` that fires at two thirds of failed checks
required for the notification. The idea is to fix the issue before a
notification is sent.
### Count threshould
The count threshould (default is 5 checks) is configurable as well:
/ tool netwatch add comment="notify, hostname=example.com, count=10" host=104.18.144.11;
### Parents & dependencies
If the host is behind another checked host add a dependency, this will
suppress notification if the parent host is down:
@ -61,6 +67,8 @@ suppress notification if the parent host is down:
Note that every configured parent in a chain increases the check count
threshould by one.
### Update from DNS
The host address can be updated dynamically. Give extra parameter `resolve`
with a resolvable name:
@ -70,6 +78,16 @@ But be warned: Dynamic updates will probably cause issues if the name has
more than one record in dns - a high rate of configuration changes (and flash
writes) at least.
### No notification on host down
Also suppressing the notification on host down is possible with parameter
`no-down-notification`. This may be desired for devices that are usually
powered off, but accessibility is of interest.
/ tool netwatch add comment="notify, hostname=printer, no-down-notification" host=10.0.0.30;
Go and get your coffee ☕️ before sending the print job.
Also notification settings are required for e-mail, matrix and/or telegram.
Tips & Tricks

View file

@ -41,8 +41,10 @@ See also
--------
* [Notify on RouterOS update](check-routeros-update.md)
* [Upload backup to Mikrotik cloud](backup-cloud.md)
* [Send backup via e-mail](backup-email.md)
* [Upload backup to server](backup-upload.md)
* [Automatically upgrade firmware and reboot](firmware-upgrade-reboot.md)
---
[◀ Go back to main README](../README.md)

32
firmware-upgrade-reboot Normal file
View file

@ -0,0 +1,32 @@
#!rsc by RouterOS
# RouterOS script: firmware-upgrade-reboot
# Copyright (c) 2022 Christian Hesse <mail@eworm.de>
# https://git.eworm.de/cgit/routeros-scripts/about/COPYING.md
#
# install firmware upgrade, and reboot
# https://git.eworm.de/cgit/routeros-scripts/about/doc/firmware-upgrade-reboot.md
:local 0 "firmware-upgrade-reboot";
:global GlobalFunctionsReady;
:while ($GlobalFunctionsReady != true) do={ :delay 500ms; }
:global LogPrintExit2;
:local RouterBoard [ / system routerboard get ];
:if ($RouterBoard->"current-firmware" = $RouterBoard->"upgrade-firmware") do={
$LogPrintExit2 info $0 ("Firmware is already up to date.") true;
}
:if ([ / system routerboard settings get auto-upgrade ] = false) do={
$LogPrintExit2 info $0 ("Firmware version " . $RouterBoard->"upgrade-firmware" . \
" is available, upgrading.") false;
/ system routerboard upgrade;
}
:while ([ :len [ / log find where topics=({"system";"info";"critical"}) \
message="Firmware upgraded successfully, please reboot for changes to take effect!" ] ] = 0) do={
:delay 1s;
}
$LogPrintExit2 info $0 ("Firmware upgrade successful, rebooting.") false;
/ system reboot;

View file

@ -8,7 +8,7 @@
# Make sure all configuration properties are up to date and this
# value is in sync with value in script 'global-functions'!
:global GlobalConfigVersion 74;
:global GlobalConfigVersion 77;
# This is used for DNS and backup file.
:global Domain "example.com";

View file

@ -8,7 +8,10 @@
# Make sure all configuration properties are up to date and this
# value is in sync with value in script 'global-functions'!
# Comment or remove to disable news and change notifications.
:global GlobalConfigVersion 74;
:global GlobalConfigVersion 77;
# Use branch routeros-v6 with RouterOS v6:
:global ScriptUpdatesUrlSuffix "\?h=routeros-v6";
# Copy configuration from global-config here and modify it.

View file

@ -78,6 +78,9 @@
72="Introduced new script 'netwatch-dns' to manage DNS and DoH servers from netwatch.";
73="Renamed backup scripts ('cloud-backup' -> 'backup-cloud', 'email-backup' -> 'backup-email', 'upload-backup' -> 'backup-upload').";
74="Extended 'hotspot-to-wpa', it can now read additional configuration from templates and hotspot users.";
75="You are using the branch 'routeros-v6', well done.";
76="Added an option to suppress notifications on host down with 'netwatch-notify'.";
77="Introduced new script 'firmware-upgrade-reboot'. Handle with care!";
};
# Migration steps to be applied on script updates

View file

@ -8,7 +8,7 @@
# https://git.eworm.de/cgit/routeros-scripts/about/
# expected configuration version
:global ExpectedConfigVersion 74;
:global ExpectedConfigVersion 77;
# global variables not to be changed by user
:global GlobalFunctionsReady false;
@ -252,6 +252,7 @@
:global CleanFilePath;
:global LogPrintExit2;
:global MkDir;
:global VersionToNum;
:global WaitForFile;
:if ([ :len $PkgName ] = 0) do={ :return false; }
@ -259,6 +260,9 @@
:if ([ :len $PkgArch ] = 0) do={ :set PkgArch [ / system resource get architecture-name ]; }
:local PkgFile ($PkgName . "-" . $PkgVer . "-" . $PkgArch . ".npk");
:if ([ $VersionToNum $PkgVer ] < [ $VersionToNum "7.0" ] && $PkgName = "routeros") do={
:set PkgFile ($PkgName . "-" . $PkgArch . "-" . $PkgVer . ".npk");
}
:if ($PkgArch = "x86_64" || $PkgName ~ "^routeros-") do={
:set PkgFile ($PkgName . "-" . $PkgVer . ".npk");
}
@ -278,13 +282,13 @@
$LogPrintExit2 error $0 ("Downloading required certificate failed.") true;
}
:local Url ("https://upgrade.mikrotik.com/routeros/" . $PkgVer . "/" . $PkgFile);
$LogPrintExit2 info $0 ("Downloading package file '" . $PkgName . "'...") false;
$LogPrintExit2 debug $0 ("... from url: " . $Url) false;
:local Retry 3;
:while ($Retry > 0) do={
:do {
/ tool fetch check-certificate=yes-without-crl \
("https://upgrade.mikrotik.com/routeros/" . $PkgVer . "/" . $PkgFile) \
dst-path=$PkgDest;
/ tool fetch check-certificate=yes-without-crl $Url dst-path=$PkgDest;
$WaitForFile $PkgDest;
:if ([ / file get [ find where name=$PkgDest ] type ] = "package") do={
@ -719,28 +723,28 @@
:foreach Scheduler in=[ / system scheduler find where on-event~("\\b" . $ScriptVal->"name" . "\\b") ] do={
:local SchedulerVal [ / system scheduler get $Scheduler ];
:if ($ScriptVal->"policy" != $SchedulerVal->"policy") do={
$LogPrintExit2 warning $0 ("Policies differ for script " . $ScriptVal->"name" . \
" and its scheduler " . $SchedulerVal->"name" . "!") false;
$LogPrintExit2 warning $0 ("Policies differ for script '" . $ScriptVal->"name" . \
"' and its scheduler '" . $SchedulerVal->"name" . "'!") false;
}
}
:if ([ :len $SourceNew ] = 0 && $ScriptUpdatesFetch = true) do={
:local Comment [ $ParseKeyValueStore ($ScriptVal->"comment") ];
:if (!($Comment->"ignore" = true)) do={
$LogPrintExit2 debug $0 ("Fetching script from url: " . $ScriptVal->"name") false;
:do {
:local BaseUrl $ScriptUpdatesBaseUrl;
:local UrlSuffix $ScriptUpdatesUrlSuffix;
:if ([ :typeof ($Comment->"base-url") ] = "str") do={ :set BaseUrl ($Comment->"base-url"); }
:if ([ :typeof ($Comment->"url-suffix") ] = "str") do={ :set UrlSuffix ($Comment->"url-suffix"); }
:local Url ($BaseUrl . $ScriptVal->"name" . $UrlSuffix);
:local Result [ / tool fetch check-certificate=yes-without-crl \
($BaseUrl . $ScriptVal->"name" . $UrlSuffix) output=user as-value ];
$LogPrintExit2 debug $0 ("Fetching script '" . $ScriptVal->"name" . "' from url: " . $Url) false;
:local Result [ / tool fetch check-certificate=yes-without-crl $Url output=user as-value ];
:if ($Result->"status" = "finished") do={
:set SourceNew ($Result->"data");
}
} on-error={
$LogPrintExit2 warning $0 ("Failed fetching " . $ScriptVal->"name") false;
$LogPrintExit2 warning $0 ("Failed fetching script '" . $ScriptVal->"name" . "'!") false;
}
}
}
@ -761,18 +765,18 @@
:set ReloadGlobalFunctions true;
}
} else={
$LogPrintExit2 warning $0 ("Syntax validation for script " . $ScriptVal->"name" . \
" failed! Ignoring!") false;
$LogPrintExit2 warning $0 ("Syntax validation for script '" . $ScriptVal->"name" . \
"' failed! Ignoring!") false;
}
} else={
$LogPrintExit2 warning $0 ("Looks like new script " . $ScriptVal->"name" . \
" is not valid (missing shebang). Ignoring!") false;
$LogPrintExit2 warning $0 ("Looks like new script '" . $ScriptVal->"name" . \
"' is not valid (missing shebang). Ignoring!") false;
}
} else={
$LogPrintExit2 debug $0 ("Script " . $ScriptVal->"name" . " did not change.") false;
$LogPrintExit2 debug $0 ("Script '" . $ScriptVal->"name" . "' did not change.") false;
}
} else={
$LogPrintExit2 debug $0 ("No update for script " . $ScriptVal->"name" . ".") false;
$LogPrintExit2 debug $0 ("No update for script '" . $ScriptVal->"name" . "'.") false;
}
}
@ -800,11 +804,10 @@
:global GlobalConfigMigration;
:local ChangeLogCode;
$LogPrintExit2 debug $0 ("Fetching news, changes and migration.") false;
:do {
:local Result [ / tool fetch check-certificate=yes-without-crl \
($ScriptUpdatesBaseUrl . "global-config.changes" . $ScriptUpdatesUrlSuffix) \
output=user as-value ];
:local Url ($ScriptUpdatesBaseUrl . "global-config.changes" . $ScriptUpdatesUrlSuffix);
$LogPrintExit2 debug $0 ("Fetching news, changes and migration: " . $Url) false;
:local Result [ / tool fetch check-certificate=yes-without-crl $Url output=user as-value ];
:if ($Result->"status" = "finished") do={
:set ChangeLogCode ($Result->"data");
}

View file

@ -43,12 +43,14 @@ $ScriptLock $0;
:if ($DnsServers != $DnsCurrent) do={
$LogPrintExit2 info $0 ("Updating DNS servers: " . [ :tostr $DnsServers ]) false;
/ ip dns set servers=$DnsServers;
/ ip dns cache flush;
}
} else={
:if ([ :len $DnsFallback ] > 0) do={
:if ($DnsFallback != $DnsCurrent) do={
$LogPrintExit2 info $0 ("Updating DNS servers to fallback: " . [ :tostr $DnsFallback ]) false;
/ ip dns set servers=$DnsFallback;
/ ip dns cache flush;
}
}
}
@ -69,10 +71,12 @@ $ScriptLock $0;
:if ($DohServer != $DohCurrent) do={
$LogPrintExit2 info $0 ("Updating DoH server: " . $DohServer) false;
/ ip dns set use-doh-server=$DohServer;
/ ip dns cache flush;
}
} else={
:if ($DohCurrent != "") do={
$LogPrintExit2 info $0 ("DoH server (" . $DohCurrent . ") is down, disabling.") false;
/ ip dns set use-doh-server="";
/ ip dns cache flush;
}
}

View file

@ -66,21 +66,23 @@ $ScriptLock $0;
:set $Metric ($NetwatchNotify->$HostName);
}
:if ([ :typeof ($HostInfo->"resolve") ] = "str" && [ $DNSIsResolving ] = true) do={
:do {
:local Resolve [ :resolve ($HostInfo->"resolve") ];
:if ($Resolve != $HostVal->"host") do={
$LogPrintExit2 info $0 ("Name '" . $HostInfo->"resolve" . [ $IfThenElse ($HostInfo->"resolve" != \
$HostInfo->"hostname") ("' for host '" . $HostInfo->"hostname") "" ] . \
"' resolves to different address " . $Resolve . ", updating.") false;
/ tool netwatch set host=$Resolve $Host;
:set ($Metric->"resolve-failed") false;
}
} on-error={
:if ($Metric->"resolve-failed" != true) do={
$LogPrintExit2 warning $0 ("Resolving name '" . $HostInfo->"resolve" . [ $IfThenElse ($HostInfo->"resolve" != \
$HostInfo->"hostname") ("' for host '" . $HostInfo->"hostname") "" ] . "' failed.") false;
:set ($Metric->"resolve-failed") true;
:if ([ :typeof ($HostInfo->"resolve") ] = "str") do={
:if ([ $DNSIsResolving ] = true) do={
:do {
:local Resolve [ :resolve ($HostInfo->"resolve") ];
:if ($Resolve != $HostVal->"host") do={
$LogPrintExit2 info $0 ("Name '" . $HostInfo->"resolve" . [ $IfThenElse ($HostInfo->"resolve" != \
$HostInfo->"hostname") ("' for host '" . $HostInfo->"hostname") "" ] . \
"' resolves to different address " . $Resolve . ", updating.") false;
/ tool netwatch set host=$Resolve $Host;
:set ($Metric->"resolve-failed") false;
}
} on-error={
:if ($Metric->"resolve-failed" != true) do={
$LogPrintExit2 warning $0 ("Resolving name '" . $HostInfo->"resolve" . [ $IfThenElse ($HostInfo->"resolve" != \
$HostInfo->"hostname") ("' for host '" . $HostInfo->"hostname") "" ] . "' failed.") false;
:set ($Metric->"resolve-failed") true;
}
}
}
}
@ -122,10 +124,10 @@ $ScriptLock $0;
:set Parent ($NetwatchNotify->$Parent->"parent");
}
}
$LogPrintExit2 info $0 ("Host " . $HostName . " (" . $HostVal->"host" . ") is down for " . \
$Metric->"count" . " checks, " . [ $IfThenElse ($ParentNotified = false) [ $IfThenElse \
($Metric->"notified" = true) ("already notified.") ($Count - $Metric->"count" . " to go.") ] \
("parent host " . $Parent . " is down.") ]) false;
$LogPrintExit2 [ $IfThenElse ($HostInfo->"no-down-notification" != true) info debug ] $0 \
("Host " . $HostName . " (" . $HostVal->"host" . ") is down for " . $Metric->"count" . " checks, " . \
[ $IfThenElse ($ParentNotified = false) [ $IfThenElse ($Metric->"notified" = true) ("already notified.") \
($Count - $Metric->"count" . " to go.") ] ("parent host " . $Parent . " is down.") ]) false;
:if ((($Count * 2) - ($Metric->"count" * 3)) / 2 = 0 && [ :typeof ($HostInfo->"pre-down-hook") ] = "str") do={
$NetwatchNotifyHook $HostName "pre-down" ($HostInfo->"pre-down-hook");
}
@ -134,9 +136,11 @@ $ScriptLock $0;
:if ([ :typeof ($HostInfo->"down-hook") ] = "str") do={
:set Message ($Message . "\n\n" . [ $NetwatchNotifyHook $HostName "down" ($HostInfo->"down-hook") ]);
}
$SendNotification2 ({ origin=$0; \
subject=([ $SymbolForNotification "cross-mark" ] . "Netwatch Notify: " . $HostName . " down"); \
message=$Message });
:if ($HostInfo->"no-down-notification" != true) do={
$SendNotification2 ({ origin=$0; \
subject=([ $SymbolForNotification "cross-mark" ] . "Netwatch Notify: " . $HostName . " down"); \
message=$Message });
}
:set ($Metric->"notified") true;
}
}

View file

@ -35,7 +35,7 @@ $ScriptLock $0;
:if ($NumInstalled > $NumLatest) do={
:if ([ $ScriptFromTerminal $0 ] = true) do={
:put "Latest version is older than installed one. Want to downgrade? [y/N]";
:if (([ :terminal inkey timeout=60 ] % 32) = 25) do={
:if (([ / terminal inkey timeout=60 ] % 32) = 25) do={
:set DoDowngrade true;
} else={
:put "Canceled...";
@ -61,7 +61,7 @@ $ScriptLock $0;
$LogPrintExit2 warning $0 ("Running backup script " . $ScriptName . " before update failed!") false;
:if ([ $ScriptFromTerminal $0 ] = true) do={
:put "Do you want to continue anyway? [y/N]";
:if (([ :terminal inkey timeout=60 ] % 32) = 25) do={
:if (([ / terminal inkey timeout=60 ] % 32) = 25) do={
$LogPrintExit2 info $0 ("User requested to continue anyway.") false;
} else={
$LogPrintExit2 info $0 ("Canceled update...") true;
@ -80,7 +80,7 @@ $ScriptLock $0;
:if ([ $ScriptFromTerminal $0 ] = true) do={
:put "Do you want to (s)chedule reboot or (r)eboot now? [s/R]";
:if (([ :terminal inkey timeout=60 ] % 32) = 19) do={
:if (([ / terminal inkey timeout=60 ] % 32) = 19) do={
/ system scheduler add name="reboot-for-update" start-time=03:00:00 interval=1d \
on-event=(":global RandomDelay; \$RandomDelay 3600; " . \
"/ system scheduler remove reboot-for-update; / system reboot;");