Как автоматически перейти из Suspend в Hibernate?

53

Можно ли перевести Ubuntu в состояние гибернации из Suspend, также называемого «Suspend Sedation»?

Я ищу следующее:
когда я закрываю крышку, ноутбук переводится в режим ожидания. Затем, по прошествии заданного времени (даже если аккумулятор разряжается), если я все еще не использую его, он должен перейти в режим гибернации для экономии заряда аккумулятора.

Например, мой ноутбук настроен на переход в режим ожидания, когда я закрываю крышку. Если я не использую его в течение всего дня, батарея разряжается, потому что даже в режиме ожидания оборудование все еще потребляет небольшое количество энергии, и батарея в конечном итоге разряжается. Я хочу сказать Ubuntu, что даже если он приостановлен, он все равно должен войти в Hibernate после нескольких часов бездействия.

Windows может сделать это. Ubuntu может быть запрограммирован на переход в режим ожидания или спящий режим по таймеру, но не в обоих случаях.

Сергей Стадник
источник
В своем исследовании я обнаружил ту же ветку Linux Mint, но «Suspend Sedation» не является официальным термином Microsoft для этой функции и, насколько я могу судить, был изобретен пользователем форума Linux Mint, который упомянул об этом.
ayan4m1
Есть ли лучшее название для этой функции?
Сергей Стадник
Насколько я могу судить, универсального названия этой функции не существует. "Hybrid Suspend" используется некоторыми, "Suspend Sedation" используется этим одним пользователем форума Linux Mint, и я слышал, что "Hibernate and Suspend" раньше использовался для обозначения процесса. Microsoft официально называет это «гибридным сном», по крайней мере, для Windows 7.
ayan4m1
2
@ ayan4m1 Я понимаю, что это старый вопрос, но я думаю, что важно уточнить это. Гибридный сон - это не то же самое, что «Спи, а потом впадаешь в спящий режим через определенное время». Гибридный сон просто переходит в спящий режим при потере питания из-за разрядки аккумулятора. Поведение, описанное OP, не требует включения гибридного сна.
Пол

Ответы:

20

В Ubuntu 18.04 это намного проще. В systemd доступен новый режим suspend-then-hibernate . Чтобы начать использовать эту функцию, вам нужно создать файл /etc/systemd/sleep.conf со следующим содержимым:

[Sleep]
HibernateDelaySec=3600

Затем вы можете проверить это командой:

sudo systemctl suspend-then-hibernate

Вы можете редактировать, HibernateDelaySecчтобы уменьшить задержку в спящем режиме.


Если все работает нормально, вы можете изменить Lid Close Action, для этого вам нужно отредактировать файл /etc/systemd/logind.conf

Вам нужно найти опцию HandleLidSwitch=, раскомментировать ее и изменить на HandleLidSwitch=suspend-then-hibernate. Затем вам нужно перезапустить службу systemd-logind (предупреждение! Ваш пользовательский сеанс будет перезапущен) следующей командой:

sudo systemctl restart systemd-logind.service

Вот и все! Теперь вы можете использовать эту красивую функцию.

PRIHLOP
источник
Это было на месте. Использование его на Pop! _OS 18.10 (он же Ubuntu 18.10).
eduncan911
Гениальное спасибо! Влияет ли sleep.conf на режим гибернации каким-то образом, или он влияет только на suspend-then-hibernate?
user2428107
@ user2428107 Вы можете прочитать об опциях в руководстве systutorials.com/docs/linux/man/5-systemd-sleep
PRIHLOP
35

Решение этого простое. Во-первых, после приостановки и возобновления программа pm-suspend выполняет ряд сценариев в /etc/pm/sleep.dи /usr/lib/pm-utils/sleep.d. Поэтому мое решение состоит в том, чтобы добавить скрипт, который выполняет следующее:

  1. После приостановки запишите текущее время и зарегистрируйте событие пробуждения, используя rtcwake.
  2. После возобновления проверьте текущее время по сравнению с записанным временем сверху. Если прошло достаточно времени, то мы, вероятно, проснулись из-за события таймера rtc. В противном случае мы проснулись рано из-за пользовательского события (например, открытия экрана ноутбука).
  3. Если мы проснулись из-за таймера rtc, то немедленно запускаем команду «pm-hibernate», чтобы перейти в спящий режим.

Вот скрипт, который делает это. Назовите его 0000rtchibernateи поместите в /etc/pm/sleep.dкаталог (значение 0000 важно, чтобы скрипт выполнялся сначала при приостановке, а затем при возобновлении).

#!/bin/bash
# Script name: /etc/pm/sleep.d/0000rtchibernate
# Purpose: Auto hibernates after a period of sleep
# Edit the "autohibernate" variable below to set the number of seconds to sleep.
curtime=$(date +%s)
autohibernate=7200
echo "$curtime $1" >>/tmp/autohibernate.log
if [ "$1" = "suspend" ]
then
    # Suspending.  Record current time, and set a wake up timer.
    echo "$curtime" >/var/run/pm-utils/locks/rtchibernate.lock
    rtcwake -m no -s $autohibernate
fi

if [ "$1" = "resume" ]
then
    # Coming out of sleep
    sustime=$(cat /var/run/pm-utils/locks/rtchibernate.lock)
    rm /var/run/pm-utils/locks/rtchibernate.lock
    # Did we wake up due to the rtc timer above?
    if [ $(($curtime - $sustime)) -ge $autohibernate ]
    then
        # Then hibernate
        rm /var/run/pm-utils/locks/pm-suspend.lock
        /usr/sbin/pm-hibernate
    else
        # Otherwise cancel the rtc timer and wake up normally.
        rtcwake -m no -s 1
    fi
fi

Надеюсь, этот код появится на этой доске объявлений (это мой первый пост здесь).

Измените значение тайм-аута autohibernate=7200вверху, чтобы вы могли поспать сколько угодно секунд, прежде чем перейти в спящий режим. Текущее значение выше - 2 часа. Обратите внимание, что ваш ноутбук БУДЕТ просыпаться в это время на несколько секунд, пока он выполняет функцию гибернации.

Так что, если вы планируете положить свой ноутбук в чехол, не приостанавливайте, а вместо этого переходите в спящий режим. В противном случае ваш ноутбук может перегреться в ESP. если он находится в плотно прилегающем футляре (хотя он будет включен только от нескольких секунд до минуты).

Я использовал этот метод в течение последних нескольких дней, пока он был успешным (и спас меня от разряженной батареи сегодня днем). Наслаждаться.

Для других дистрибутивов Linux , что использование systemdи более новые версии Ubuntu это должно работать , если вы поместите скрипт в /usr/lib/systemd/system-sleepвместо /etc/pm/sleep.d. Также замените /usr/sbin/pm-hibernateкоманду на systemctl hibernate.

Дерек Прессналл
источник
Это сработало здесь, но только после того, как я изменил файл, чтобы добавить X всем. Я большой новичок, и мне потребовалось 2 дня, чтобы понять. Очень хороший сценарий, и я надеюсь, что это поможет тем, у кого могут быть проблемы. Спасибо.
2
Это сделало бы полезный пакет Ubuntu / Debian!
Петр Пудлак
Просто интересно: будет ли это по-прежнему актуально для Ubuntu 13.04? Мне нужно именно это решение, но я не хочу связываться с ноутбуком жены, если он выйдет из строя на более новых версиях.
Торбен Гундтофте-Бруун
Спасибо за сценарий. У меня отлично работает на Ubuntu 14.04! Одним из улучшений было бы то, что, когда ноутбук просыпается в спящий режим, он может проверить, подключен ли он к сети переменного тока. Если это так, я бы хотел, чтобы он снова приостановился, а не впал в спячку. Восстановление из спящего режима занимает больше времени, и мне не нужно, чтобы оно
впало
Огромное спасибо!!!! Этот сценарий - волшебство, о котором я мечтал !!
Янп
12

Чтобы объяснить, как это работает (это похоже на Windows) простыми словами: машина не выходит из режима ожидания, когда батарея разряжается, чтобы иметь возможность сохранить состояние машины в раздел подкачки, она сразу сохраняет все в раздел подкачки в режиме ожидания, и когда батарея разрядится, она восстановится после загрузки состояния из раздела подкачки (как это было бы в случае перехода в спящий режим).

AFAIK linux будет / должен использовать гибридный режим ожидания / спящий режим вместо «нормального» режима ожидания, если он знает, что он работает на вашем оборудовании. Также возможно, что это отключено в настоящее время из-за слишком большого количества ошибок или чего-то ...;)

Если вам нравится экспериментировать, возможно, вы сможете увидеть, можете ли вы получить какие-либо хорошие результаты с pm-suspend-hybrid .

Если следующее говорит, что вам повезло, то теоретически в вашей системе поддерживается гибридная приостановка:

pm-is-supported --suspend-hybrid && echo "you're lucky"
Janc
источник
1
Единственный апостроф в вашей команде оболочки может вводить в заблуждение и сбивать с толку ... пожалуйста, избегайте его.
ayan4m1
1
Бах, вот что происходит, когда вы редактируете командную строку, встроенную в другой текст, не думая об этом как о командной строке ... Спасибо и исправлено.
Янв
Нет проблем, да, мы поняли о разном свободном пространстве для этих двух процессов.
ayan4m1
6

Вы можете быть заинтересованы в s2both . Это предусмотрено пакетом uswsuspв Ubuntu 10.10. Он приостанавливается на диск, но вместо выключения системы вместо этого переводит его в режим S3, который является режимом питания, обычно связанным с опцией «Suspend» в Ubuntu. pm-suspend-hybrid - еще один инструмент, который делает то же самое.

Чтобы сделать это автоматизированным при закрытии крышки, взгляните на следующее руководство, которое позволяет запускать произвольный скрипт при обнаружении события крышки:

http://ubuntuforums.org/showthread.php?t=1076486

Если у вас есть ThinkPad, tpctlсправочная страница для ссылки ссылается на аргумент --pm-sedation-hibernate-from-suspend-timer, который, кажется, обеспечивает функцию, которую вы ищете. Я бы предостерег вас от попыток сделать это на оборудовании, отличном от ThinkPad.

Для справки я просмотрел man-страницу hibernate.conf ; у этого, казалось, не было никаких соответствующих вариантов, но могло бы стоить второго чтения.

ayan4m1
источник
5

Ubuntu 16.04 - из режима ожидания / сна в спящий режим через заданное время

Кажется, что в Ubuntu 16.04 все немного по-другому, поэтому я предпринял следующие шаги:

  1. Убедитесь, что Hibernate работает должным образом при запуске

    systemctl hibernate
    
  2. Скопируйте оригинальный suspend.targetфайл:

    sudo cp /lib/systemd/system/suspend.target /etc/systemd/system/suspend.target
    

    Затем отредактируйте файл /etc/systemd/system/suspend.targetи добавьте строку:

    Requires=delayed-hibernation.service
    

    в [Unit]разделе этого файла.

  3. Создайте файл /etc/systemd/system/delayed-hibernation.serviceсо следующим содержимым:

[Единица измерения]
Описание = Задержка спящего режима
Перед = suspend.target
Conflicts = hibernate.target hybrid-suspend.target
StopWhenUnneeded = верно

[Обслуживание]
Тип = OneShot
RemainAfterExit = да
ExecStart = / usr / local / bin / delayed-hibernation.sh предварительная приостановка
ExecStop = / usr / local / bin / delayed-hibernation.sh пост приостановить

[Установить]
WantedBy = sleep.target
  1. Создайте файл конфигурации /etc/delayed-hibernation.confдля скрипта со следующим содержимым:
# Файл конфигурации для скрипта delayed-hibernation.sh

# Укажите время в секундах, которое нужно провести в режиме сна, прежде чем компьютер перейдет в спящий режим
TIMEOUT = 1200 # в секундах, дает 20 минут
  1. Создайте сценарий, который на самом деле выполняет тяжелую работу.

    Создать файл /usr/local/bin/delayed-hibernation.shс содержанием:

#! / Bin / Баш
# Имя скрипта: delayed-hibernation.sh
# Цель: авто зимует после периода сна
# Отредактируйте переменную `TIMEOUT` в файле` $ hibernation_conf`, чтобы установить количество секунд ожидания.

hibernation_lock = '/ вар / бег / отсроченный hibernation.lock'
hibernation_fail = '/ вар / запустить / delayed-hibernation.fail'
hibernation_conf = '/ и т.д. / замедленного hibernation.conf'

# Проверка файла конфигурации
если [ ! -f $ hibernation_conf]; тогда
    echo "Отсутствует файл конфигурации ('$ hibernation_conf'), прерывание."
    выход 1
фи
hibernation_timeout = $ (grep "^ [^ #]" $ hibernation_conf | grep "TIMEOUT =" | awk -F '=' '{print $ 2}' | awk -F '#' '{print $ 1}' | tr -d '[[\ t]]')
if ["$ hibernation_timeout" = ""]; тогда
    echo "Отсутствует параметр 'TIMEOUT' в файле конфигурации ('$ hibernation_conf'), прерывание."
    выход 1
элиф [[! "$ hibernation_timeout" = ~ ^ [0-9] + $]]; тогда
    echo «Неверный параметр TIMEOUT» («$ hibernation_timeout») в файле конфигурации («$ hibernation_conf»), ожидаемое количество секунд, прерывание ».
    выход 1
фи

# Обработка заданных параметров
if ["$ 2" = "suspend"]; тогда
    curtime = $ (дата +% s)
    if ["$ 1" = "pre"]; тогда
        if [-f $ hibernation_fail]; тогда
            echo "Обнаружен сбой гибернации, пропущена настройка таймера пробуждения RTC."
        еще
            echo "Обнаружена приостановка. Время записи, установить таймер RTC"
            echo "$ curtime"> $ hibernation_lock
            rtcwake -m no -s $ hibernation_timeout
        фи
    elif ["$ 1" = "post"]; тогда
        if [-f $ hibernation_fail]; тогда
            rm $ hibernation_fail
        фи
        if [-f $ hibernation_lock]; тогда
            sustime = $ (кошка $ hibernation_lock)
            rm $ hibernation_lock
            if [$ (($ curtime - $ sustime)) -ge $ hibernation_timeout]; тогда
                echo "Автоматическое возобновление при обнаружении приостановки. Гибернация ..."
                systemctl hibernate
                если [$? -не 0]; тогда
                    echo "Автоматическая гибернация не удалась. Попытка приостановить вместо этого."
                    коснитесь $ hibernation_fail
                    systemctl приостановить
                    если [$? -не 0]; тогда
                        echo "Не удалось выполнить автоматический переход в режим гибернации и приостановки при сбое. Больше ничего не попробовать."
                    фи
                фи
            еще
                echo "Обнаружено ручное возобновление из режима ожидания. Сброс таймера RTC"
                rtcwake -m отключить
            фи
        еще
            echo "Файл '$ hibernation_lock' не найден, ничего не делать"
        фи
    еще
        echo "Нераспознанный первый параметр: '$ 1', ожидаемый" pre "или" post ""
    фи
еще
    echo "Этот скрипт предназначен для запуска systemctl delayed-hibernation.service (ожидаемый второй параметр: 'suspend')"
фи
  1. Сделайте скрипт исполняемым:
chmod 755 /usr/local/bin/delayed-hibernation.sh

Это заняло у меня довольно много времени, пока я не написал этот сценарий, основанный на других ответах в этой теме, таких вещах, которые я нашел в Интернете, таких как https://bbs.archlinux.org/viewtopic.php?pid=1554259.

Моя версия скрипта пытается справиться со многими проблемами, такими как снова перейти в режим ожидания, если гибернация не была успешной, но не просыпаться снова по истечении заданного времени снова и снова.

  1. Последний шаг, который я предполагаю, будет просто выполнить

    sudo systemctl daemon-reload
    sudo systemctl enable delayed-hibernation.service 
    

    чтобы убедиться, что новый сервис / конфигурации используются.

Чтобы проверить сервисный журнал, вы можете использовать:

sudo systemctl status delayed-hibernation.service

или для полного журнала использования сервиса:

sudo journalctl -u отложенная-гибернация.сервис

Обычный журнал, который я получаю от работающей службы:

mile @ mile-ThinkPad: ~ $ sudo systemctl status delayed-hibernation.service 
● delayed-hibernation.service - отложенный триггерный режим
   Загружен: загружен (/etc/systemd/system/delayed-hibernation.service; включен; предустановка поставщика: включена)
   Активный: неактивный (мертвый)

Июн 09 20:35:42 mile-ThinkPad systemd [1]: запуск отложенного триггерационного триггера ...
Июн 09 20:35:42 mile-ThinkPad delayed-hibernation.sh [2933]: Обнаружена приостановка. Время записи, установить таймер RTC
09 июня 20:35:42 mile-ThinkPad delayed-hibernation.sh [2933]: rtcwake: при условии, что RTC использует UTC ...
Июн 09 20:35:42 mile-ThinkPad delayed-hibernation.sh [2933]: rtcwake: пробуждение с использованием / dev / rtc0 в четверг 9 июня 18:55:43 2016
Июн 09 20:55:44 mile-ThinkPad systemd [1]: Запущен отложенный триггерный режим.
Июн 09 20:55:44 mile-ThinkPad systemd [1]: delayed-hibernation.service: юнит больше не нужен. Остановка.
Июн 09 20:55:44 mile-ThinkPad systemd [1]: остановка отложенного триггерационного триггера ...
Июн 09 20:55:44 mile-ThinkPad delayed-hibernation.sh [3093]: Обнаружено автоматическое возобновление после приостановки. Hibernating ...
Июн 09 20:55:44 mile-ThinkPad systemd [1]: остановлен отложенный триггерный режим.
мили @ мили ThinkPad: ~ $ 

Так что это будет, я надеюсь, что это действительно кому-то поможет, поскольку я потратил несколько дней, пытаясь найти правильную комбинацию конфигураций и версий скриптов, чтобы эта удобная функция работала.

mihai.ile
источник
Спасибо за ответ, это все еще работает как шарм на Ubuntu 18.04. Я не мог заставить вышеуказанные ответы работать, выполнение /bin/systemctl hibernateвсегда возвращало бы 1 при запуске в сценарии systemd, даже если оно отлично работает в командной строке.
Евгенху
4

На всякий случай, если что-то пойдет не так во время, pm-hibernateя бы предпочел приостановить работу компьютера, а не запускать его. Таким образом, вы можете использовать:

   ...
/usr/sbin/pm-hibernate || /usr/sbin/pm-suspend
   ...
iiegn
источник
3

Вот обновленная версия ответа Дерека Прессналла, который работает с systemd и включает предложение Элии Кагана , просто поместите его в /usr/lib/systemd/system-sleep/delayed_hibernation.sh и сделайте его исполняемым:

#!/bin/bash

hibernation_timeout=1800  #30 minutes

if [ "$2" = "suspend" ]; then
    curtime=$(date +%s)
    if [ "$1" = "pre" ]; then
        echo -e "[($curtime) $@]\nExecuting pre-suspend hook..." >> /tmp/delayed_hibernation.log
        echo "$curtime" > /var/run/delayed_hibernation.lock
        rtcwake -m no -s $hibernation_timeout
    elif [ "$1" = "post" ]; then
        echo -e "[($curtime) $@]\nExecuting post-suspend hook..." >> /tmp/delayed_hibernation.log
        sustime=$(cat /var/run/delayed_hibernation.lock)
        if [ $(($curtime - $sustime)) -ge $hibernation_timeout ]; then
            echo -e "Automatic resume detected, hibernating.\n" >> /tmp/delayed_hibernation.log
            systemctl hibernate || systemctl suspend
        else
            echo -e "Manual resume detected, clearing RTC alarm.\n" >> /tmp/delayed_hibernation.log
            rtcwake -m no -s 1
        fi
        rm /var/run/delayed_hibernation.lock
    fi
fi
Никколо Маджони
источник
Это работало отлично в течение нескольких месяцев 15.10, но что-то в 16.04 мешает ему переходить в спящий режим, даже если скрипт все еще работает.
Шон
@Sean ты пробовал обходной путь в этой теме ?
Никколо Маджиони
Спасибо, что указал мне правильное направление. Я создал службу systemd (/etc/systemd/system/delayed-hibernation.service), которая ссылалась на приведенный выше скрипт, затем изменила /etc/systemd/system/suspend.target так, чтобы она требовала delayed-hibernation.service.
Шон
2

Вот мой рецепт (проверял его на двух ноутбуках Ubuntu 16.04):

Поместите этот скрипт туда, куда вам нравится (я поставил его в root /syspend.sh) и сделайте его исполняемым ( chmod +x /suspend.sh)

TIMELOG=/tmp/autohibernate.log
ALARM=$(tail -n 1 $TIMELOG)
SLEEPTIME=5000 #edit this line to change timer, e.g. 2 hours "$((2*60*60))"
if [[ $1 == "resume" ]]
then
    if [[ $(date +%s) -ge $(( $ALARM + $SLEEPTIME )) ]]
    then
        echo "hibernate triggered $(date +%H:%M:%S)">>$TIMELOG
        systemctl hibernate 2>> $TIMELOG
    else
        echo "normal wakeup $(date +%H:%M:%S)">>$TIMELOG
    fi
elif [[ $1 == "suspend" ]]
then
    echo "$(date +%s)" >> $TIMELOG
    rtcwake -m no -s $SLEEPTIME
fi

Затем создайте цель systemd: # touch /etc/systemd/system/suspend-to-sleep.target вставьте этот контент:

#/etc/systemd/system/suspend-to-hibernate.service
[Unit]
Description=Delayed hibernation trigger
Before=suspend.target
Conflicts=hibernate.target hybrid-suspend.target
StopWhenUnneeded=true

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/bin/bash /suspend.sh suspend
ExecStop=/bin/bash /suspend.sh wakeup

[Install]
WantedBy=sleep.target
RequiredBy=suspend.target

Затем включите его # systemctl enable suspend-to-sleep.target.

Я столкнулся с проблемой на одном из ноутбуков: закрытие крышки не сработало. Это было связано с xfce4-power-manager. Есть два способа обойти эту проблему. Первый - отредактировать /etc/systemd/logind.confфайл и заменить HandleLidSwitch=ignoreна HandleLidSwitch=suspend. Но это будет общесистемно, поэтому я просто добавил символическую ссылку в свой скрипт# ln -s /suspend.sh /etc/pm/sleep.d/0000rtchibernate

yanpas
источник
1

Еще один более распространенный обходной путь, который вы можете использовать hybrid-sleep(как это делает Mac OS). Если ваш компьютер поддерживает спящий режим, вы можете использовать эту функцию:

systemctl hybrid-sleep

Эта команда должна приостановить и отправить на диск (в спящий режим) компьютер. Через некоторое время компьютер выключится (при включении он будет использовать файлы гибернации для пробуждения).

PS: я знаю, что это не совсем то, что опубликовал ОП, но это довольно близко

morhook
источник
0

Не забудьте chmod + x этот файл, сделайте его исполняемым.

Есть другое решение без rtcwake, использующее wakealarm в / sys / class / rtc / rtc0. Используйте устаревший код в pm-functions (/ usr / lib / pm-utils) после комментариев #, поскольку ядро ​​не поддерживает напрямую ..., (потому что текущее ядро ​​(после 3.6 что-то) поддерживает напрямую). Верните этот код и вставьте часть do_suspend () вместо do_suspend_hybrid ().

Устаревший код (приостановить, а затем перейти в спящий режим при вызове suspend_hybrid):

# since the kernel does not directly support hybrid sleep, we do
# something else -- suspend and schedule an alarm to go into
# hibernate if we have slept long enough.
# Only do this if we do not need to do any special video hackery on resume
# from hibernate, though.
if [ -z "$SUSPEND_HYBRID_MODULE" -a -w "$PM_RTC/wakealarm" ] && \
    check_suspend && check_hibernate && ! is_set $HIBERNATE_RESUME_POST_VIDEO; \
    then
    SUSPEND_HYBRID_MODULE="kernel"
    do_suspend_hybrid() {
    WAKETIME=$(( $(cat "$PM_RTC/since_epoch") + PM_HIBERNATE_DELAY))
    echo >"$PM_RTC/wakealarm"
    echo $WAKETIME > "$PM_RTC/wakealarm"
    if do_suspend; then
        NOW=$(cat "$PM_RTC/since_epoch")
        if [ "$NOW" -ge "$WAKETIME" -a "$NOW" -lt $((WAKETIME + 30)) ]; then
        log "Woken by RTC alarm, hibernating."
        # if hibernate fails for any reason, go back to suspend.
        do_hibernate || do_suspend
        else
        echo > "$PM_RTC/wakealarm"
        fi
    else
        # if we cannot suspend, just try to hibernate.
        do_hibernate
    fi
    }
fi

Рекомендуемые. Еще проще использовать uswsusp, в то же время максимизируя преимущества s2both, т.е. s2both при приостановке. Поместите возвращенный код в do_suspend () часть модуля uswsusp (/usr/lib/pm-utils/module.d).

Возвращенный код (suspend_hybrid, когда вызывается suspend):

WAKETIME=$(( $(cat "$PM_RTC/since_epoch") + PM_HIBERNATE_DELAY))
echo >"$PM_RTC/wakealarm"
echo $WAKETIME > "$PM_RTC/wakealarm"
if do_suspend_hybrid; then
    NOW=$(cat "$PM_RTC/since_epoch")
    if [ "$NOW" -ge "$WAKETIME" -a "$NOW" -lt $((WAKETIME + 30)) ];             then
    log "Woken by RTC alarm, hibernating."
    # if hibernate fails for any reason, go back to suspend_hybrid.
    do_hibernate || do_suspend_hybrid
    else
    echo > "$PM_RTC/wakealarm"
    fi
else
    # when do_suspend is being called, convert to suspend_hybrid.
    do_suspend_hybrid
fi      

С помощью uswsusp мы можем видеть ход приостановки / гибернации и обратный процесс, отображаемый в тексте, даже мы можем прервать его, нажав клавишу backspace. Без uswsusp suspend / hibernate просто раздражающе появляется-исчезает, особенно когда срабатывает wakealarm и выполняется hibernate (s2disk в uswsusp). Установите период сна до гибернации в обычном месте в файле pm-functions.

# variables to handle hibernate after suspend support
PM_HIBERNATE_DELAY=900  # 15 minutes
PM_RTC=/sys/class/rtc/rtc0

Вот мод uswsusp: (помните, этот модуль вызывается из pm-функций, поэтому вставленные переменные одинаковы)

#!/bin/sh

# disable processing of 90chvt and 99video.
# s2ram and s2disk handle all this stuff internally.
uswsusp_hooks()
{
    disablehook 99video "disabled by uswsusp"
}

# Since we disabled 99video, we need to take responsibility for proper
# quirk handling.  s2ram handles all common video quirks internally,
# so all we have to do is translate the HAL standard options to s2ram options.
uswsusp_get_quirks()
{
    OPTS=""
    ACPI_SLEEP=0
    for opt in $PM_CMDLINE; do
        case "${opt##--quirk-}" in # just quirks, please
            dpms-on)       ;; # no-op
            dpms-suspend)      ;; # no-op
            radeon-off)        OPTS="$OPTS --radeontool" ;;
            reset-brightness)  ;; # no-op
            s3-bios)       ACPI_SLEEP=$(($ACPI_SLEEP + 1)) ;;
            s3-mode)       ACPI_SLEEP=$(($ACPI_SLEEP + 2)) ;;
            vbe-post)      OPTS="$OPTS --vbe_post" ;;
            vbemode-restore)   OPTS="$OPTS --vbe_mode" ;;
            vbestate-restore)  OPTS="$OPTS --vbe_save" ;;
            vga-mode-3)        ;; # no-op
            save-pci)          OPTS="$OPTS --pci_save" ;;
            none)          QUIRK_NONE="true" ;;
            *) continue ;;
        esac
    done
    [ $ACPI_SLEEP -ne 0 ] && OPTS="$OPTS --acpi_sleep $ACPI_SLEEP"
    # if we were told to ignore quirks, do so.
    # This is arguably not the best way to do things, but...
    [ "$QUIRK_NONE" = "true" ] && OPTS=""
}

# Since we disabled 99video, we also need to handle displaying
# help info for the quirks we handle.
uswsusp_help()
{
    echo  # first echo makes it look nicer.
    echo "s2ram video quirk handler options:"
    echo
    echo "  --quirk-radeon-off"
    echo "  --quirk-s3-bios"
    echo "  --quirk-s3-mode"
    echo "  --quirk-vbe-post"
    echo "  --quirk-vbemode-restore"
    echo "  --quirk-vbestate-restore"
    echo "  --quirk-save-pci"
    echo "  --quirk-none"
}

# This idiom is used for all sleep methods.  Only declare the actual
# do_ method if:
# 1: some other sleep module has not already done so, and
# 2: this sleep method can actually work on this system.
#
# For suspend, if SUSPEND_MODULE is set then something else has already
# implemented do_suspend.  We could just check to see of do_suspend was
# already declared using command_exists, but using a dedicated environment
# variable makes it easier to debug when we have to know what sleep module
# ended up claiming ownership of a given sleep method.
if [ -z "$SUSPEND_MODULE" ] && command_exists s2ram && \
    ( grep -q mem /sys/power/state || \
        ( [ -c /dev/pmu ] && check_suspend_pmu; ); ); then
    SUSPEND_MODULE="uswsusp"
    do_suspend()
    {
        WAKETIME=$(( $(cat "$PM_RTC/since_epoch") + PM_HIBERNATE_DELAY))
        echo >"$PM_RTC/wakealarm"
        echo $WAKETIME > "$PM_RTC/wakealarm"
        if do_suspend_hybrid; then
            NOW=$(cat "$PM_RTC/since_epoch")
            if [ "$NOW" -ge "$WAKETIME" -a "$NOW" -lt $((WAKETIME + 30)) ];             then
            log "Woken by RTC alarm, hibernating."
            # if hibernate fails for any reason, go back to suspend_hybrid.
            do_hibernate || do_suspend_hybrid
            else
            echo > "$PM_RTC/wakealarm"
            fi
        else
            # when do_suspend is being called, convert to suspend_hybrid.
            do_suspend_hybrid
        fi      
    }
fi

if [ -z "$HIBERNATE_MODULE" ] && \
    [ -f /sys/power/disk ] && \
    grep -q disk /sys/power/state && \
    [ -c /dev/snapshot ] &&
    command_exists s2disk; then
    HIBERNATE_MODULE="uswsusp"
    do_hibernate()
    {
        s2disk
    }
fi

if [ -z "$SUSPEND_HYBRID_MODULE" ] && 
    grep -q mem /sys/power/state && \
    command_exists s2both && \
    check_hibernate; then
    SUSPEND_HYBRID_MODULE="uswsusp"
    do_suspend_hybrid()
    {   
        uswsusp_get_quirks
        s2both --force $OPTS 
    }
    if [ "$METHOD" = "suspend_hybrid" ]; then
        add_before_hooks uswsusp_hooks
        add_module_help uswsusp_help
    fi
fi  
отметка
источник