是否有可能在脚本完成之前将Ubuntu设置为不关闭的方式?
我使用脚本从一个磁盘到另一个磁盘执行btrfs分区的增量备份。
该脚本由cron.weekly在一天的随机时间启动。
如果我在脚本运行时关闭了系统,那么在删除旧备份和未创建新备份时会遇到问题。
有没有办法设置系统等到脚本完成?
我正在使用带有systemd的Ubuntu 16.04。
对于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
禁止(非特权)用户请求的系统挂起和hibernate -
shutdown
禁止高级系统关闭电源并重启(非特权用户) -
idle
禁止系统进入空闲模式,可能导致系统自动暂停或关闭,具体取决于配置。 -
handle-power-key
禁止系统电源硬件密钥的低级(即logind-internal)处理,允许(可能没有特权的)外部代码来处理事件。 -
handle-suspend-key
禁止系统硬件挂起键的低级处理。 -
handle-hibernate-key
禁止系统硬件hibernate密钥的低级处理。 -
handle-lid-switch
禁止系统硬件盖开关的低级操作。
您可能还希望阻止suspend
, idle
和hibernate
。
使用“包管理器”的示例 :
fd = Inhibit("shutdown:idle", "Package Manager", "Upgrade in progress...", "block"); /* ... do your work ... */ close(fd);
与此类似,您可以编写您的版本并在此脚本的末尾添加“关闭”(或添加一种方法来确定关闭需要是下一个操作)。
在BackInTime中,我使用几种不同的DBus方法来处理所有主要的DE。 唯一的缺点是这对root
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)