Як продовжити сценарій після перезавантаження машини?


18

Я пишу сценарій оболонки в баш. У якийсь момент сценарію він виявляє, що машину потрібно перезавантажити, перш ніж продовжувати. Він видає:

sudo reboot

Коли машина повертається вперед, цьому сценарію потрібно виконати більше роботи. Як налаштувати щось, щоб продовжувати виконувати роботу в цьому сценарії?

Я припускаю, що є якесь місце, де я можу написати сценарій оболонки таким чином, що він буде виконаний при наступному перезавантаженні. Де таке місце? Я бачу, що у cron є директива @reboot. Я також знаю, що такі сервіси, як Apache, запускаються під час завантаження. Чи був би один із цих механізмів відповідним механізмом? Якщо так, як би це було викликано?

Цей сценарій потрібно запустити лише один раз, а не кожне перезавантаження. Тож доведеться піти кудись, що просто працює при наступному перезавантаженні, або мати змогу видалити себе, як тільки він запустився.

Це питання задає питання про збереження стану програми після перезавантаження. Мій сценарій не має великого стану, тому я можу цим керувати. Мені просто потрібно знати, як запустити цей сценарій, щоб запустити щось після наступної перезавантаження.

Моя конкретна версія - Ubuntu Linux 14.04. Оригінальний скрипт запускається в командному рядку системним адміністратором (на відміну від запуску з cron).


Перезавантаження в сценарії слід використовувати лише в тому випадку, якщо ви НЕ МОЖЕТЕ цього уникати. Наприклад, нова установка ядра. Я впевнений, що ви можете виконати свою роботу без перезавантаження. Чи можете ви вказати, для чого вам потрібна перезавантаження?
хаос

1
Цей скрипт встановлює нове ядро ​​(а точніше викликає вдосконалення apt, яке може зробити це). Він також перевіряє, чи потрібна перезавантаження насправді перед перезавантаженням.
Стівен Остерміллер

"Перезавантаження в сценарії слід використовувати лише в тому випадку, якщо ви НЕ МОЖЕТЕ цього уникати." - @chaos Чому?
Джон Ред

Відповіді:


16

В системі єдине, що є дійсно стійким - це файл. Це майже те, що ви повинні використовувати. Ось рішення за допомогою сценарію init.d.

Розглянемо наступний (простий) сценарій /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

Якщо ви активуєте його за допомогою update-rc.d myupdate defaults, startдія буде виконано після завантаження. Тепер, коли ваш сценарій оновлення вимагає перезавантаження:

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

За допомогою цього рішення ви можете розділити свій сценарій оновлення на дві частини:

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

Він виконає before_rebootрозділ коду, створить файл у /var/runта перезавантажиться. Після завантаження сценарій буде викликаний знову, але оскільки файл існує, after_rebootвін буде викликаний замість before_reboot.

Зауважте, що update-rc.dпотрібні привілеї root.

Без використання файлу (з коментаря Стівена Остерміллера ):

Якщо ви знайомі з getoptsутилітою, ви можете використовувати параметри замість файлів. У скрипті init викликайте сценарій за допомогою:

/path/to/update/script -r

А у своєму сценарії перевірте параметри замість файлів. Викличте свій сценарій один раз без можливості, і init.d знову зателефонує під час завантаження, на цей раз з -r.

# Set AFTER_REBOOT according to options (-r).

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

Тут ви знайдете більше інформації про керування опціями (лише для коротких варіантів) . Я також редагував свій сценарій із закликами update-rc.dзберегти цю роботу одноразово (з іншого коментаря).


2
Це може бути простіше подзвонити /path/to/update/script --after-rebootз , /etc/init.d/myupdateа не покладатися на присутність /var/run/rebooting-for-updates. Тоді у нього будуть різні аргументи при запуску безпосередньо проти виклику при завантаженні.
Стівен Остерміллер

Гарний, не думав про варіанти. Дозвольте мені редагувати;)
Джон У. Сміт

1
Крім того, оскільки це разова робота, я, мабуть, хотів би додати update-rc.d myupdate defaultsі update-rc.d myupdate removeв сам сценарій, а також запис і видалення, /etc/init.d/myupdateщоб він не залишав файлів, що сидять навколо.
Стівен Остерміллер

Я це реалізував, і це добре працює. Єдине, що я додам - ​​це те, що моя система на базі Debian вимагає додаткових елементів у INIT INFOрозділі: wiki.debian.org/LSBInitScripts
Стівен Остерміллер

Я дуже хотів, щоб це було просто;) Написання належного init.d займає небагато часу, але я радий, що ви дізналися більше: ці сценарії можуть стати дуже зручними.
Джон У. Сміт
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.