
Ich möchte einen Befehl so planen, dass er zu einem bestimmten Zeitpunkt ausgeführt wird, der durch einen Unix-Zeitstempel identifiziert wird. Es scheint, als wäre dies mit systemd mithilfe von möglich systemd-run
, aber wie würde das funktionieren? Und was würde mit dem geplanten Befehl passieren, wenn die Maschine zum Zeitpunkt der Planung des Befehls ausgeschaltet oder angehalten wird?
Verwandte Frage: Dasselbe mit „ at
von“ tun atd
(dazu muss der Zeitstempel wieder in ein Datum umgewandelt werden):Ist es möglich, mit dem Befehl „at“ die Ausführung eines Jobs zu einem bestimmten Zeitstempel zu planen?
Antwort1
systemd-run
Sie können einen Befehl so planen, dass er zu einem bestimmten Zeitpunkt ausgeführt wird.so lange wie:
- Das System wird nicht vor diesem Zeitpunkt heruntergefahren, da es eine temporäre Timer- und Servicedatei in /run schreibt, die beim Neustart gelöscht wird.
- Das System wird während dieser bestimmten Zeit nicht angehalten, es sei denn, Sie verwenden die Option „WakeSystem“ (siehe unten).
Eine Option zum dauerhaften Neustart finden Sie weiter unten.
Ein einfaches Beispiel für systemd-run
:
# generate an arbitrary timestamp, in seconds-since-the-epoch
timestamp=$(date -d 'now + 42 seconds' +%s)
systemd-run --on-calendar "$(date -d @"$timestamp" +'%F %T')" \
--timer-property=AccuracySec=1us \
touch /tmp/done
Die wichtigen Teile für die systemd-run
Verwendung eines Zeitstempels „Sekunden seit der Epoche“ sind:
- zu verwenden
--on-calendar
und - hier wird GNU date verwendet, um den Zeitstempel der Sekunden seit der Epoche in ein Format umzuwandeln, das
systemd-run
es versteht. Sie können den Zeitstempel selbst eingeben oder konvertieren, solange das Ergebnis in einemFormat, das OnCalendar versteht.
Die aktuelle Dokumentation für OnCalendar gibt an, dass es die Eingabe in einem Sekunden-seit-der-Epoche-Zeitstempel direkt unterstützt. Diese '@seconds'-Unterstützung wurde hinzugefügt insystemd Version 234(suchen Sie auf dieser Seite nach der Datei src/basic/calendarspec.c
) inbegehen d80e5b7. Ihre Version von systemd ist möglicherweise älter als diese Änderung. Beispiele:
- RHEL 7 begann mit systemd 208 und wurde später auf Version 219 aktualisiert; RHEL 8 verwendet Version 239 (Referenz).
- Debian 8 verwendete Version 215, Debian 9 verwendete Version 232 und Debian 10 verwendet Version 241 (Referenz).
- Ubuntu 16.04 LTS hatte Version 229, Ubuntu 17.10 hatte Version 234 und Ubuntu 18.04 LTS hatte Version 237 (Referenz).
Mit einer ausreichend neuen Version von systemd könnten Sie diesen Aufruf verwenden:
timestamp=$(date -d 'now + 42 seconds' +%s)
systemd-run --on-calendar "@${timestamp}" \
--timer-property=AccuracySec=1us \
touch /tmp/done
Ich habe auch gezeigt,Timer-Eigenschaft von AccuracySec, der standardmäßig auf 1 Minute eingestellt ist und dessen Wert Sie basierend auf der Dokumentation anpassen sollten:
Um den Stromverbrauch zu optimieren, stellen Sie diesen Wert so hoch wie möglich und so niedrig wie nötig ein.
Ich habe es nicht getestet, aber es gibt auch eine Timer-Option namens „, WakeSystem
die Folgendes tun würde:
bewirkt, dass das System aus dem Ruhezustand wieder aufgenommen wird, falls es in den Ruhezustand versetzt wurde und das System dies unterstützt. Beachten Sie, dass diese Option nur sicherstellt, dass das System zu den entsprechenden Zeiten wieder aufgenommen wird. Sie kümmert sich nicht darum, es erneut in den Ruhezustand zu versetzen, nachdem die auszuführende Arbeit abgeschlossen ist.
Sie würden es in das Obige folgendermaßen integrieren:
timestamp=$(date -d 'now + 42 seconds' +%s)
systemd-run --on-calendar "$(date -d @"$timestamp" +'%F %T')" \
--timer-property=AccuracySec=1us \
--timer-property=WakeSystem=true \
touch /tmp/done
Um systemd aufzufordern, einen Befehl zu einer bestimmten Zeit auszuführen, und zwar auf eine Weise, diebleibt über einen Neustart hinaus bestehen, und das unabhängig von einer bestimmten Anmeldesitzung ist, müssten Sie Timer- und Service-Unit-Dateien unter platzieren /etc/systemd/system/
./etc/systemd/system ist der Ort, an dem die lokale Konfiguration gespeichert istfür systemd.
Ein Beispiel für eine Timerdatei wäre:
[Timer]
AccuracySec=1us
[Unit]
Description=2020-01-22 09:50:00 timer
[Timer]
OnCalendar=2020-01-22 09:50:00
und eine Beispiel-Servicedatei wäre:
[Unit]
Description=my 2020-01-22 09:50:00 service
[Service]
ExecStart=
ExecStart=@/usr/bin/bash "/usr/bin/bash" "-c" "echo 2020-01-22 09:50:00 timer and service ran > /tmp/done"
Anschließend würden Sie systemd über die Dateien informieren, indem Sie es neu laden:
systemctl daemon-reload
... und anschließend den Timer aktivieren:
systemctl enable foo.timer
... und anschließend den Timer starten:
systemctl start foo.timer
Möglicherweise möchten Sie abgelaufene Timer und Service-Einheiten regelmäßig aus /etc/systemd/system entfernen, sobald ihre Zeit abgelaufen ist.