Bagaimana melanjutkan skrip setelah reboot mesin?

18

Saya sedang menulis skrip shell di bash. Pada titik tertentu dalam skrip, ia mendeteksi bahwa mesin perlu di-boot ulang sebelum melanjutkan. Ini masalah:

sudo reboot

Ketika mesin muncul kembali, ada lebih banyak pekerjaan yang perlu dilakukan skrip ini. Bagaimana cara mengkonfigurasi sesuatu untuk terus melakukan pekerjaan dalam skrip ini?

Saya berasumsi bahwa ada beberapa tempat yang bisa saya tuliskan skrip shell sehingga akan dieksekusi pada reboot berikutnya. Di mana tempat seperti itu? Saya melihat bahwa cron memiliki arahan @reboot. Saya juga tahu bahwa layanan seperti Apache dimulai saat boot oleh pemula. Apakah salah satu dari itu mekanisme yang tepat? Jika demikian, bagaimana hal itu dipicu?

Script ini hanya perlu dijalankan sekali, tidak setiap reboot. Jadi itu harus pergi ke suatu tempat yang hanya berjalan pada reboot berikutnya, atau dapat menghapus sendiri setelah dijalankan.

Pertanyaan ini menanyakan tentang bagaimana cara menyimpan status aplikasi Anda setelah reboot. Skrip saya tidak memiliki banyak status, jadi saya dapat mengaturnya. Saya hanya perlu tahu bagaimana agar skrip ini memicu sesuatu untuk dijalankan setelah reboot berikutnya.

Versi spesifik saya adalah Ubuntu Linux 14.04. Skrip asli dimulai pada baris perintah oleh administrator sistem (bukan menjalankan dari cron).

Stephen Ostermiller
sumber
Reboot dalam skrip seharusnya hanya digunakan jika Anda TIDAK BISA menghindarinya. Misalnya instalasi kernel baru. Saya yakin Anda dapat melakukan pekerjaan Anda tanpa reboot. Bisakah Anda menentukan mengapa Anda perlu reboot?
kekacauan
1
Skrip ini menginstal kernel baru (atau lebih tepatnya memanggil pembaruan apt yang mungkin melakukannya). Itu juga memeriksa juga melihat apakah reboot benar-benar diperlukan sebelum melakukan reboot.
Stephen Ostermiller
"Sebuah reboot dalam sebuah skrip seharusnya hanya digunakan jika Anda TIDAK BISA menghindarinya." - @chaos Kenapa?
John Red

Jawaban:

16

Pada suatu sistem, satu-satunya hal yang benar-benar persisten adalah file. Cukup banyak yang harus Anda gunakan. Inilah solusi menggunakan skrip init.d.

Mari kita mempertimbangkan (sederhana) script berikut, /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

Jika Anda mengaktifkannya dengan update-rc.d myupdate defaults, starttindakan akan dieksekusi saat boot. Sekarang, ketika skrip pembaruan Anda memanggil untuk reboot:

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

Dengan solusi ini, Anda dapat membagi skrip pembaruan Anda menjadi dua bagian:

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

Ini akan menjalankan bagian before_rebootkode, membuat file /var/run, dan reboot. Saat boot, skrip akan dipanggil lagi, tetapi karena file ada, after_rebootakan dipanggil bukan before_reboot.

Catat itu update-rc.d membutuhkan hak akses root.

Tanpa menggunakan file (dari Stephen Ostermiller ):

Jika Anda terbiasa dengan getoptsutilitas, Anda mungkin ingin menggunakan opsi, bukan file. Di skrip init, panggil skrip dengan:

/path/to/update/script -r

Dan dalam skrip Anda, periksa opsi bukan file. Panggil skrip Anda satu kali tanpa opsi, dan init.d akan memanggilnya lagi saat boot, kali ini dengan -r.

# Set AFTER_REBOOT according to options (-r).

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

Anda akan menemukan informasi lebih lanjut tentang penanganan opsi di sini (hanya untuk opsi singkat) . Saya juga mengedit skrip saya dengan panggilan update-rc.duntuk menjadikan ini pekerjaan satu kali (dari komentar lain).

John WH Smith
sumber
2
Mungkin sederhana untuk memanggil /path/to/update/script --after-rebootdari /etc/init.d/myupdatedaripada mengandalkan kehadiran /var/run/rebooting-for-updates. Maka itu akan memiliki argumen yang berbeda ketika dijalankan secara langsung vs dipanggil saat boot.
Stephen Ostermiller
Bagus, tidak memikirkan opsi. Izinkan saya mengedit;)
John WH Smith
1
Juga, karena ini adalah pekerjaan satu kali, saya mungkin ingin menambahkan update-rc.d myupdate defaultsdan update-rc.d myupdate removeke dalam skrip itu sendiri, serta penulisan dan penghapusan /etc/init.d/myupdatesehingga tidak meninggalkan file duduk-duduk.
Stephen Ostermiller
Saya sudah menerapkan ini dan berfungsi dengan baik. Satu-satunya hal lain yang akan saya tambahkan adalah bahwa sistem saya berbasis Debian memerlukan item tambahan di INIT INFObagian: wiki.debian.org/LSBInitScripts
Stephen Ostermiller
Saya benar-benar ingin membuatnya tetap sederhana;) Menulis init yang tepat. Butuh sedikit waktu, namun saya senang Anda mencari informasi lebih lanjut: skrip ini bisa sangat berguna.
John WH Smith