Чи можна встановити Ubuntu таким чином, щоб він не вимикався до завершення сценарію?


15

Я використовую сценарій, щоб робити додаткові резервні копії розділу btrfs з одного диска на інший.

Сценарій запускається cron.weekly у випадковий час доби.

Якщо я закриваю систему під час запуску сценарію, я потрапляю в проблеми зі видаленими старими резервними копіями та новими не створеними.

Чи є спосіб налаштування системи дочекатися закінчення сценарію?

Я використовую Ubuntu 16.04 з systemd.


Існує спосіб блокувати команди GUI. У мене є сценарій підходу до цього. Але блокувати командний рядок неможливо, якщо це зроблено sudo користувачем. Я зв’яжу минулу відповідь для GUI. Повідомте мене, чи хочете ви, щоб він був налаштований відповідно до ваших потреб
Сергій Колодяжний,


1
@ByteCommander обережно: вони попередньо систематизовані.
Rinzwind

1
@Serg приємний :) Але чи systemd-inhibitтрохи легше на очах? >: - D
Rinzwind

1
Що станеться, якщо сценарій заблокується? Чи не було б краще не видаляти свої старі резервні копії, поки нові все одно не будуть закінчені? Хоча, можливо, ви зможете запобігти відключенню, ви не можете запобігти ситуації, коли відбувається збій системи або загальна втрата електроенергії. В будь-якому випадку вам залишається видалена стара копія, а нова не створена.
Jo W

Відповіді:


20

Для Ubuntu 16.04+ з використанням systemd (за замовчуванням).

systemd-inhibit --why="Wait for this script to finish" bash script.sh

===

Тест:

$ systemctl poweroff
Operation inhibited by "bash script.sh" (PID 23912 "systemd-inhibit", user rinzwind),
reason is "Wait for this script to finish".
Please retry operation after closing inhibitors and logging out other users.

===

Є 7 замків :

  • sleep гальмує призупинення роботи системи та сну в режимі сну, прохання яких (непривілейовані) користувачі
  • shutdown пригнічує відключення та перезавантаження системи на високому рівні за запитом (непривілейованих) користувачів
  • idle гальмує, що система переходить в режим очікування, що, можливо, призводить до автоматичного призупинення або відключення системи в залежності від конфігурації.
  • handle-power-key пригнічує низький рівень (тобто внутрішній вихід) керування системним апаратним ключем живлення системи, дозволяючи (можливо, непривілейований) зовнішній код обробляти подію.
  • handle-suspend-key гальмує керування ключем призупинення апаратного забезпечення на низькому рівні.
  • handle-hibernate-key гальмує низькорівневу обробку режиму сплячого обладнання апаратного забезпечення системи.
  • handle-lid-switch пригнічує низький рівень керування перемикачем кришки системного обладнання.

Ви, ймовірно, також хочете запобігти suspend, idleі hibernate.


Приклад використання "менеджера пакунків" :

fd = Inhibit("shutdown:idle", "Package Manager", "Upgrade in progress...", "block");
/* ...
      do your work
                 ... */
close(fd);

Подібно до цього, ви можете кодувати свою версію та додати "відключення" в кінці цього сценарію (або додати спосіб визначення відключення має бути наступною дією).


Коментарі не для розширеного обговорення; розмова, що велася тут, була переміщена до чату .
Thomas Ward

2

У BackInTime я використовую пару різних методів DBus для роботи над усіма основними DE. Тільки недоліком цього не вийде, rootтому rootщо немає dbus.SessionBus.

#!/usr/bin/env python3
import sys
import dbus
from time import sleep

INHIBIT_LOGGING_OUT = 1
INHIBIT_USER_SWITCHING = 2
INHIBIT_SUSPENDING = 4
INHIBIT_IDLE = 8

INHIBIT_DBUS = (
               {'service':      'org.gnome.SessionManager',
                'objectPath':   '/org/gnome/SessionManager',
                'methodSet':    'Inhibit',
                'methodUnSet':  'Uninhibit',
                'interface':    'org.gnome.SessionManager',
                'arguments':    (0, 1, 2, 3)
               },
               {'service':      'org.mate.SessionManager',
                'objectPath':   '/org/mate/SessionManager',
                'methodSet':    'Inhibit',
                'methodUnSet':  'Uninhibit',
                'interface':    'org.mate.SessionManager',
                'arguments':    (0, 1, 2, 3)
               },
               {'service':      'org.freedesktop.PowerManagement',
                'objectPath':   '/org/freedesktop/PowerManagement/Inhibit',
                'methodSet':    'Inhibit',
                'methodUnSet':  'UnInhibit',
                'interface':    'org.freedesktop.PowerManagement.Inhibit',
                'arguments':    (0, 2)
               })

def inhibitSuspend(app_id = sys.argv[0],
                    toplevel_xid = None,
                    reason = 'take snapshot',
                    flags = INHIBIT_SUSPENDING | INHIBIT_IDLE):
    """
    Prevent machine to go to suspend or hibernate.
    Returns the inhibit cookie which is used to end the inhibitor.
    """
    if not app_id:
        app_id = 'backintime'
    if not toplevel_xid:
        toplevel_xid = 0

    for dbus_props in INHIBIT_DBUS:
        try:
            bus = dbus.SessionBus()
            interface = bus.get_object(dbus_props['service'], dbus_props['objectPath'])
            proxy = interface.get_dbus_method(dbus_props['methodSet'], dbus_props['interface'])
            cookie = proxy(*[(app_id, dbus.UInt32(toplevel_xid), reason, dbus.UInt32(flags))[i] for i in dbus_props['arguments']])
            print('Inhibit Suspend started. Reason: %s' % reason)
            return (cookie, bus, dbus_props)
        except dbus.exceptions.DBusException:
            pass
    print('Inhibit Suspend failed.')

def unInhibitSuspend(cookie, bus, dbus_props):
    """
    Release inhibit.
    """
    assert isinstance(cookie, int), 'cookie is not int type: %s' % cookie
    assert isinstance(bus, dbus.bus.BusConnection), 'bus is not dbus.bus.BusConnection type: %s' % bus
    assert isinstance(dbus_props, dict), 'dbus_props is not dict type: %s' % dbus_props
    try:
        interface = bus.get_object(dbus_props['service'], dbus_props['objectPath'])
        proxy = interface.get_dbus_method(dbus_props['methodUnSet'], dbus_props['interface'])
        proxy(cookie)
        print('Release inhibit Suspend')
        return None
    except dbus.exceptions.DBusException:
        print('Release inhibit Suspend failed.')
        return (cookie, bus, dbus_props)

if __name__ == '__main__':
    cookie, bus, dbus_props = inhibitSuspend()
    print('do something here')
    sleep(10)
    unInhibitSuspend(cookie, bus, dbus_props)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.