I wrote a script that works in almost every situation, but when it fails, it causes a massive problem.
Basically, the script is scheduled to run 3 seconds after a reboot.
It compares the information from /system/routerboard firmware; if the new firmware has been applied—and assuming /system routerboard settings set auto-upgrade=yes is actually active—it triggers another reboot.
The goal here is to ensure that, when managing hundreds of units, none are left with updated RouterOS and updated firmware but still running the old current-firmware version simply because a reboot was missed.
I encountered a very peculiar case (truly peculiar—it has only happened to me twice) where the firmware auto-upgrade procedure didn't go as expected. As a result, the unit got stuck in an infinite reboot loop, restarting just 3 seconds after booting up.
It might not be the most elegant script in the world, but I can say with confidence that it works 99.9% of the time.
Naturally, I am already refining the logic to minimize the risk of this type of problem occurring.
The worst part:
To make matters worse, the field technician arrived at the site with a console cable but couldn't stop the loop by pressing keys or anything similar... We had to perform a Netinstall to resolve the issue.
I am looking for a way—without having to log in via WinBox, SSH, or console—for the field technician to prevent that final reboot simply by pressing a key (or perhaps a specific key combination).
However, I’m unsure if there is a scripting function that allows for console interaction without the user being logged in.
So far, the adjustments I’ve considered are:
Instead of triggering the reboot immediately, I could call a 60-second :delay (or a loop of 10 iterations with a 6-second :delay) and wait for console interaction to halt the reboot. I even considered something like:
"If the interface used for booting changes status during this time, abort the pending reboot and continue operating as is."
But I found that a bit crude and too susceptible to external interference.
I would still prefer a "Press Ctrl+Lambda to avoid next reboot!"
You could do the reboot in another script (called from the initial script) and then when it loops you can quickly disable that script during the delay time.
This particular case happened after updating over 50 units for a client. Notably, 12 of those units—including one of each model present in the fleet—had already been updated manually and individually the day after the CVE fix was released.
The update for the remaining 50+ units was carried out via remote commands using an automation tool.
When one of them failed to come back online, we investigated what had happened.
Off-topic: I suspect something might have gone wrong due to flash memory wear on a CCR2004—even though the configurations had been carefully reviewed to minimize unnecessary flash writes.
So... Calm Down.
Not everyone suffers from "scripted-finger-sexuality syndrome:
"Where you insert a script and f*** everything up."
Preamble:
RouterBOOT (BIOS) and RouterOS (software) are not the same thing.
A wise administrator leaves the same version of RouterOS everywhere.
And new versions aren't used until after months of testing.
Updating the BIOS is impossible if the factory firmware is later.
For example, if RouterOS is 7.19.1 and the factory firmware is 7.20.2,
there's no point in the system trying to update the current firmware
(and in fact it doesn't even try, the problem would be the script that tries to do it).
If someone was really stupid, he would proceed in this way, on scheduler:
Check if the next, freshly released, client-crashing version of RouterOS is available.
If is not available, stop here the script, else:
Set auto-upgrade=yes regardlessly if already is =yes (why not?)
Create a scheduler that start at next reboot after 60 seconds with just only :execute "<SET HERE INSTRUCTION TO DELETE THE SCHEDULER HERE>;/sys reboot"
Update it instantly, without even reading the forum if there are any problems (But everything is perfect, so why do it?).
On reboot, it reboot again, without the risk of it being blocked by the scheduler, but for everything else...
But it doesn't answer the question in the topic title:
Whether it is possible, using MikroTik scripting, to wait for console interaction and take action based on it.
In general, no, because the console is not the controlling TTY for the script.
You could have (should have) inserted extra code in the script to allow it to skip the reboot, but you did not.
When you put "reboot" in /etc/rc.local on a Linux machine you will face a similar situation... but there you could escape it by booting in "single use mode" or by booting from a different device. Well, you can do that on MikroTik devices as well, that is what "netinstall" does.
Now, I'm a person who doesn't know where modesty lies, obviously,
but I've never dared to pass myself off as an expert in something I don't know well...
You know how shi~~y embarrassing it would be?
But I assure you, this time it's simple.
For example, the script waits for a system variable to be set to value "X" before continuing the script.
So until someone "manually" sets the variable to "X". nothing happens.
Or another:
The device do NOT reboot, if all ether ports are empty...
@fischerdouglas, as @rextended mentioned - self deleting/disabling scheduler is safe solution in this case. I have (for some different case) need to execute on startup scheduled script once until next time is manually enabled, such script disables startup scheduler which executes it.
If "disabled" you must include a :delay, otherwise the operation occasionally fails to commit to the SQL3 database and the machine reboots with the operation cached and no applied.
However, if you delete it, I've never had it reappear...
Never tried with restart, my script doesn't restart ROS, just disables startup scheduler so that is not executed on next boot (whenever it happens).
This means, as you wrote, any configuration change prior reboot requires delayed reboot? It seems that ROS doesn't reboot gracefully is such is the case. Not including containers here, I have script for graceful ROS reboot which stops all running containers and waits until all are stopped before runs system reboot command.
I'm only talking about disabling the scheduler just before rebooting.
On customer machines (CPEs), there are no containers or other things to stop first for safety.
As for containers, I have no experience with them.
I think stopping containers doesn't do any config change so there can be no issue regarding config DB commit when rebooting immediately after. But I did experienced issues in containers when I performed ROS (some older versions) reboots before stopping containers so in that purpose I created such script for ROS rebooting. (sry for OT)
PS
I figured out what you mean here, that sheduler is locking own configuration change until is finished because it writes next run interval (even if startup time doesn't have it) when finished, never thought that is transactional...
It surprises me a little that reboot is apparently so harsh that it does not commit all config changes. After all any RouterOS upgrade is also done in the reboot procedure. Maybe a good idea to report a bug so they can add some synchronization inside reboot.