Safe-Mode für MikroTik-Router nutzen

Bei der Konfiguration eines MikroTik-Routers kann es immer mal wieder passieren, dass der Nutzer eine falsche Konfiguration hinterlegt und sich im schlimmsten Fall aus dem Gerät aussperrt oder die Konnektivität des Gerätes verloren geht. Das wird durch den Umstand erschwert, dass die Konfiguration immer sofort umgesetzt wird. Allerdings gibt es für diesen Fall eine Lösung, den sogenannten Safe-Mode. Nach eine Verbindung per SSH hergestellt wurde:

ssh admin@192.168.1.1

kann der Safe-Mode mittels der Tastenkombination Ctrl + X aktiviert werden. Der Prompt im Terminal ändert sich daraufhin:

[admin@192.168.1.1] <SAFE>

Alle Befehle, welche nun eingegeben werden, sind sofort wirksam, allerdings kann jederzeit zum Stand zurückgekehrt werden, als der Safe-Mode aktiviert wurde. Sollen die Änderungen, welche im Safe-Mode getätigt wurden, übernommen werden, so muss erneut Ctrl + X gedrückt werden. Damit wird der Safe-Mode deaktiviert und die Änderungen werden übernommen.

Sollen die Änderungen hingegen nicht aktiviert werden, so sollte das Terminal mittels Ctrl + D verlassen werden. Nach der Beendigung der Verbindung und dem entsprechenden Timeout (bei TCP in etwa neun Minuten) werden die im Safe-Mode gemachten Änderungen rückgängig gemacht.

ExecutorService unter Java nutzen

Wenn unter Java die Ausführung von Quelltext parallelisiert werden soll, so können hierfür Threads genutzt werden:

Thread thread = new Thread(new TestRunnable());
thread.start();

In diesem Beispiel wird für eine auszuführende Aufgabe ein Thread erstellt und dieser anschließend gestartet. Nun kann es Fälle geben, in welchem mehrere Threads die gleiche Aufgabe ausführen sollen, allerdings nicht unbedingt die entsprechende Anzahl von Threads angelegt werden soll. Für eine solche Aufgabe eignet sich ein ExecutorService. Im ersten Schritt sollte ein Runnable definiert werden. In diesem Interface wird eine run-Methode definiert, die den auszuführenden Quellcode enthält:

public static class TestRunnable implements Runnable {

    @Override
    public void run() {
        // Do something
    }
}

Nun kann der ExecutorService angelegt werden und mit einem Threadpool ausgestattet werden. Anschließend werden die neuen Instanzen des Runnable, mittels der execute-Methode, an den ExecutorService übergeben.

// Executor service
ExecutorService executorService = Executors.newCachedThreadPool();

// Add jobs to executor service
for (int i = 0; i < 100; i++) {
    executorService.execute(new TestRunnable());
}

// Shutdown executor service
executorService.shutdown();
executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);

Damit würden die Aufgaben abgearbeitet. Allerdings würde der ExecutorService nun bis zu einem Timeout noch bestehen bleiben. Stattdessen wird er im Beispiel kontrolliert heruntergefahren. Nach der Ausführung der shutdown-Methode nimmt der ExecutorService keine neuen Aufträge mehr an; bestehende Aufträge werden allerdings noch abgearbeitet. Über die Methode awaitTermination wird sichergestellt das der Service wartet, bis alle Aufgaben abgearbeitet sind. Bei der Methode wird ein Timeout angegeben, nach welchem der Service zwangsweise abgeschaltet wird. Damit werden die Aufgaben Stück für Stück abgearbeitet, ohne entsprechende viele Threads zu öffnen. Stattdessen werden Threads aus dem Threadpool wiederverwendet.