Wie fahre ich einen Linux-Server herunter, nachdem ich ihn 60 Minuten lang ausgeführt habe?

18

Ich habe einen Server, der aus Sicherheitsgründen normalerweise ausgeschaltet ist. Wenn ich daran arbeiten möchte, schalte ich es ein, führe meine Aufgaben aus und fahre es wieder herunter. Meine Aufgaben dauern in der Regel nicht länger als 15 Minuten. Ich möchte einen Mechanismus implementieren, der es nach 60 Minuten automatisch herunterfährt.

Ich habe nachgeforscht, wie das mit cron geht, aber ich glaube nicht, dass dies der richtige Weg ist, da cron nicht berücksichtigt, wann der Server das letzte Mal eingeschaltet wurde. Ich kann nur periodische Muster festlegen, aber diese berücksichtigen diese Daten nicht.

Wie könnte ich diese Implementierung durchführen?

jmhostalet
quelle
4
Schauen Sie sich an at(einmalige Ausführung).
Dirkt
14
Ich habe dies nicht getan, aber Ihr Anmeldeskript könnte einen sudo shutdown -h +60starten, der einen Countdown-Zähler von 60 Minuten für den Herunterfahren (-halt) -Prozess startet. Wenn du es abbrechen willst, kannst du sudo shutdown -c (das benutzt zwar kein Cron)
guiverc
7
Abhängig von der Art Ihrer Aufgaben lohnt es sich möglicherweise, sie in einem Docker-Container auszuführen, damit Sie sich nicht um das Ausschalten eines Servers kümmern müssen. Der Container wird erstellt, Ihre Aufgaben ausgeführt und anschließend zerstört.
Vicente Olivert Riera
6
Erwarten Sie keinen wirklichen Sicherheitsvorteil. Die meisten Sicherheitsanfälligkeiten können in weniger als einer Sekunde ausgenutzt werden, sodass ein Herunterfahren nach einer Stunde die Ausnutzung nicht verhindert. Ein Angreifer, der eine Sicherheitsanfälligkeit gefunden hat, kann warten, bis Sie den Computer eingeschaltet haben, um den Angriff auszuführen.
Kasperd
2
Betreff: Bei @kasperds Kommentar würde ich sagen, dass Sie auf Ihrem Server genau die gleiche Sicherheitsstufe benötigen, unabhängig davon, wie viel oder wenig der Server tatsächlich online ist. Beachten Sie, dass es sich um einen Server handelt, der mit etwas verbunden ist, und das bedeutet , dass beim Einschalten etwas bekannt ist. Automatisierte Sweeps sind nicht das, worüber Sie sich Gedanken machen, es sind Verbindungen jeglicher Art, und Sie können dies nicht vermeiden der einzige Weg.
StephenG

Antworten:

23

Wenn Sie Ihre Aufgaben jedes Mal als derselbe Benutzer ausführen, können Sie einfach den Befehl shutdown (optional mit der Option -P) zu Ihrem Profil hinzufügen. Die Zahl steht für die Anzahl der Minuten, um die der Befehl zum Herunterfahren verzögert wird. Stellen Sie sicher, dass Ihr Benutzer den Befehl shutdown über sudo ohne Kennwort ausführen kann.

echo "sudo shutdown -P +60" >> ~/.profile
Dirk Krijgsman
quelle
11
Die Zeit ist in Minuten und nicht in Sekunden. Try shutdown -k -P 3600vs shutdown -k -P 60( -kdruckt die Nachricht an der Wand, hat aber keine andere Wirkung)
2.
12
Probieren Sie den Befehl jedoch zuerst einmal aus. Sie möchten nicht, dass ein sofortiges Herunterfahren an Ihr Profil gebunden wird!
Fabian Röling
17
Ich stelle mir vor, jedes SSH-Login würde einen neuen Aufruf zum Herunterfahren auslösen. Würde der Zähler dann zurückgesetzt?
JoL
4
Es kann auch erwähnenswert sein, dass in den letzten 5 Minuten keine Anmeldungen möglich sind, wie in der Hilfeseite zum Herunterfahren angegeben.
JoL
6
Beachten Sie, dass 60 Minuten nach der Anmeldung nicht mit 60 Minuten nach dem Start identisch sind. Was passiert, wenn Sie den Computer booten und dann vergessen, sich anzumelden?
Hagen von Eitzen
69

Es gibt mehrere Möglichkeiten.

  • Geben Sie Ihre Zeit direkt an shutdown -P:

    shutdown -P +60
    

    Beachten Sie, dass die shutdown Manpage auch Folgendes hervorhebt:

    Wenn das Argument time verwendet wird, wird 5 Minuten vor dem Systemausfall die Datei / run / nologin erstellt, um sicherzustellen, dass keine weiteren Anmeldungen zulässig sind.

  • Verwenden atBefehl.

  • Erstellen Sie eine System-Unit-Datei oder ein Init-Skript, das shutdown -P 60beim Start ausgeführt wird.

  • Verwenden Sie cron's @reboot, um den Befehl nach dem Booten auszuführen.

    Zu (root) crontab hinzufügen:

    @reboot shutdown -P +60
    

Bei den letzten beiden Methoden können Sie auch sleep 3600 && shutdown -P nowanstelle des Zeitarguments verwenden shutdown, um das Herunterfahren um 60 Minuten zu verzögern. Auf diese Weise sind Anmeldungen bis zum letzten Moment vor dem Herunterfahren möglich.

sebasth
quelle
2
Ich denke, mit dem sleepBefehl müssen Sie noch eine Zeit angeben, bis shutdown- wir würden nowfür dieses Argument verwenden, wenn wir bereits gewartet haben (aber beachten Sie, dass Sie nicht sehr gewarnt werden, wenn Sie Ihre Arbeit davor speichern verschwindet unter dir!).
Toby Speight
1
Obwohl es shutdown -P 60funktioniert, ist es nicht die Art und Weise, wie der Befehl aufgerufen werden sollte. Laut der Manpage solltest du verwenden shutdown -P +60. --- Auch das Herunterfahren ohne Zeitargument (im Beispiel sleep 3600 && shutdown -P) wird um eine Minute verzögert (like shutdown -P +1). Wie Toby Speight schrieb, würden Sie wahrscheinlich verwenden wollen shutdown -P now.
Pabouk
34

Das sieht nach einem XY-Problem aus .

Meine Aufgaben dauern in der Regel nicht länger als 15 Minuten. Ich möchte einen Mechanismus implementieren, der es nach 60 Minuten automatisch herunterfährt.

Wenn Sie nach 60 Minuten herunterfahren, besteht die Gefahr, dass Sie ein besonders kompliziertes Problem haben und einfach mehr Zeit benötigen. Viele der vorherigen Lösungen würden es nicht leicht machen, das Herunterfahren zu verzögern.

Wenn es sich bei der Aufgabe nicht um eine interaktive Aufgabe handelt, sondern um eine Skriptaufgabe, die automatisch von einem anderen Computer ausgelöst wird, hat @sdkks eine hervorragende Lösung für diese Aufgabe gefunden . Sie sollten der Maschine einfach die Aufgabe erteilen, das Ausschalten auszuführen, sobald das Skript und alle seine Aufgaben abgeschlossen sind.

Wenn es sich bei Ihrer Aufgabe jedoch um eine interaktive Aufgabe handelt, würde ich vorschlagen, stattdessen die Leerlauferkennung durchzuführen.

Wenn Sie Ihre Aufgabe in einer GUI (X11) ausführen, können Sie die inaktiven GUI-Sitzungen anhand des hier beschriebenen Ansatzes erkennen: Führen Sie einen Befehl aus, wenn das System inaktiv ist und wenn es wieder aktiv ist

Wenn Sie die Aufgabe über ein Terminal ausführen, können Sie mit dem whoBefehl angemeldete Benutzer erkennen . Sie können einen Cronjob einrichten, der den Computer herunterfährt, wenn whoein leeres Ergebnis zurückgegeben wird. Beachten Sie, dass dies ein recht konservativer Ansatz ist. Das System wird nicht heruntergefahren, wenn Sie die Konsole angeschlossen haben, sondern im Leerlauf.

Wenn Sie aggressiver sein und auch inaktive Terminalsitzungen trennen möchten, können Sie den vorherigen Ansatz mit dem automatischen Trennen inaktiver SSH-Sitzungen ClientAliveInterval und kombinieren ClientAliveCountMax. Ein anderer Ansatz für diesen Fall, wenn Sie nicht über SSH, sondern über eine lokale Terminalsitzung verfügen, besteht darin, die vom Befehl zurückgegebene Leerlaufzeit des Terminals zu verwenden w.

Lüge Ryan
quelle
2
Dies ist ein sehr wichtiger Punkt. Was auch immer Sie implementieren - es liegt in Ihrem Interesse, sicherzustellen, dass Sie das Herunterfahren auch abbrechen können .
Schatten
1
Etwas ist schief gelaufen, wenn es immer noch auf 60 m läuft, also fang einfach wieder von vorne an. Dies kann Cloud-bezogen sehr teuer sein. Wenn ich nicht sicher war, dass ich einmal heruntergefahren wurde, bekam ich mehr als 4.000 US-Dollar zurück.
McKenzm
8

Die vorherigen Antworten hier erfüllen zwar alle die Anforderung nach Perfektion, Sie können die Maschine jedoch auch ausschalten, sobald die Aufgaben erledigt sind.

bashSkripte können trapped sein, was bedeutet, dass bestimmte Signale abgefangen und bestimmte Aufgaben bei Bedarf ausgeführt werden können. EXITist eines der Signale, die abgefangen werden können.

Sie könnten:

  1. Legen Sie ein trapfür EXITIhre automatisierten Shell-Skripte fest, was bedeutet, dass Ihre automatisierten Aufgaben beendet werden
  2. Legen Sie einen Wert trapfür fest .bashrc EXIT, dh schalten Sie den Computer aus, wenn Sie sich von diesem Computer abmelden.

Option 1 wäre der ideale Fall, vorausgesetzt, Ihre Aufgaben erfordern keine Ad-hoc-Prüfung und manuelle Beurteilung.

Option 2 würde die Fälle abdecken, in denen Sie vergessen würden, das Terminal zu verlassen, ohne es auszuschalten. Es gibt jedoch eine Einschränkung; Wenn mehrere Terminals für dasselbe Gerät geöffnet sind und Sie eines verlassen, wird das Gerät trotzdem ausgeschaltet. (Es kann ein Skript erstellt werden, um dies zu vermeiden, aber ich werde die Lösung nicht komplizieren.)

cleanup(){
    # Do some tasks before terminating
    echo oh la la, cleaning is so nice
    echo "See you later, world"
    sudo poweroff & # finally shutdown
}
trap cleanup EXIT

Dies kann am Ende von .bashrcOption 2 sein, an einer Stelle am oberen Rand Ihres Skripts für Option 1.

Warum nicht poweroffam Ende des Skripts verwenden?

Ich bevorzuge es, set -eo pipefailoben in meinen Skripten zu verwenden. Wenn ein Fehler auftritt, schlägt dieser nicht unbemerkt fehl. Es werden keine weiteren Befehle mehr ausgeführt. trapof EXITsignal sollte die Fälle abdecken, in denen das Skript aufgrund von Fehlern vorzeitig beendet wird.

Für Ihre Aufgaben kann dies jedoch auch bedeuten, dass die Maschine heruntergefahren wird, bevor sie abgeschlossen sind.

Ich verwende eine einfache bashVorlage, um das Debuggen von Skripten zu vereinfachen. Vielleicht könnte es von Nutzen sein. Bitte sehen Sie diesen Kern .

sdkks
quelle
Einverstanden, und um sicher zu sein, vielleicht eine Tageszeit Herunterfahren von Cron. Das ist eine Totmannsbremse.
McKenzm
@Abigail für das Skript muss oben stehen, da .bashrcich den Boden vorziehen würde, falls etwas anderes ihn überschreibt. Ihr Anliegen scheint nicht klar zu sein. Können Sie vielleicht ein Beispiel-Snippet auf repl.it veröffentlichen?
SDKKS
@mckenzm verstehe ich nicht. Können Sie Beispielcode oder mehr Erklärung teilen?
SDKKS
5

Wenn Sie auf @dirkt comment eingehen, können Sie einen atBefehl in Ihre .bashrcoder eine beliebige .profileDatei einfügen, die Ihre Shell bei der Anmeldung verwendet, um ein automatisches Herunterfahren 60 Minuten nach Ihrer Anmeldung zu planen.

Etwas wie:

at now + 60 minutes -f /sbin/halt
Herr Shunz
quelle
Diese Aufgabe steht an at. Sie können auch atAufgaben in/var/spool/
sdkks
5
Ich würde atin diesem Zusammenhang davon abraten, da es Neustarts übersteht. Wenn sich OP anmelden, manuell herunterfahren und sich dann innerhalb einer Stunde erneut anmelden würde, würde er vor Ablauf einer Stunde nach seiner letzten Anmeldung beim ersten geplanten Herunterfahren gestartet.
Aaron
@ Aaron das stimmt. Daran habe ich nicht gedacht. Die Boot-Persistenz ist eine Einschränkung für diese Lösung.
SDKKS
5

Der folgende Befehl wird commandmit Parametern ausgeführt. Wenn der Vorgang erfolgreich abgeschlossen wurde, wird das Kontrollkästchen sofort deaktiviert, sofern der Benutzer ausgeführt werden kann poweroff. Es muss möglicherweise verwendet werden sudo poweroff.

command --parameters && poweroff

Während der folgende einfach poweroffsofort ausgeführt wird, wenn der Befehl beendet wird:

command --parameters ; poweroff

Wenn Sie der Meinung sind, dass der Befehl nach Abschluss eine Ruhezeit benötigt, führen Sie ihn aus

command --parameters ; sleep 3600 ; poweroff

Wenn Sie glauben, dass der Befehl über die Zeit hinaus ausgeführt wird, können Sie ihn auf eine Stunde beschränken:

timeout 1h command --parameters ; poweroff

timeoutist Teil des coreutilsPakets, also haben Sie es wahrscheinlich bereits.

Criggie
quelle
3

Wenn Sie sich wirklich Sorgen um die Sicherheit machen, verwenden Sie einen mechanischen Auslasstimer an der Stromquelle. Stellen Sie einfach die Zeit ein, zu der das System heruntergefahren werden soll. Auf diese Weise kann sich niemand remote anmelden und das Herunterfahren deaktivieren. Sie benötigen physischen Zugang.

Gogatoren
quelle
2
Beschädigung des Dateisystems?
Xen2050
@ Xen2050 Kein Problem mit einem modernen (Journaling-) Dateisystem.
Tom
1
@Tom Haben Sie eine Quelle für erzwungene Umounts, die niemals zu einer Beschädigung des Dateisystems führen, wenn es Journaling gibt? Klingt neu für mich, ich würde es gerne nachlesen. Zumindest muss es das Dateisystem als schmutzig markieren und ein fsck erzwingen, oder?
Xen2050
1
In den meisten Fällen sollte das Journal nur noch einmal abgespielt und fertig sein. Ein Herunterfahren sollte keine Beschädigung des Dateisystems auf einem aufgezeichneten Dateisystem verursachen. Es gibt jedoch keine Garantien, es sei denn, Sie verwenden ein Dateisystem wie ZFS, das speziell für diesen Fall entwickelt wurde.
Tom
1
Die Journalwiedergabe kann fehlschlagen - ich hatte vor ein paar Wochen eine sehr schwierige fsck-Sitzung, nachdem eine Maschine ohne USV für eine halbe Sekunde vom Stromnetz getrennt worden war. Das benutzte ext4 mit einem Tagebuch; es ist nicht völlig unbesiegbar!
Toby Speight
2

Wenn Sie sich in einer systemdMaschine befinden, können Sie einen monotonen Timer verwenden

Die Timer-Einheit /etc/systemd/system/shutdown_after_an_hour.timer

[Unit]
Description=shutdown after an hour

[Timer]
OnBootSec=1h

[Install]
WantedBy=timers.target

Die Timer-Einheit /etc/systemd/system/shutdown_after_an_hour.service:

[Unit]
Description=shutdown after an hour

[Service]
ExecStart=/sbin/poweroff --force --no-wall
Type=oneshot

Es wird über aktiviert

# systemctl enable shutdown_after_an_hour.timer

Sein Status (insbesondere wie viel Zeit bis zum Herunterfahren verbleibt) ist über verfügbar

# systemctl list-timers shutdown_after_an_hour.timer

Es wird beim nächsten Neustart funktionieren, es ist systemctl startwährend der Sitzung, in der es erstellt wird, nicht nützlich, da es entweder nicht funktioniert (weil es beim Neustart nicht ausgelöst wurde) oder den Computer sofort herunterfährt, wenn es länger als eine Stunde dauert. Ich weiß nicht, welches tatsächlich passieren wird, ich habe diesen speziellen Fall nie getestet.

WoJ
quelle
1

Versuchen Sie, das Skript ( sudo shutdown -P 3600) im /etc/init.dVerzeichnis abzulegen, damit es beim Start automatisch ausgeführt wird.

Oder versuchen Sie es mit anacron, indem Sie den Befehl in die /etc/anacrontabDatei einfügen. Ich schlage auch vor, nohupvor dem Befehl zu verwenden, um sicherzustellen, dass der Befehl nach dem Abmelden noch funktioniert.

Saveriofr
quelle
1
Abhängig von der Distribution wird es möglicherweise nicht ausgeführt, wenn
Sie sich
@sdkks, du hast recht. Anacron kann ebenfalls in Betracht gezogen werden. Legen Sie das Skript in / etc / anacrontab ab, das im Falle einer Abmeldung auch mit 'nohup' verwendet wird.
Saveriofr
1
@Saveriofr Sie können Ihre Antwort bearbeiten , um ihre Qualität zu verbessern (besser als das Posten zusätzlicher Informationen als Kommentar).
Anthony G - Gerechtigkeit für Monica
1

Nutzen Sie die Logout-Datei Ihrer Shell

Wenn Sie den Server nur für interaktive oder nicht interaktive Aufgaben benötigen, die von Ihrer UID gestartet werden, sollten Sie Ihre Befehle zum Herunterfahren in Ihre Datei ~ / .bash_logout einfügen . Das GNU Bash Manual sagt:

Wenn eine interaktive Anmeldeshell beendet wird oder eine nicht interaktive Anmeldeshell den eingebauten Befehl exit ausführt, liest Bash Befehle aus der Datei ~ / .bash_logout und führt sie aus, falls vorhanden.

Wenn Sie also "sudo poweroff" oder ähnliches zu Ihrer Abmeldedatei hinzufügen, wird der Server ausgeschaltet , sobald Sie sich von Ihrer aktuellen Sitzung abmelden oder wenn eine nicht interaktive Bash-Sitzung aufgerufen wird exit. Sie könnten auch verwenden wählen zu oder eine Zeitverzögerung passieren Abschaltung , wenn Sie die Abschaltung verschieben würden es vorziehen.

Um dies interaktiver zu gestalten, können Sie die folgenden Bashisms in Ihre Logout-Datei einfügen:

# Shutdown unless N or n is pressed within 30 seconds.
shopt -s nocasematch
read -t 30 -N 1 -p 'Shutdown now? (Y/n) '
[[ "$REPLY" =~ n ]] || sudo poweroff

Vorbehalte

Es gibt einige Einschränkungen, die Sie bei dieser Lösung beachten sollten:

  • Dies wird wahrscheinlich sogar unter einem von X Windows gestarteten Terminal funktionieren, würde aber wahrscheinlich nicht für eine X11-Sitzung funktionieren, die nicht von startxoder ähnlich gestartet wurde .
  • Wenn Sie über nicht interaktive Skripts verfügen, die aufgerufen werden exit, kann es zu unerwarteten Herunterfahren kommen.
  • In Ihrer sudoers-Datei werden Sie möglicherweise zur Eingabe eines Kennworts aufgefordert, wenn Sie die NOPASSWDBefehle zum Herunterfahren nicht angegeben oder sudo -vvor dem Ausführen des Befehls zum Herunterfahren nicht angerufen haben .
  • Es gibt wahrscheinlich andere Randfälle, an die ich noch nicht gedacht habe.

Kurz gesagt, möchten Sie vielleicht überlegen, ob dieser Ansatz Ihren tatsächlichen Anforderungen entspricht oder ob ein völlig anderer Ansatz wie die Überwachung auf Abwesenheit angemeldeter Benutzer oder eine andere Alternative besser geeignet ist. Ihr Kilometerstand wird auf jeden Fall variieren.

CodeGnome
quelle