Eseguire un comando prima dell'arresto


52

Voglio eseguire un semplice comando appena prima che il computer si spenga (il tempismo non è essenziale).

Per l'avvio, posso usare /etc/rc.local; c'è qualcosa di simile per lo spegnimento?

Nota che vorrei ancora utilizzare il pulsante di spegnimento integrato dal menu; cioè non voglio usare uno script personalizzato ogni volta che mi chiudo tramite terminale - deve essere automatico.

Risposte:


42

Linux Mint si basa su Ubuntu, quindi immagino che il sistema runlevel sia probabilmente lo stesso. Su Ubuntu, gli script per i diversi runlevel vengono eseguiti in base alla loro presenza nelle /etc/rc[0-6].ddirectory. Il runlevel 0 corrisponde allo spegnimento e 6 al riavvio.

In genere lo script stesso viene archiviato /etc/init.de quindi i collegamenti simbolici vengono inseriti nelle directory corrispondenti ai runlevel richiesti.

Quindi, nel tuo caso, scrivi il tuo script, memorizzalo in /etc/init.d/, quindi crea un link simbolico in ciascuno di ( /etc/rc0.de /etc/rc6.dse vuoi entrambi) che punta al tuo script.

Gli script in ciascuna directory del runlevel verranno eseguiti in ordine asciibetico , quindi se l'ordine all'interno del runlevel è importante per te, scegli il nome del tuo link simbolico di conseguenza.


Ho appena dato un'occhiata al file skeleton in init.d (kubuntu preciso) e mi sono un po 'intimidito. Voglio solo aggiungere un paio di comandi che fanno eco alla data di arresto in un file in / var / log. Posso semplicemente farlo o devo affrontare alcune delle altre cose nel file scheletro?
Joe,

2
@Joe - Non hai bisogno della maggior parte di queste cose se non vuoi che il tuo script sia controllabile come servizio standard. Non romperai nulla con una semplice eco nel tuo file di registro, quindi provalo e vedi.
ire_and_curses,

1
Ecco un semplice script init.d di esempio. Inoltre, è più facile e più robusto creare i symlink usandosudo update-rc.d /etc/init.d/myservice defaults
RolfBly

Ho scritto /etc/init.d/spark_shutdown.sh e creato il collegamento di in /etc/rc0.d & /etc/rc6.d ora come posso confermare che questo script è stato eseguito nell'istanza ubuntu aws ec2
Ashish Karpe

10

Ora che le varianti di Ubuntu e Mint sono passate a systemd ho trovato le mie vecchie soluzioni basate su quelle precedenti meno soddisfacenti. Ho cercato sul Web per scoprire come farlo con systemd e ho finito per combinare la saggezza degli altri e documentarlo come post di blog su blogspot.com.au contenente il seguente tutorial.

Con systemd crei uno o due file per chiamare i tuoi script utilizzando i modelli seguenti ed esegui un paio di comandi. Semplice.


Versione GUI

Innanzitutto creare gli script che si desidera eseguire all'avvio e / o allo spegnimento. Ho creato .scopening_atstart e .scfullcopy_atend.

Quindi assicurati che siano entrambi eseguibili facendo clic con il pulsante destro del mouse sul file, selezionando le proprietà e assicurandoti che, sotto le autorizzazioni, hai selezionato Consenti l'esecuzione del file come programma.

I due file che ho creato popolano e salvano il contenuto di un ramdisk. Inoltre creano un file nella mia home directory per dimostrare che il servizio funziona. Erano della forma:

#!/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

Quindi ho aperto il mio file manager come root, ho aperto /etc/systemd/systeme creato un file startup.service e un file save-ramdisk.service. Ovviamente puoi scegliere i tuoi nomi e nomi generici potrebbero aver incluso un file di avvio chiamato johns_start.service e un file di arresto chiamato johns_shutdown.service. Basta non scegliere i nomi dei servizi esistenti.

[Unit]
Description=Startup Applications

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

[Install]
WantedBy=multi-user.target

e

[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

Puoi usare gli stessi file di servizio, sostituendo il mio percorso completo con lo script eseguibile.

Infine per ognuno eseguire il comando systemctl abilita your_files_name (ma senza il servizio suffisso). Quindi il mio primo è statosystemctl enable startup

Riavvia il computer una volta per avviare i servizi. Il servizio di avvio verrà eseguito ogni volta che systemd entra nella destinazione multiutente e il servizio di arresto quando esce dalla destinazione multiutente. Di seguito verranno descritti file di servizio alternativi con condizioni di attivazione diverse.


Versione CLI (riga di comando)

Questa descrizione presuppone che tu operi dalla tua directory home piuttosto che / home / john, usi sudo secondo necessità e la tua scelta dell'editor dove scrivo vim o svim.

Crea script shell di avvio e spegnimento con la prima riga #!/bin/she rendili eseguibili usando chmod +x my_new_filename.

Creare due file come sopra o, in questo esempio, un file per gestire le attività di avvio e arresto. Eseguirò gli script nella mia directory home ma @don_crissti mostra alcune alternative a Stack Exchange .

vim /etc/systemd/system/start_and_stop.service

e copia nel contenuto del file:

[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

Quindi abilitare il servizio con il comando:

systemctl enable start_and_stop

e riavviare il sistema dopo il quale i servizi saranno attivi. I comandi systemctl is-enabled start_and_stope systemctl is-active start_and_stoppossono essere utilizzati nel monitoraggio dei nuovi servizi.


Modifica delle condizioni di trigger per l'arresto

I file utilizzano soprattutto l'apertura o la chiusura dell'ambiente multiutente per avviare l'esecuzione degli script. Il file seguente utilizza l'inizio di quattro potenziali processi di arresto per avviare i suoi script. L'aggiunta o la rimozione dei target nella riga Prima + la riga WantedBy ti consentirà di fare distinzioni più precise:

Questo file è stato proposto nella seconda risposta di questo post ma non sono stato in grado di farlo funzionare fino a quando non ho aggiunto una sezione di installazione.

Ancora una volta, modifica lo script /etc/systemd/service/e abilitalo usando systemctl enable your_file_name. Quando ho cambiato le destinazioni ho usato il systemclt disable file_namecomando e poi l'ho riattivato, che lo collegava alle directory di destinazione. Riavvia e il servizio sarà operativo.

[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

7

È necessario utilizzare rc.shutdownlo script di arresto per il kernel Linux. Citando la pagina man di OpenBSD :

Quando il sistema viene spento usando i comandi reboot (8) o halt (8), o quando viene segnalato init (8) per farlo, o quando viene emessa una fermata richiesta dalla tastiera (se l'architettura lo supporta), rc ( 8) viene invocato con l'argomento `` shutdown ''.

Quindi, apri semplicemente il tuo rc.shutdown e aggiungi qualsiasi comando shell che desideri eseguire su di esso.

AGGIORNAMENTO: Dal momento che Linux Mint si basa su Ubuntu, che ha una diversa procedura di avvio / arresto, ecco la procedura che ti interessa:

Scrivi lo script della shell che desideri eseguire e copialo nella relativa directory nel tuo /etc/rc*.d/. I *corrisponde al runlevel in cui si desidera lo script da eseguire.
Ubuntu segue la numerazione del runlevel Debian, quindi hai runlevel 0 per halt e runlevel 6 per il riavvio.


1

Per i sistemi init basati sulla dipendenza SysV usati in Debian Wheezy, Devuan e suoi derivati ​​e forse altri, puoi imitare il comportamento rc.shutdowndell'analogico rc.localcome il seguente:

Aggiungi i tuoi comandi al seguente scheletro di /etc/rc.shutdown:

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

# <add your commands here, before exit 0>

exit 0

Salvare lo script e rendere eseguibile il file chmod a+x /etc/rc.shutdown.

Quindi, aggiungi un nuovo script /etc/init.d/rc.shutdownal tuo sistema con il seguente contenuto:

#! /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

Rendi anche questo script eseguibile.

Creare i collegamenti simbolici in /etc/rc[06[.d:

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

e

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

Utilizzare insservper correggere i collegamenti simbolici e per creare i file .depend.boot, .depend.start e .depend.stop necessari:

insserv -v

Devi essere root o usare sudo per tutti i comandi sopra menzionati.


Ho perso tempo con questo per un po 'oggi e non sono riuscito a farlo funzionare con Ubuntu 16, forse sono stato io ma la soluzione sopra ha funzionato immediatamente.
Mike Q
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.