Führen Sie vor dem Herunterfahren einen Befehl aus

52

Ich möchte einen einfachen Befehl ausführen, bevor der Computer heruntergefahren wird (Timing ist nicht unbedingt erforderlich).

Zum Starten kann ich /etc/rc.local verwenden; Gibt es etwas Ähnliches für das Herunterfahren?

Beachten Sie, dass ich weiterhin die integrierte Schaltfläche zum Herunterfahren aus dem Menü verwenden möchte. dh ich möchte nicht jedes Mal ein benutzerdefiniertes Skript verwenden, wenn ich über das Terminal herunterfahre - es muss automatisch ablaufen.

Primož Kralj
quelle

Antworten:

42

Linux Mint basiert auf Ubuntu, daher schätze ich, dass das Runlevel-System wahrscheinlich dasselbe ist. Unter Ubuntu werden Skripte für die verschiedenen Runlevel entsprechend ihrer Präsenz in den /etc/rc[0-6].dVerzeichnissen ausgeführt. Runlevel 0 entspricht dem Herunterfahren und 6 dem Neustart.

In der Regel wird das Skript selbst in gespeichert. /etc/init.dAnschließend werden Symlinks in den Verzeichnissen abgelegt , die den von Ihnen benötigten Runleveln entsprechen.

Schreiben Sie also in Ihrem Fall Ihr Skript, speichern Sie es in /etc/init.d/, und erstellen Sie dann in jedem Skript einen Symlink, /etc/rc0.dund /etc/rc6.d(wenn Sie beide möchten) verweisen Sie auf Ihr Skript.

Die Skripte in jedem Runlevel-Verzeichnis werden in einer bestimmten Reihenfolge ausgeführt. Wenn die Reihenfolge innerhalb des Runlevels für Sie relevant ist , wählen Sie den Namen Ihres Symlinks entsprechend aus.

ire_and_curses
quelle
Ich habe mir nur die Skelettdatei in init.d (kubuntu precision) angesehen und mich ein wenig einschüchtern lassen. Ich möchte nur ein paar Befehle hinzufügen, die das Datum des Herunterfahrens in einer Datei unter / var / log wiedergeben. Kann ich das einfach machen oder muss ich mich um einige der anderen Dinge in der Skelettdatei kümmern?
Joe
2
@Joe - Sie brauchen das meiste nicht, es sei denn, Sie möchten, dass Ihr Skript als Standarddienst steuerbar ist. Sie werden nichts mit einem einfachen Echo auf Ihre eigene Protokolldatei brechen, also versuchen Sie es und sehen Sie.
ire_and_curses
1
Hier ist ein einfaches Beispiel für ein init.d-Skript. Außerdem ist es einfacher und robuster, die Symlinks mitsudo update-rc.d /etc/init.d/myservice defaults
RolfBly
Ich habe /etc/init.d/spark_shutdown.sh geschrieben und Link in /etc/rc0.d erstellt und /etc/rc6.d jetzt Wie bestätige ich dieses Skript lief in ubuntu aws EC2 - Instanz
Ashish Karpe
10

Nachdem die Ubuntu-Varianten und Mint zu systemd gewechselt sind, stellte ich fest, dass meine alten Lösungen, die auf den oben genannten basieren, weniger zufriedenstellend sind. Ich suchte im Internet, um herauszufinden, wie man es mit systemd macht, und kombinierte schließlich die Weisheit anderer und dokumentierte es als Blog-Post auf blogspot.com.au mit dem folgenden Tutorial.

Mit systemd erstellen Sie eine oder zwei Dateien, um Ihre Skripte mithilfe der folgenden Vorlagen aufzurufen, und führen einige Befehle aus. Einfach.


GUI-Version

Erstellen Sie zuerst die Skripte, die Sie beim Starten und / oder Herunterfahren ausführen möchten. Ich habe .scopening_atstart und .scfullcopy_atend erstellt.

Stellen Sie dann sicher, dass beide Programme ausführbar sind, indem Sie mit der rechten Maustaste auf die Datei klicken, Eigenschaften auswählen und sicherstellen, dass Sie unter Berechtigungen die Option Datei als Programm ausführen lassen ausgewählt haben.

Die beiden von mir erstellten Dateien füllen und speichern den Inhalt einer Ramdisk. Sie erstellen auch eine Datei in meinem Home-Verzeichnis, um zu beweisen, dass der Dienst funktioniert. Sie waren von der Form:

#!/bin/sh
cp -pru /home/john/zRamdisk/subdirectory1/* /home/john/.wine/drive_c/subdirectory1/
rm /home/john/stop_time
date +%D' '%T > /home/john/stop_time

Dann habe ich meinen Dateimanager als root geöffnet /etc/systemd/systemund eine Datei startup.service und eine Datei save-ramdisk.service erstellt. Natürlich können Sie Ihre eigenen Namen auswählen, und generische Namen können eine Startdatei mit dem Namen johns_start.service und eine Datei zum Herunterfahren mit dem Namen johns_shutdown.service enthalten. Wählen Sie einfach keine vorhandenen Dienstnamen aus.

[Unit]
Description=Startup Applications

[Service]
Type=oneshot
RemainAfterExit=false
ExecStart=/home/john/.scopening_atstart

[Install]
WantedBy=multi-user.target

und

[Unit]
Description=Save Ramdisk to Wine drive C

[Service]
Type=oneshot
RemainAfterExit=true
ExecStart=/bin/true
ExecStop=/home/john/.scfullcopy_atend

[Install]
WantedBy=multi-user.target

Sie können dieselben Dienstdateien verwenden und meinen durch den vollständigen Pfad Ihres ausführbaren Skripts ersetzen.

Führen Sie zum Schluss für jeden Befehl den Befehl systemctl enable your_files_name aus (jedoch ohne den Suffix-Dienst). Also war mein erstersystemctl enable startup

Starten Sie den Computer einmal neu, um die Dienste zu starten. Der Startdienst wird immer dann ausgeführt, wenn systemd in das Mehrbenutzerziel eintritt, und der Stoppdienst, wenn es das Mehrbenutzerziel verlässt. Alternative Servicedateien mit unterschiedlichen Aktivierungsbedingungen werden unten beschrieben.


CLI (Command Line) Version

In dieser Beschreibung wird davon ausgegangen, dass Sie von Ihrem Home-Verzeichnis aus und nicht von / home / john aus arbeiten, sudo nach Bedarf verwenden und den Editor auswählen, in dem ich vim oder svim schreibe.

Erstellen Sie in der ersten Zeile Shell-Skripte zum Starten und Herunterfahren #!/bin/shund machen Sie sie mit ausführbar chmod +x my_new_filename.

Erstellen Sie zwei Dateien wie oben oder in diesem Beispiel eine Datei, um Start- und Herunterfahraufgaben zu erledigen. Ich werde Skripte in meinem Home-Verzeichnis ausführen, aber @don_crissti zeigt einige Alternativen bei Stack Exchange .

vim /etc/systemd/system/start_and_stop.service

und in den Dateiinhalt kopieren:

[Unit]
Description=Run Scripts at Start and Stop

[Service]
Type=oneshot
RemainAfterExit=true
ExecStart=/home/john/.startup_commands  #your paths and filenames
ExecStop=/home/john/.shutdown_commands

[Install]
WantedBy=multi-user.target

Aktivieren Sie dann den Dienst mit dem Befehl:

systemctl enable start_and_stop

und starten Sie Ihr System neu, wonach die Dienste aktiv sind. Die Befehle systemctl is-enabled start_and_stopund systemctl is-active start_and_stopkönnen zur Überwachung Ihrer neuen Dienste verwendet werden.


Ändern der Auslösebedingungen für das Herunterfahren

Die Dateien verwenden vor allem das Öffnen oder Schließen der Mehrbenutzerumgebung, um die Ausführung der Skripte einzuleiten. Die folgende Datei verwendet den Anfang von vier möglichen Herunterfahrprozessen, um die Skripte zu starten. Durch Hinzufügen oder Entfernen der Ziele in der Vorher-Zeile + der WantedBy-Zeile können Sie feinere Unterscheidungen treffen:

Diese Datei wurde in der zweiten Antwort dieses Beitrags vorgeschlagen , konnte jedoch erst ausgeführt werden, nachdem ich einen Installationsabschnitt hinzugefügt hatte.

Bearbeiten Sie das Skript erneut in /etc/systemd/service/und aktivieren Sie es mit systemctl enable your_file_name. Als ich die Ziele geändert habe, habe ich den systemclt disable file_nameBefehl verwendet und wieder aktiviert, wodurch er mit den Zielverzeichnissen verknüpft wurde. Starten Sie neu und der Dienst wird ausgeführt.

[Unit]
Description=Do something required
DefaultDependencies=no
Before=shutdown.target reboot.target halt.target
# This works because it is installed in the target and will be
#   executed before the target state is entered
# Also consider kexec.target

[Service]
Type=oneshot
ExecStart=/home/john/.my_script  #your path and filename

[Install]
WantedBy=halt.target reboot.target shutdown.target
John 9631
quelle
7

Sie müssen rc.shutdowndas Shutdown-Skript für den Linux-Kernel verwenden. Zitieren der OpenBSD-Manpage :

Wenn das System mit den Befehlen reboot (8) oder halt (8) heruntergefahren wird oder wenn init (8) dazu aufgefordert wird oder wenn ein von der Tastatur angeforderter Halt ausgegeben wird (sofern die Architektur dies unterstützt), wird rc ( 8) wird mit dem Argument `` shutdown '' aufgerufen.

Sie öffnen also einfach Ihre rc.shutdown und fügen alle Shell-Befehle hinzu, die Sie ausführen möchten.

UPDATE: Da Linux Mint auf Ubuntu basiert, das ein anderes Verfahren zum Starten / Herunterfahren hat, ist das folgende Verfahren für Sie relevant:

Schreiben Sie das Shell - Skript, das Sie ausführen möchten, und kopieren Sie es in das entsprechende Verzeichnis in Ihrem /etc/rc*.d/. Das *entspricht dem Runlevel, auf dem das Skript ausgeführt werden soll.
Ubuntu folgt der Debian-Runlevel-Nummerierung, so dass Sie Runlevel 0 für halt und Runlevel 6 für den Neustart haben.

verdammt
quelle
1

Für SysV-abhängigkeitsbasierte Init-Systeme, die in Debian Wheezy, Devuan und seinen Derivaten und möglicherweise anderen verwendet werden, können Sie das Verhalten von rc.shutdownAnalog nachahmen, um rc.localFolgendes zu tun :

Fügen Sie Ihre Befehle dem folgenden Grundgerüst hinzu /etc/rc.shutdown:

#!/bin/sh -e
#
# rc.shutdown
#

# <add your commands here, before exit 0>

exit 0

Speichern Sie das Skript und machen Sie die Datei mit ausführbar chmod a+x /etc/rc.shutdown.

Fügen Sie /etc/init.d/rc.shutdowndann Ihrem System ein neues Skript mit folgendem Inhalt hinzu:

#! /bin/sh
### BEGIN INIT INFO
# Provides:          rc.shutdown
# Required-Start:
# Required-Stop:
# X-Stop-After:      umountroot
# Default-Start:
# Default-Stop:      0 6
# Short-Description: Run /etc/rc.shutdown if it exist
### END INIT INFO


PATH=/sbin:/usr/sbin:/bin:/usr/bin

. /lib/init/vars.sh
. /lib/lsb/init-functions

do_stop() {
    if [ -x /etc/rc.shutdown ]; then
            [ "$VERBOSE" != no ] && log_begin_msg "Running local shutdown scripts (/etc/rc.shutdown)"
        /etc/rc.shutdown
        ES=$?
        [ "$VERBOSE" != no ] && log_end_msg $ES
        return $ES
    fi
}

case "$1" in
    start)
        # No-op
        ;;
    restart|reload|force-reload)
        echo "Error: argument '$1' not supported" >&2
        exit 3
        ;;
    stop|status)
    do_stop
        exit 0
        ;;
    *)
        echo "Usage: $0 start|stop" >&2
        exit 3
        ;;
esac

Machen Sie dieses Skript auch ausführbar.

Erstellen Sie die Symlinks in /etc/rc[06).d:

cd /etc/rc0.d ; ln -s ../init.d/rc.shutdown K01rc.shutdown

und

cd /etc/rc6.d ; ln -s ../init.d/rc.shutdown K01rc.shutdown

Verwenden insservSie diese Option, um die Symlinks zu korrigieren und die erforderlichen .depend.boot-, .depend.start- und .depend.stop-Dateien zu erstellen:

insserv -v

Sie müssen root sein oder sudo für alle oben genannten Befehle verwenden.

Adrian Zaugg
quelle
Ich habe heute meine Zeit damit verschwendet und konnte es nicht mit Ubuntu 16 zum Laufen bringen. Vielleicht war ich es, aber die Lösung oben hat sofort funktioniert.
Mike Q