Debian - wie man ein Skript beim Start ausführt, sobald eine Internetverbindung zur Verfügung steht?

13

Ich verwende Debian 7 Wheezy und muss beim Start einige Bildschirme starten, sobald eine voll funktionsfähige Internetverbindung besteht. Allerdings nicht, wenn die Internetverbindung unterbrochen und wieder hergestellt wurde. Also erst bei der ersten funktionierenden Internetverbindung nach dem Booten.

Könnten Sie bitte ein Dummy-Skript dazu posten und mir mitteilen, wo es abgelegt und unter den gegebenen Bedingungen ausgeführt werden soll?

Das Skript muss nur den Bildschirm starten und dann beenden, der Bildschirm sollte jedoch fortgesetzt werden.


BEARBEITEN Ich habe schon von dem /etc/network/if-up.d/Ordner gehört. Aber wie kann ich sicherstellen, dass das Skript nicht erneut ausgeführt wird, wenn die Internetverbindung unterbrochen und dann wieder hergestellt wird?

MinecraftShamrock
quelle
@ Celada siehe bitte die Bearbeitung
MinecraftShamrock

Antworten:

20

Fügen Sie Ihr Skript ein /etc/network/if-up.dund machen Sie es ausführbar. Es wird bei jedem Aufrufen einer Netzwerkschnittstelle automatisch ausgeführt.

Damit es nur beim ersten Start funktioniert, müssen Sie prüfen, ob eine Flag-Datei vorhanden ist, die Sie nach dem ersten Start erstellt haben. Beispiel:

#!/bin/sh

FLAGFILE=/var/run/work-was-already-done

case "$IFACE" in
    lo)
        # The loopback interface does not count.
        # only run when some other interface comes up
        exit 0
        ;;
    *)
        ;;
esac

if [ -e $FLAGFILE ]; then
    exit 0
else
    touch $FLAGFILE
fi

: here, do the real work.
Celada
quelle
Wird die Flagdatei gelöscht, wenn der Server heruntergefahren wird?
MinecraftShamrock
1
Ja, denn unter Debian /var/rungibt es ein flüchtiges Dateisystem (a tmpfs). So bleibt es bei jedem neuen Schuh garantiert leer.
Celada
1
Guter Fang. Ich denke, Sie müssten wirklich Pech haben, aber ich denke ja, wegen der Hot-Plug-Schnittstellen, die gleichzeitig aufgerufen werden könnten. Du kannst das also atomar machen, anstatt erst zu testen und dann zu erstellen, was es sicher macht, aber was ich mir auf den Kopf gestellt habe, ist nicht schön! python -c 'import os; os.open("/var/run/work-was-already-done", os.O_EXCL|os.O_CREAT, 0)' 2>/dev/null || exit 0
Celada
3
@MinecraftShamrock Wenn Sie Celadas Skript unverändert verwenden, wird Ihr Code ausgeführt, sobald die Loopback-Schnittstelle aufgerufen wird. Wenn Sie auf die Internetverbindung warten möchten, überprüfen Sie zumindest, ob dies IFACEkeine looder eine virtuelle Schnittstelle ist. Testen Sie die Internetverbindung, indem Sie einen Ping-Befehl senden.
Gilles 'SO- hör auf böse zu sein'
1
@MinecraftShamrock $IFACEkann als Werte jede Schnittstelle haben, die auftaucht. Sie können alle Schnittstellen auflisten, die vorhanden sind, ip linkoder überprüfen, welche für das Scannen konfiguriert sind/etc/network/interfaces
Celada
8

Dies ist ein Job, für den er sehr gut geeignet ist systemd.

Ausführen eines Skripts als systemd-Dienst

Wenn auf Ihrem System systemd ausgeführt wird , können Sie Ihr Skript so konfigurieren, dass es als systemd-Dienst ausgeführt wird, der die Kontrolle über die Lebenszyklus- und Ausführungsumgebung sowie die Voraussetzungen für den Start des Skripts bietet, z. B., dass das Netzwerk aktiv ist.

Der empfohlene Ordner für Ihre eigenen Dienste ist /etc/systemd/system/(eine andere Option ist /lib/systemd/systemjedoch, dass diese normalerweise nur für OOTB-Dienste verwendet werden sollte).

Erstellen Sie die Datei zB mit sudo vim /etc/systemd/system/autossh.service:

[Unit]
# By default 'simple' is used, see also https://www.freedesktop.org/software/systemd/man/systemd.service.html#Type=
# Type=simple|forking|oneshot|dbus|notify|idle
Description=Autossh keepalive daemon
## make sure we only start the service after network is up
Wants=network-online.target
After=network.target

[Service]
## here we can set custom environment variables
Environment=AUTOSSH_GATETIME=0
Environment=AUTOSSH_PORT=0
ExecStart=/usr/local/bin/ssh-keep-alive.sh
ExecStop=pkill -9 autossh
# don't use 'nobody' if your script needs to access user files
# (if User is not set the service will run as root)
#User=nobody

# Useful during debugging; remove it once the service is working
StandardOutput=console

[Install]
WantedBy=multi-user.target

Jetzt können Sie den Service testen:

sudo systemctl start autossh

Überprüfen des Status des Dienstes:

systemctl status autossh

Beenden des Dienstes:

sudo systemctl stop autossh

Sobald Sie überprüft haben, dass der Dienst wie erwartet funktioniert, aktivieren Sie ihn mit:

sudo systemctl enable autossh

ANMERKUNG: Aus Sicherheitsgründen systemdwird das Skript in einer eingeschränkten Umgebung ausgeführt, ähnlich wie crontabSkripte ausgeführt werden. Nehmen Sie daher keine Annahmen über bereits vorhandene Systemvariablen wie $ PATH vor. Verwenden Sie die EnvironmentTasten, wenn für Ihr Skript bestimmte Variablen definiert werden müssen. Wenn set -xSie das Bash-Skript oben hinzufügen und dann ausführen, können Sie systemctl status my_servicemöglicherweise feststellen, warum das Skript fehlschlägt. Verwenden Sie in der Regel immer absolute Pfade für alles, einschließlich echo, oder definieren Sie Ihren $ PATH explizit, indem Sie hinzufügen Environment=MYVAR=abc.

ccpizza
quelle
2

Die Internetverbindung wird durch einen Eintrag in /etc/rc6.d/vermutlich hergestellt S35networking. Wenn Sie diese Datei ändern und Ihre Befehle am Ende einfügen oder besser a /etc/init.d/mystuffund einen Link hinzufügen und /etc/rc0.d/S36mystuffIhre Befehle dort einfügen, wird dies gestartet, sobald das Netzwerk aktiv ist.

Anthon
quelle
Wird es aufgerufen, wenn die Verbindung unterbrochen und dann wiederhergestellt wird? Denn sonst könnte ich das Drehbuch einfach in/etc/network/if-up.d
MinecraftShamrock
Nein, dies ist nur beim Start
Anthon
1
Das wird funktionieren, aber nur aus Gründen der Korrektheit möchte ich darauf hinweisen, dass /etc/rc0.dbeim Start kein Skript ausgeführt wird. Diese werden beim Herunterfahren ausgeführt (Run Level 0). Beim Start wäre es etwas in /etc/rc2.doder ähnlich. Speziell für das Debian-Keuchen des OP ist es /etc/rcS.d/S12networking. Das alles verlinkt natürlich auf dieselbe Datei. Auch BTW @Anthon danke für die Behebung meiner Antwort: "Bitte" statt "Put"? Was für ein seltsamer Tippfehler!
Celada
@Celada Du hast Recht, es ist RC6 auf meinem (Nicht-Debian-System). Ich war mir nicht sicher, ob Sie "Bitte setzen" wollten, aber nur "Setzen" schien knuspriger zu sein. Übrigens, ich habe Ihre Antwort positiv bewertet, es ist nur ein besserer Ansatz für die Vernetzung, da dieser if-up.dals generischer Mechanismus auch bei einer erneuten Verbindung funktioniert.
Anthon