Como ir automaticamente de Suspender para Hibernate?

53

É possível fazer o Ubuntu entrar no estado de Hibernate a partir do Suspend, também conhecido como "Suspend Sedation"?

O que estou procurando é o seguinte:
Quando fecho a tampa, o laptop é colocado em Suspender. Depois de um tempo pré-determinado (mesmo que a bateria esteja ficando forte), se eu ainda não a usar, ela deverá se colocar no Hibernate para economizar energia da bateria.

Por exemplo, meu laptop está configurado para entrar em Suspender quando eu fechar a tampa. Se não o uso durante todo o dia, a bateria fica descarregada, porque mesmo no modo de suspensão o hardware ainda consome uma pequena quantidade de energia e a bateria acaba descarregando. O que eu quero é poder dizer ao Ubuntu que, mesmo que esteja suspenso, ele ainda precisa entrar no Hibernate após algumas horas de inatividade.

O Windows pode fazer isso. O Ubuntu pode ser programado para entrar no modo de espera ou de hibernação no timer, mas não nos dois.

Sergey Stadnik
fonte
Em minha pesquisa, encontrei o mesmo thread do Linux Mint, mas "Suspend Sedation" não é um termo oficial da Microsoft para esse recurso e, pelo que sei, foi inventado pelo usuário do fórum do Linux Mint que o mencionou.
ayan4m1
Existe um nome melhor para esse recurso?
Sergey Stadnik 11/11
Até onde eu sei, não há um nome universalmente aceito para o recurso. "Hybrid suspend" é usado por alguns, "suspend sedation" é usado por esse usuário do fórum do Linux Mint, e ouvi "hibernate and suspend" usado para se referir ao processo antes. A Microsoft se refere oficialmente a ele como "suspensão híbrida", pelo menos para o Windows 7.
ayan4m1
2
@ ayan4m1 Sei que esta é uma pergunta antiga, mas acho importante esclarecer isso. O sono por Hyrbid não é o mesmo que "Dormir e hibernar depois de um tempo especificado". O sono híbrido simplesmente se torna hibernado quando a energia é perdida, devido ao esgotamento da bateria. O comportamento descrito pelo OP não requer que o Hybrid Sleep esteja ativado.
Paul #

Respostas:

20

No Ubuntu 18.04 é muito mais fácil. No systemd está disponível um novo modo de suspensão e hibernação . Para começar a usar esta função, você precisa criar um arquivo /etc/systemd/sleep.conf com o próximo conteúdo:

[Sleep]
HibernateDelaySec=3600

Então você pode testá-lo por comando:

sudo systemctl suspend-then-hibernate

você pode editar HibernateDelaySecpara reduzir o atraso da hibernação.


Se tudo funcionar bem, você pode alterar a ação Fechar tampa, para isso, é necessário editar o arquivo /etc/systemd/logind.conf

Você precisa encontrar a opção HandleLidSwitch=, descomentar e alterar para HandleLidSwitch=suspend-then-hibernate. Em seguida, você precisa reiniciar o serviço systemd-logind (aviso! A sessão do usuário será reiniciada) pelo próximo comando:

sudo systemctl restart systemd-logind.service

Isso é tudo! Agora você pode usar esta boa função.

PRIHLOP
fonte
Isso foi no local. Utilizando-o no Pop! _OS 18.10 (também conhecido como Ubuntu 18.10).
eduncan911 27/01
Brilhante obrigado! O sleep.conf também afeta o modo de hibernação de alguma forma ou afeta apenas a suspensão e o hibernação?
user2428107 27/02
@ user2428107 você pode ler sobre as opções no manual systutorials.com/docs/linux/man/5-systemd-sleep
PRIHLOP
35

A solução para isso é simples. Primeiro, ao suspender e retomar, o programa pm-suspend executa uma série de scripts em /etc/pm/sleep.de /usr/lib/pm-utils/sleep.d. Portanto, minha solução é adicionar um script que faça o seguinte:

  1. Ao suspender, registre a hora atual e registre um evento de ativação usando rtcwake.
  2. Ao retomar, verifique a hora atual em relação ao tempo gravado acima. Se tiver decorrido tempo suficiente, provavelmente acordamos devido ao evento do timer rtc. Caso contrário, acordamos cedo devido a um evento do usuário (como abrir a tela do laptop).
  3. Se acordamos devido ao timer rtc, emita imediatamente um comando "pm-hibernate" para entrar em hibernação.

Aqui está um script que faz isso. Nomeie-o 0000rtchibernatee coloque-o no /etc/pm/sleep.ddiretório (o 0000 é importante, para que o script seja executado primeiro na suspensão e por último no resumo).

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

Espero que este código seja exibido neste quadro de mensagens (este é o meu primeiro post aqui).

Edite o valor do tempo limite autohibernate=7200na parte superior, por quantos segundos você deseja dormir antes de entrar em hibernação. O valor atual acima é de 2 horas. Observe que seu laptop ACORDARÁ naquele momento por alguns segundos, enquanto estiver executando a função de hibernação.

Portanto, se você planeja colocar seu laptop em um estojo, não o suspenda, mas hiberne. Caso contrário, seu laptop poderá superaquecer em esp. se estiver em um estojo de encaixe apertado (embora esteja ligado apenas por alguns segundos a um minuto).

Eu tenho usado esse método nos últimos dois dias, até agora ele foi bem-sucedido (e me salvou de uma bateria descarregada esta tarde). Desfrutar.

Para outras distribuições Linux que usam systemdversões mais recentes do Ubuntu, isso ainda funcionará se você inserir o script em /usr/lib/systemd/system-sleepvez de /etc/pm/sleep.d. Além disso, substitua o /usr/sbin/pm-hibernatecomando por systemctl hibernate.

Derek Pressnall
fonte
Ele funcionou aqui, mas somente depois que eu modifiquei o arquivo para adicionar X a todos. Eu sou um novato enorme e demorei 2 dias para descobrir. Script muito bom e espero que isso ajude quem quer que esteja tendo problemas. Obrigado.
2
Isso tornaria um pacote Ubuntu / Debian útil!
Petr Pudlák
Apenas imaginando: isso ainda seria válido para o Ubuntu 13.04? Preciso exatamente dessa solução, mas não quero mexer no laptop da esposa, se isso acabar quebrando as coisas nas versões mais recentes.
Torben Gundtofte-Bruun
Obrigado pelo script. Funciona bem para mim no Ubuntu 14.04! Uma melhoria seria se, quando o laptop acordar para hibernar, pudesse verificar se está conectado à energia CA. Nesse caso, eu gostaria que ele fosse suspenso novamente em vez de hibernar. Restaurando a partir de hibernação leva mais tempo e eu realmente não precisa dele para hibernar quando ele está conectado ...
maddentim
Muito obrigado!!!! Esse roteiro é mágico que eu estava sonhando !!
yanpas
12

Para explicar como isso funciona (isso é semelhante ao Windows) em palavras simples: a máquina não acorda do modo de espera quando a bateria fica fraca para poder salvar o estado da máquina na partição swap, salva tudo na partição swap imediatamente no modo de espera, e quando a bateria acabar, ela se recuperará disso carregando o estado da partição swap (como faria no caso de hibernação).

O AFAIK linux deve / deve usar o modo de espera híbrido / hibernar em vez do modo de espera "normal" se souber que funciona para o seu hardware. Também é possível que isso esteja desativado no momento por causa de muitos bugs ou algo assim ...;)

Se você gosta de experimentar, talvez consiga ver bons resultados com o pm-suspend-hybrid .

Se o seguinte diz que você tem sorte, em teoria, a suspensão híbrida é suportada no seu sistema:

pm-is-supported --suspend-hybrid && echo "you're lucky"
JanC
fonte
11
O único apóstrofo no seu comando shell pode ser enganoso e confuso ... por favor, escape.
ayan4m1
11
Bah, é isso que acontece quando você edita uma linha de comando incorporada em outro texto, sem pensar nela como uma linha de comando ... Obrigado e corrigido.
JanC
Não tem problema, sim, entendi sobre os diferentes espaços de cabeça para os dois processos.
ayan4m1
6

Você pode estar interessado em s2both . É fornecido pelo pacote uswsuspno Ubuntu 10.10. Ele suspende para o disco, mas, em vez de desligar o sistema, coloca-o no S3, que é o modo de energia geralmente associado à opção "Suspender" no Ubuntu. pm-suspend-hybrid é outra ferramenta que pretende fazer a mesma coisa.

Para tornar isso automatizado na tampa, dê uma olhada no seguinte guia, que permite executar um script arbitrário quando um evento de tampa é capturado:

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

Se você possui um ThinkPad, a página de manual tpctlfaz referência a um argumento --pm-sedation-hibernate-from-suspend-timer, que parece fornecer o recurso que você está procurando. Eu o advertiria contra tentar isso em hardware não-ThinkPad.

Para referência, procurei na página de manual hibernate.conf ; não parecia ter opções relevantes, mas poderia valer uma segunda leitura.

ayan4m1
fonte
5

Ubuntu 16.04 - da suspensão / suspensão para a hibernação após um tempo predeterminado

Parece que no Ubuntu 16.04 as coisas são um pouco diferentes, então as etapas que tomei para fazê-lo funcionar foram:

  1. Verifique se o hibernate está funcionando conforme o esperado ao executar

    systemctl hibernate
    
  2. Copie o suspend.targetarquivo original :

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

    Em seguida, edite o arquivo /etc/systemd/system/suspend.targete adicione a linha:

    Requires=delayed-hibernation.service
    

    para a [Unit]seção desse arquivo.

  3. Crie o arquivo /etc/systemd/system/delayed-hibernation.servicecom o seguinte conteúdo:

[Unidade]
Descrição = Gatilho de hibernação atrasada
Antes = suspend.target
Conflitos = hibernate.target hybrid-suspend.target
StopWhenUnneeded = true

[Serviço]
Tipo = oneshot
RemainAfterExit = yes
ExecStart = / usr / local / bin / delayed-hibernation.sh pré-suspensão
ExecStop = / usr / local / bin / delayed-hibernation.sh pós suspensão

[Instalar]
WantedBy = sleep.target
  1. Crie o arquivo de configuração /etc/delayed-hibernation.confpara o script com o seguinte conteúdo:
# Arquivo de configuração para o script 'delayed-hibernation.sh'

# Especifique o tempo em segundos a ser gasto no modo de suspensão antes que o computador hiberne
TIMEOUT = 1200 #em segundos, dá 20 minutos
  1. Crie o script que realmente fará o trabalho duro.

    Crie um arquivo /usr/local/bin/delayed-hibernation.shcom o conteúdo:

#! / bin / bash
# Nome do script: delayed-hibernation.sh
Objetivo: Hibernar automaticamente após um período de sono
# Edite a variável `TIMEOUT` no arquivo` $ $ hibernation_conf` para definir o número de segundos para dormir.

hibernation_lock = '/ var / run / delayed-hibernation.lock'
hibernation_fail = '/ var / run / delayed-hibernation.fail'
hibernation_conf = '/ etc / delayed-hibernation.conf'

# Verificando o arquivo de configuração
E se [ ! -f $ hibernation_conf]; então
    echo "Arquivo de configuração ausente ('$ hibernation_conf'), interrompido."
    saída 1
fi
hibernation_timeout = $ (grep "^ [^ #]" $ hibernation_conf | grep "TIMEOUT =" | awk -F '=' '{print $ 2}' | awk -F '#' '{print $ 1}' | tr -d '[[\ t]]')
if ["$ hibernation_timeout" = ""]; então
    echo "Parâmetro 'TIMEOUT' ausente do arquivo de configuração ('$ hibernation_conf'), interrompido."
    saída 1
elif [[! "$ hibernation_timeout" = ~ ^ [0-9] + $]]; então
    echo "Parâmetro incorreto 'TIMEOUT' ('$ hibernation_timeout') no arquivo de configuração ('$ hibernation_conf'), número esperado de segundos, abortando."
    saída 1
fi

# Processando determinados parâmetros
if ["$ 2" = "suspender"]; então
    curtime = $ (data +% s)
    if ["$ 1" = "pré"]; então
        if [-f $ hibernation_fail]; então
            eco "Falha na hibernação detectada, ignorando a configuração do timer de ativação do RTC."
        outro
            eco "Suspender detectado. Tempo de gravação, definir temporizador RTC"
            eco "$ curtime"> $ hibernation_lock
            rtcwake -m não -s $ hibernation_timeout
        fi
    elif ["$ 1" = "postagem"]; então
        if [-f $ hibernation_fail]; então
            rm $ hibernation_fail
        fi
        if [-f $ hibernation_lock]; então
            sustime = $ (cat $ hibernation_lock)
            rm $ hibernation_lock
            if [$ (($ curtime - $ sustime)) -ge $ hibernation_timeout]; então
                echo "Resumo automático da suspensão detectada. Hibernando ..."
                systemctl hibernate
                se [$? -ne 0]; então
                    echo "Falha na hibernação automática. Tentando suspender."
                    toque em $ hibernation_fail
                    suspensão do systemctl
                    se [$? -ne 0]; então
                        echo "Falha na hibernação automática e suspensão do failover. Nada mais para tentar."
                    fi
                fi
            outro
                eco "Resumo manual da suspensão detectada. Limpando o timer RTC"
                desabilitar rtcwake -m
            fi
        outro
            eco "O arquivo '$ hibernation_lock' não foi encontrado, nada a fazer"
        fi
    outro
        echo "Primeiro parâmetro não reconhecido: '$ 1', esperado 'pré' ou 'pós'"
    fi
outro
    echo "Este script deve ser executado pelo systemctl delayed-hibernation.service (segundo parâmetro esperado: 'suspend')"
fi
  1. Torne o script executável:
chmod 755 /usr/local/bin/delayed-hibernation.sh

Demorei bastante até escrever este script com base em outras respostas deste tópico, coisas que encontrei na internet como https://bbs.archlinux.org/viewtopic.php?pid=1554259

Minha versão do script tenta lidar com muitos problemas, como suspender novamente se o hibernar não tiver sido bem-sucedido, mas não for ativado novamente após o tempo pré-determinado, repetidamente.

  1. Etapa final que eu assumo seria apenas executar

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

    para garantir que novos serviços / configurações estejam sendo usados.

Para verificar o log de serviço, você pode usar:

status do sudo systemctl delayed-hibernation.service

ou para um log completo do uso do serviço:

sudo journalctl -u delayed-hibernation.service

Um log normal que recebo do serviço em execução é:

mile @ mile-ThinkPad: ~ Status do sudo systemctl $ delayed-hibernation.service 
● delayed-hibernation.service - Gatilho de hibernação atrasada
   Carregado: carregado (/etc/systemd/system/delayed-hibernation.service; ativado; predefinição de fornecedor: ativado)
   Ativo: inativo (morto)

Jun 09 20:35:42 mile-ThinkPad systemd [1]: Iniciando o gatilho de hibernação atrasada ...
Jun 09 20:35:42 mile-ThinkPad delayed-hibernation.sh [2933]: Suspensão detectada. Tempo de gravação, ajuste o temporizador RTC
Jun 09 20:35:42 mile-ThinkPad delayed-hibernation.sh [2933]: rtcwake: assumindo que o RTC use o UTC ...
Jun 09 20:35:42 mile-ThinkPad delayed-hibernation.sh [2933]: rtcwake: ativação usando / dev / rtc0 em quinta-feira 9 de junho 18:55:43 2016
Jun 09 20:55:44 mile-ThinkPad systemd [1]: Iniciado Gatilho de hibernação atrasada.
Jun 09 20:55:44 mile-ThinkPad systemd [1]: delayed-hibernation.service: Unidade não é mais necessária. Parando.
Jun 09 20:55:44 mile-ThinkPad systemd [1]: Parando o gatilho de hibernação atrasada ...
Jun 09 20:55:44 mile-ThinkPad delayed-hibernation.sh [3093]: Reinício automático da suspensão detectado. Hibernando ...
Jun 09 20:55:44 mile-ThinkPad systemd [1]: Parado Gatilho de hibernação atrasada.
mile @ mile-ThinkPad: ~ $ 

Então é isso, espero que realmente ajude alguém, pois passei dias tentando descobrir a combinação certa de configurações e versões de script para fazer esse útil recurso funcionar.

mihai.ile
fonte
Obrigado pela resposta, isso ainda funciona como um encanto no Ubuntu 18.04. Não consegui que as respostas acima funcionassem, a execução /bin/systemctl hibernatesempre retornaria 1 ao executar no script systemd, mesmo que funcione bem na linha de comando.
eugenhu
4

Apenas no caso de algo dar errado durante pm-hibernateeu prefiro suspender o computador do que deixá-lo funcionar. Então você pode usar:

   ...
/usr/sbin/pm-hibernate || /usr/sbin/pm-suspend
   ...
iiegn
fonte
3

Aqui está uma versão atualizada da resposta de Derek Pressnall que funciona com systemd e inclui a sugestão de Eliah Kagan , basta soltá-la em /usr/lib/systemd/system-sleep/delayed_hibernation.sh e torná-lo executável:

#!/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
Niccolò Maggioni
fonte
Isso funcionou muito bem por vários meses nas 15.10, mas algo no 16.04 impede a hibernação, mesmo que o script ainda seja executado.
23416 Sean
@ Sean Você já tentou a solução alternativa neste segmento ?
Niccolò Maggioni
Obrigado por me apontar na direção certa. Criei um serviço systemd (/etc/systemd/system/delayed-hibernation.service) que referenciou o script acima e modifiquei /etc/systemd/system/suspend.target para exigir delayed-hibernation.service.
24416 Sean
2

Aqui está minha receita (testei em dois notebooks Ubuntu 16.04):

Coloque esse script onde quiser (eu o coloco como root /syspend.sh) e o torne executável ( 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

Em seguida, crie o destino do systemd: # touch /etc/systemd/system/suspend-to-sleep.target Cole este conteúdo:

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

Então habilite-o # systemctl enable suspend-to-sleep.target.

Eu enfrentei um problema no notebook: fechar a tampa não acionava esse alvo. Isso ocorreu devido ao xfce4-power-manager. Existem duas maneiras de solucionar esse problema. O primeiro é editar o /etc/systemd/logind.confarquivo e substituí-lo HandleLidSwitch=ignorepor HandleLidSwitch=suspend. Mas será em todo o sistema, então acabei de adicionar um link simbólico ao meu script# ln -s /suspend.sh /etc/pm/sleep.d/0000rtchibernate

yanpas
fonte
1

Outra solução alternativa mais comum que você pode usar hybrid-sleep(como o Mac OS). Se o seu computador suportar hibernação, você poderá usar este recurso:

systemctl hybrid-sleep

Esse comando deve suspender e enviar para o disco (hibernar) o computador. Depois de algum tempo, o computador será desligado (ao ligar, os arquivos de hibernação serão ativados).

ps: Eu sei que não é exatamente o que o OP postou, mas é bem próximo

morhook
fonte
0

Não se esqueça de chmod + x esse arquivo, torná-lo executável.

Existe outra solução sem o rtcwake, usando o wakealarm em / sys / class / rtc / rtc0. Faça uso de código obsoleto nas funções pm (/ usr / lib / pm-utils) após os comentários #since o kernel não suporta diretamente ..., (porque o kernel atual (após algo do 3.6) suporta diretamente). Reverta esse código e insira a parte do_suspend () em vez de do_suspend_hybrid ().

Código obsoleto (suspenda e hiberne quando o suspend_hybrid for chamado):

# 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

Recomendado. Ainda mais fácil de usar uswsusp, ao mesmo tempo, maximiza os benefícios do s2both, ou seja, s2both ao suspender. Coloque o código revertido na parte do_suspend () do módulo uswsusp (/usr/lib/pm-utils/module.d).

Código revertido (suspend_hybrid quando a suspensão é chamada):

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      

Com uswsusp, podemos ver o progresso de suspender / hibernar e o processo inverso exibido no texto, até podemos abortá-lo pressionando backspace. Sem o uswsusp, suspender / hibernar apenas parece desaparecer irritantemente, especialmente quando o wakealarm é acionado e executa o hibernar (s2disk em uswsusp). Defina o período de suspensão antes da hibernação no local usual no arquivo pm-functions.

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

Aqui está o mod uswsusp: (lembre-se, este módulo é chamado de pm-functions para que as variáveis ​​inseridas sejam as mesmas)

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