Có thể đặt Ubuntu theo cách mà nó không tắt trước khi tập lệnh kết thúc?


15

Tôi sử dụng một tập lệnh để thực hiện sao lưu gia tăng của phân vùng btrfs từ đĩa này sang đĩa khác.

Kịch bản được bắt đầu bởi cron.weekly vào thời gian ngẫu nhiên trong ngày.

Nếu tôi tắt hệ thống trong khi tập lệnh đang chạy, tôi sẽ gặp rắc rối với các bản sao lưu cũ bị xóa và mới không được tạo.

Có cách nào để thiết lập hệ thống để đợi cho đến khi tập lệnh kết thúc?

Tôi đang sử dụng Ubuntu 16.04 với systemd.


Có một cách để chặn các lệnh GUI. Tôi có một cách tiếp cận kịch bản cho điều đó. Nhưng dòng lệnh không thể chặn nếu được thực hiện bởi sudo người dùng. Tôi sẽ liên kết một câu trả lời trong quá khứ cho GUI. Hãy cho tôi biết nếu bạn muốn nó được tùy chỉnh cho phù hợp với nhu cầu của bạn
Sergiy Kolodyazhnyy


1
@ByteCommander cẩn thận: đó là những hệ thống trước.
Rinzwind

1
@Serg đẹp một :) Nhưng mắt không systemd-inhibitdễ hơn một chút sao? >: - D
Rinzwind

1
Điều gì xảy ra nếu tập lệnh bị khóa? Sẽ không tốt hơn nếu không loại bỏ các bản sao lưu cũ của bạn cho đến khi những cái mới được hoàn thành? Mặc dù bạn có thể ngăn chặn tắt máy nhưng bạn không thể ngăn chặn tình huống xảy ra lỗi hệ thống hoặc mất điện nói chung. Trong cả hai trường hợp, bạn vẫn còn lại với bản sao lưu cũ của bạn đã bị xóa và cái mới không được tạo.
Joe W

Câu trả lời:


20

Đối với Ubuntu 16.04+ sử dụng systemd (mặc định).

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

===

Kiểm tra:

$ 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.

===

Có 7 ổ khóa :

  • sleep ức chế hệ thống treo và ngủ đông được yêu cầu bởi người dùng (không có đặc quyền)
  • shutdown ức chế tắt nguồn hệ thống cấp cao và khởi động lại được yêu cầu bởi người dùng (không có đặc quyền)
  • idle ức chế rằng hệ thống chuyển sang chế độ không tải, có thể dẫn đến hệ thống tự động tạm dừng hoặc tắt máy tùy theo cấu hình.
  • handle-power-key ức chế xử lý mức thấp (tức là logind-Internal) của khóa phần cứng nguồn hệ thống, cho phép mã bên ngoài (có thể không có đặc quyền) xử lý sự kiện thay thế.
  • handle-suspend-key ức chế xử lý cấp thấp của khóa treo phần cứng hệ thống.
  • handle-hibernate-key ức chế xử lý mức thấp của khóa ngủ đông phần cứng hệ thống.
  • handle-lid-switch ức chế xử lý cấp thấp của công tắc nắp phần cứng systemd.

Bạn có thể cũng muốn ngăn chặn suspend, idlehibernate.


Ví dụ sử dụng "trình quản lý gói" :

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

Tương tự như vậy, bạn có thể mã phiên bản của mình và thêm "tắt máy" ở cuối tập lệnh này (hoặc thêm một cách để xác định tắt máy cần phải là hành động tiếp theo).


Bình luận không dành cho thảo luận mở rộng; cuộc trò chuyện đang diễn ra ở đây đã được chuyển sang trò chuyện .
Thomas Ward

2

Trong BackInTime, tôi đang sử dụng một vài phương thức DBus khác nhau để hoạt động trên tất cả các DE chính. Chỉ có nhược điểm là điều này sẽ không hoạt động rootrootkhông có 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)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.