Виконайте команду перед відключенням


52

Я хочу виконати просту команду перед тим, як комп'ютер вимкнеться (терміни не є істотними).

Для запуску я можу використовувати /etc/rc.local; чи є щось подібне для відключення?

Зауважте, що я все одно хотів би використовувати вбудовану кнопку вимкнення з меню; тобто я не хочу використовувати користувальницький скрипт щоразу, коли вимикаюсь через термінал - він повинен бути автоматичним.

Відповіді:


42

Linux Mint базується на Ubuntu, тому я здогадуюсь, що система бігового рівня, мабуть, та сама. У Ubuntu сценарії для різних рівнів виконуються відповідно до їх наявності в /etc/rc[0-6].dкаталогах. Рівень запуску 0 відповідає відключенню, а 6 - перезавантаженню.

Зазвичай сам скрипт зберігається в /etc/init.d, а потім посилання розміщуються в каталогах, що відповідають необхідним рівням запуску.

Тож у вашому випадку напишіть свій скрипт, збережіть його /etc/init.d/, а потім створіть символьне посилання у кожному із них /etc/rc0.dта /etc/rc6.d(якщо ви хочете обох), вказуючи на ваш сценарій.

Сценарії в кожному каталозі runlevel будуть виконані в асибетичному порядку , тому, якщо порядок в межах runlevel має значення для вас, виберіть відповідно ім'я вашої символьної посилання.


Я щойно подивився файл скелета в init.d (точний kubuntu) і трохи залякався. Я просто хочу додати пару команд, які відображають дату відключення у файл під / var / log. Чи можу я це зробити чи мені доводиться мати справу з іншими речами у файлі скелета?
Джо

2
@Joe - Більшість цього матеріалу вам не потрібна, якщо ви не хочете, щоб ваш сценарій контролювався як стандартний сервіс. Ви не зламаєте нічого простим відлунням до свого власного файлу журналу, тому спробуйте і подивіться.
ire_and_curses

1
Ось простий зразок сценарію init.d. Крім того, простіше і надійніше зробити посилання, використовуючиsudo update-rc.d /etc/init.d/myservice defaults
RolfBly

Я написав /etc/init.d/spark_shutdown.sh і створив посилання в /etc/rc0.d & /etc/rc6.d, як я підтверджую, що цей сценарій працює в екземплярі ubuntu aws ec2
Ashish Karpe,

10

Тепер, коли варіанти Ubuntu та Mint перейшли до systemd, я виявив, що мої старі рішення на основі вищезазначеного є менш задовільними. Я шукав по Інтернету, щоб дізнатися, як це зробити з systemd і в кінцевому підсумку поєднуючи чужість і документуючи це як допис у блозі на blogspot.com.au, що містить наступний підручник.

За допомогою systemd ви створюєте один або два файли для виклику сценаріїв за допомогою наведених нижче шаблонів та виконуєте пару команд. Простий.


Версія GUI

Спочатку створіть сценарії, які потрібно запустити при запуску та / або вимкненні. Я створив .scopening_atstart і .scfullcopy_atend.

Потім переконайтесь, що вони обидва виконувані, клацнувши правою кнопкою миші файл, вибравши властивості та переконайтесь, що в межах дозволів ви поставили галочку Дозволити виконання файлу як програми.

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

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

Потім я відкрив свій файловий менеджер як root, відкрив /etc/systemd/systemі створив файл startup.service та файл save-ramdisk.service. Очевидно, ви можете вибрати власні імена та загальні імена, які могли б включати файл запуску під назвою johns_start.service та файл закриття під назвою johns_shutdown.service. Просто не вибирайте існуючі назви служб.

[Unit]
Description=Startup Applications

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

[Install]
WantedBy=multi-user.target

і

[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

Ви можете використовувати ті самі файли служб, замінюючи повний шлях вашого виконуваного сценарію для мого.

Нарешті, для кожного з них виконайте команду systemctl enable your_files_name (але без служби суфікса). Отже, моя перша булаsystemctl enable startup

Перезавантажте комп'ютер один раз, щоб запустити послуги. Служба запуску буде виконуватися щоразу, коли systemd вводить ціль для багатьох користувачів, а служба зупинки, коли вона виходить з цілі для багатьох користувачів. Альтернативні файли обслуговування з різними умовами активації будуть описані нижче.


Версія CLI (командного рядка)

Цей опис передбачає, що ви працюєте з домашнього каталогу, а не / home / john, використовуєте sudo за потребою та ваш вибір редактора, де я пишу vim чи svim.

Створіть сценарії оболонки запуску та відключення з першого рядка #!/bin/shта зробіть їх виконуваним за допомогою chmod +x my_new_filename.

Створіть два файли, як описано вище, або в цьому прикладі, один файл для обробки завдань запуску та вимкнення. Я виконуватиму сценарії у своєму домашньому каталозі, але @don_crissti показує деякі варіанти на Stack Exchange .

vim /etc/systemd/system/start_and_stop.service

і скопіюйте вміст файлу:

[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

Потім увімкніть службу за допомогою команди:

systemctl enable start_and_stop

і перезавантажте систему, після чого служби будуть активними. Команди systemctl is-enabled start_and_stopта systemctl is-active start_and_stopїх можна використовувати для моніторингу нових служб.


Зміна умов тригера для вимкнення

Файли перш за все використовують відкрите або закрите багатокористувацьке середовище для ініціювання запуску скриптів. У наведеному нижче файлі використовується початок чотирьох потенційних процесів відключення для ініціювання його сценаріїв. Додавання або видалення цілей у рядку "Перед" + рядок "WantedBy" дозволить вам зробити чіткіші розрізнення:

Цей файл був запропонований у другій відповіді цієї публікації, але мені не вдалося змусити його працювати, поки я не додав розділ Встановити.

Знову ж відредагуйте скрипт /etc/systemd/service/і ввімкніть його за допомогою systemctl enable your_file_name. Коли я змінив цілі, я застосував systemclt disable file_nameкоманду, а потім повторно включив її, що символізувало її до цільових каталогів. Перезавантажте і сервіс буде працювати.

[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

Потрібно використовувати rc.shutdownсценарій відключення для ядра Linux. Цитуючи чоловічу сторінку OpenBSD :

Коли система вимикається за допомогою команд перезавантаження (8) або зупинки (8) або коли сигналізується про це init (8), або коли видається запит на клавіатуру (якщо архітектура підтримує це), rc ( 8) викликається аргументом `` вимкнення ''.

Отже, ви просто відкриєте rc.shutdown і додаєте до нього всі команди оболонки, які ви хочете виконати.

ОНОВЛЕННЯ: Оскільки Linux Mint базується на Ubuntu, який має іншу процедуру запуску / відключення, ось ця процедура стосується вас:

Напишіть сценарій оболонки, який ви хочете виконати, і скопіюйте його у відповідний каталог у своєму /etc/rc*.d/. У *відповідає рівень запуску , на якому ви хочете, щоб скрипт для виконання.
Ubuntu слід за нумерацією запущеного рівня Debian, тому у вас є runlevel 0 для зупинки та runlevel 6 для перезавантаження.


1

Для систем init на основі залежності від SysV, використовуваних у Debian Wheezy, Devuan та його похідних та, можливо, інших, ви можете імітувати поведінку rc.shutdownаналога rc.localтаким чином:

Додайте команди до наступного скелета /etc/rc.shutdown:

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

# <add your commands here, before exit 0>

exit 0

Збережіть сценарій і зробіть файл виконуваним chmod a+x /etc/rc.shutdown.

Потім додайте /etc/init.d/rc.shutdownу вашу систему новий сценарій із таким вмістом:

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

Також зробіть цей сценарій виконуваним.

Створіть символьні посилання в /etc/rc evidence06Sense.d:

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

і

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

Використовуйте insservдля виправлення символьних посилань та створення необхідних файлів .depend.boot, .depend.start та .depend.stop:

insserv -v

Потрібно мати root або використовувати sudo для всіх згаданих вище команд.


Сьогодні я трохи витратив час на цей і не зміг змусити його працювати з Ubuntu 16, можливо, це я, але рішення вище працювало негайно.
Майк Q
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.