Come continuare uno script dopo aver riavviato il computer?


18

Sto scrivendo una shell script in bash. Ad un certo punto dello script, rileva che è necessario riavviare la macchina prima di continuare. Emette:

sudo reboot

Quando la macchina torna indietro, c'è più lavoro che questo script deve fare. Come configuro qualcosa per continuare a fare il lavoro in questo script?

Suppongo che ci sia un posto in cui posso scrivere uno script di shell in modo che venga eseguito al prossimo riavvio. Dov'è un posto simile? Vedo che cron ha una direttiva @reboot. So anche che servizi come Apache vengono avviati all'avvio da upstart. Uno di questi sarebbe meccanismi adeguati? In tal caso, come verrebbe attivato?

Questo script deve essere eseguito solo una volta, non tutti i riavvii. Quindi dovrà andare da qualche parte che viene eseguito al prossimo riavvio, o essere in grado di rimuovere se stesso una volta che è stato eseguito.

Questa domanda chiede come salvare lo stato dell'applicazione per dopo il riavvio. La mia sceneggiatura non ha molto stato, quindi posso gestirla. Devo solo sapere come fare in modo che questo script attivi qualcosa da eseguire dopo il prossimo riavvio.

La mia versione specifica è Ubuntu Linux 14.04. Lo script originale viene avviato dalla riga di comando da un amministratore di sistema (invece di essere eseguito da cron).


Un riavvio all'interno di uno script deve essere utilizzato solo se NON PUOI evitarlo. Ad esempio una nuova installazione del kernel. Sono sicuro che puoi fare il tuo lavoro senza riavviare. Puoi specificare perché è necessario il riavvio?
caos,

1
Questo script installa un nuovo kernel (o piuttosto chiama apt upgrade che potrebbe farlo). Controlla anche se è effettivamente necessario un riavvio prima di eseguire il riavvio.
Stephen Ostermiller,

"Un riavvio all'interno di uno script deve essere utilizzato solo se NON PUOI evitarlo." - @chaos Perché?
John Red,

Risposte:


16

Su un sistema, l'unica cosa veramente persistente è un file. È praticamente quello che dovresti usare. Ecco una soluzione che utilizza uno script init.d.

Consideriamo il seguente script (semplice), /etc/init.d/myupdate:

#! /bin/sh

### BEGIN INIT INFO
# Provides:          myupdate
### END INIT INFO

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

case "$1" in
    start)
        /path/to/update/script
        ;;
    stop|restart|reload)
        ;;
esac

Se lo attivi con update-rc.d myupdate defaults, l' startazione verrà eseguita all'avvio. Ora, quando lo script di aggiornamento richiede un riavvio:

touch /var/run/rebooting-for-updates
sudo reboot

Con questa soluzione, puoi dividere lo script di aggiornamento in due parti:

before_reboot(){
    # Do stuff
}

after_reboot(){
    # Do stuff
}

if [ -f /var/run/rebooting-for-updates ]; then
    after_reboot
    rm /var/run/rebooting-for-updates
    update-rc.d myupdate remove
else
    before_reboot
    touch /var/run/rebooting-for-updates
    update-rc.d myupdate defaults
    sudo reboot
fi

Eseguirà la before_rebootsezione del codice, creerà un file /var/rune si riavvierà. All'avvio, lo script verrà richiamato di nuovo, ma poiché il file esiste, after_rebootverrà chiamato invece di before_reboot.

Si noti che update-rc.drichiede i privilegi di root.

Senza usare un file (dal commento di Stephen Ostermiller ):

Se si ha familiarità con l' getoptsutilità, è possibile utilizzare le opzioni anziché i file. Nello script init, chiama lo script con:

/path/to/update/script -r

E nel tuo script, controlla le opzioni anziché i file. Chiama lo script una volta senza l'opzione e init.d lo richiamerà nuovamente all'avvio, questa volta con -r.

# Set AFTER_REBOOT according to options (-r).

if [ "x$AFTER_REBOOT" = "xyes" ]; then
    # After reboot
else
    # Before reboot
fi

Ulteriori informazioni sulla gestione delle opzioni sono disponibili qui (solo per opzioni brevi) . Ho anche modificato la mia sceneggiatura con le chiamate per update-rc.dmantenere questo lavoro una tantum (da un altro commento).


2
Potrebbe essere più semplice per chiamare /path/to/update/script --after-rebootda /etc/init.d/myupdatepiuttosto che fare affidamento sulla presenza di /var/run/rebooting-for-updates. Quindi avrebbe argomenti diversi quando eseguito direttamente vs chiamato all'avvio.
Stephen Ostermiller,

Bello, non pensavo alle opzioni. Consentitemi di modificare;)
John WH Smith,

1
Inoltre, dal momento che è un lavoro una tantum, probabilmente vorrei aggiungere il update-rc.d myupdate defaultse update-rc.d myupdate removenello script stesso, così come la scrittura e la rimozione in /etc/init.d/myupdatemodo che non lasci i file in giro.
Stephen Ostermiller,

Ho implementato questo e funziona bene. L'unica altra cosa che aggiungerò è che il mio sistema basato su Debian richiede elementi aggiuntivi nella INIT INFOsezione: wiki.debian.org/LSBInitScripts
Stephen Ostermiller

Volevo davvero mantenerlo semplice;) Scrivere il vero init.d richiede un po 'di tempo, ma sono contento che tu abbia cercato ulteriori informazioni: questi script possono essere molto utili.
John WH Smith,
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.