Jak kontynuować skrypt po ponownym uruchomieniu komputera?


18

Piszę skrypt powłoki w bash. W pewnym momencie skryptu wykrywa, że ​​komputer musi zostać ponownie uruchomiony przed kontynuowaniem. Wydaje:

sudo reboot

Po powrocie komputera ten skrypt musi wykonać więcej pracy. Jak skonfigurować coś, aby kontynuować pracę w tym skrypcie?

Zakładam, że jest miejsce, w którym mogę napisać skrypt powłoki, który zostanie wykonany przy następnym restarcie. Gdzie jest takie miejsce? Widzę, że cron ma dyrektywę @reboot. Wiem też, że usługi takie jak Apache są uruchamiane przy starcie przez upstart. Czy któryś z tych mechanizmów byłby odpowiedni? Jeśli tak, w jaki sposób zostałby uruchomiony?

Ten skrypt musi zostać uruchomiony tylko raz, nie przy każdym ponownym uruchomieniu. Więc będzie musiał iść gdzieś, który po prostu uruchomi się przy następnym restarcie lub będzie w stanie usunąć się po uruchomieniu.

To pytanie dotyczy sposobu zapisania stanu aplikacji po ponownym uruchomieniu. Mój skrypt nie ma wiele stanów, więc mogę sobie z tym poradzić. Muszę tylko wiedzieć, jak uruchomić ten skrypt, aby uruchomił się po następnym restarcie.

Moja konkretna wersja to Ubuntu Linux 14.04. Oryginalny skrypt jest uruchamiany w wierszu poleceń przez administratora systemu (w przeciwieństwie do uruchamiania z crona).


Ponowne uruchomienie w skrypcie powinno być stosowane tylko wtedy, gdy NIE MOŻESZ tego uniknąć. Na przykład nowa instalacja jądra. Jestem pewien, że możesz wykonać swoją pracę bez restartu. Czy możesz określić, dlaczego potrzebujesz ponownego uruchomienia?
chaos

1
Ten skrypt instaluje nowe jądro (a raczej wywołuje apt upgrade, który może to zrobić). Sprawdza również, czy ponowne uruchomienie jest rzeczywiście potrzebne przed ponownym uruchomieniem.
Stephen Ostermiller

„Ponowne uruchomienie w skrypcie powinno być stosowane tylko wtedy, gdy NIE MOŻESZ tego uniknąć”. - @chaos Dlaczego?
John Red,

Odpowiedzi:


16

W systemie jedyną rzeczą, która jest naprawdę trwała, jest plik. Właśnie tego powinieneś użyć. Oto rozwiązanie za pomocą skryptu init.d.

Rozważmy następujący (prosty) skrypt /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

Jeśli go aktywujesz update-rc.d myupdate defaults, startakcja zostanie wykonana podczas rozruchu. Teraz, gdy skrypt aktualizacji wymaga ponownego uruchomienia:

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

Dzięki temu rozwiązaniu możesz podzielić skrypt aktualizacji na dwie części:

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

Wykona before_rebootsekcję kodu, utworzy plik /var/runi uruchomi się ponownie. Po uruchomieniu skrypt zostanie ponownie wywołany, ale ponieważ plik istnieje, after_rebootzostanie wywołany zamiast before_reboot.

Uwaga: update-rc.dwymaga uprawnień roota.

Bez użycia pliku (z komentarza Stephena Ostermillera ):

Jeśli znasz getoptsnarzędzie, możesz użyć opcji zamiast plików. W skrypcie init wywołaj skrypt za pomocą:

/path/to/update/script -r

W skrypcie sprawdź opcje zamiast plików. Zadzwoń do skryptu jeden raz bez opcji, a init.d wywoła go ponownie przy starcie, tym razem z -r.

# Set AFTER_REBOOT according to options (-r).

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

Więcej informacji na temat obsługi opcji znajduje się tutaj (tylko w przypadku krótkich opcji) . Zredagowałem też mój skrypt z wezwaniami, aby update-rc.dzachować to jednorazową pracę (z innego komentarza).


2
To może być prostsze zadzwonić /path/to/update/script --after-rebootze /etc/init.d/myupdatezamiast polegać na obecności /var/run/rebooting-for-updates. Wtedy miałby inne argumenty, gdy był uruchamiany bezpośrednio vs wywoływany podczas rozruchu.
Stephen Ostermiller

Fajny, nie myślałem o opcjach. Pozwól mi edytować;)
John WH Smith

1
Ponadto, ponieważ jest to jednorazowe zadanie, prawdopodobnie chciałbym dodać update-rc.d myupdate defaultsi update-rc.d myupdate removedo samego skryptu, a także pisać i usuwać, /etc/init.d/myupdateaby nie pozostawiać plików w miejscu.
Stephen Ostermiller

Zaimplementowałem to i działa dobrze. Dodam tylko, że mój system oparty na Debianie wymaga dodatkowych elementów w INIT INFOsekcji: wiki.debian.org/LSBInitScripts
Stephen Ostermiller

Naprawdę chciałem to uprościć;) Napisanie odpowiedniego init.d zajmuje trochę czasu, ale cieszę się, że poszedłeś po więcej informacji: te skrypty mogą się przydać.
John WH Smith,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.