¿Cómo pasar automáticamente de Suspender a Hibernate?

53

¿Es posible hacer que Ubuntu entre en estado de hibernación desde Suspend, también conocido como "Suspender sedación"?

Lo que estoy buscando es esto:
cuando cierro la tapa, la computadora portátil se pone en suspensión. Luego, después de un tiempo predeterminado (incluso si la batería se está agotando) si todavía no la uso, debería ponerse en Hibernación para ahorrar energía de la batería.

Por ejemplo, mi computadora portátil está configurada para entrar en suspensión una vez que cierre la tapa. Si luego no lo uso durante todo el día, la batería se agota, porque incluso en modo de suspensión el hardware todavía consume una pequeña cantidad de energía, y la batería finalmente se descarga. Lo que quiero es poder decirle a Ubuntu que incluso si está suspendido, aún necesita entrar en Hibernate después de algunas horas de inactividad.

Windows puede hacer eso. Ubuntu puede ser programado para entrar en modo de espera o hibernación en el temporizador, pero no ambos.

Sergey Stadnik
fuente
En mi investigación encontré el mismo hilo de Linux Mint, pero "Suspender sedación" no es un término oficial de Microsoft para esa característica y, por lo que puedo decir, fue inventado por el usuario del foro de Linux Mint que lo mencionó.
ayan4m1
¿Hay un mejor nombre para esa función?
Sergey Stadnik
Por lo que puedo decir, no hay un nombre universalmente aceptado para la función. Algunos usan el "suspender híbrido", ese usuario del foro Linux Mint usa "suspender la sedación" y he escuchado "hibernar y suspender" para referirse al proceso antes. Microsoft se refiere oficialmente a él como "suspensión híbrida", al menos para Windows 7.
ayan4m1
2
@ ayan4m1 Me doy cuenta de que esta es una vieja pregunta, pero creo que es importante aclarar esto. El sueño hirbido no es lo mismo que "Dormir y luego hibernar después de un tiempo específico". El sueño híbrido simplemente se hiberna cuando se pierde la energía, debido a que la batería se agota. El comportamiento descrito por el OP no requiere que se active la suspensión híbrida.
Paul

Respuestas:

20

En Ubuntu 18.04 es mucho más fácil. En systemd está disponible un nuevo modo suspender-luego-hibernar . Para comenzar a usar esta función, debe crear un archivo /etc/systemd/sleep.conf con el siguiente contenido:

[Sleep]
HibernateDelaySec=3600

Entonces puedes probarlo por comando:

sudo systemctl suspend-then-hibernate

puede editar HibernateDelaySecpara reducir el retraso para hibernar.


Si todo funciona bien, puede cambiar la Acción de cierre de la tapa, para hacerlo debe editar el archivo /etc/systemd/logind.conf

Necesita encontrar la opción HandleLidSwitch=, descomentarla y cambiar a HandleLidSwitch=suspend-then-hibernate. Luego debe reiniciar el servicio systemd-logind (¡advertencia! Su sesión de usuario se reiniciará) mediante el siguiente comando:

sudo systemctl restart systemd-logind.service

¡Eso es todo! Ahora puedes usar esta bonita función.

PRIHLOP
fuente
Esto fue perfecto. Utilizándolo en Pop! _OS 18.10 (también conocido como Ubuntu 18.10).
eduncan911
Brillante gracias! ¿Sleep.conf afecta al modo de hibernación de alguna manera también, o solo afecta a suspender y luego hibernar?
user2428107
@ user2428107 puede leer acerca de las opciones en systutorials.com/docs/linux/man/5-systemd-sleep
PRIHLOP
35

La solución a esto es simple. Primero, al suspender y reanudar, el programa pm-suspend ejecuta una serie de scripts en /etc/pm/sleep.dy /usr/lib/pm-utils/sleep.d. Entonces, mi solución es agregar un script que haga lo siguiente:

  1. Al suspender, registre la hora actual y registre un evento de activación usando rtcwake.
  2. Al reanudar, verifique la hora actual contra el tiempo registrado desde arriba. Si ha transcurrido suficiente tiempo, entonces probablemente despertamos debido al evento de temporizador rtc. De lo contrario, nos levantamos temprano debido a un evento del usuario (como abrir la pantalla del portátil).
  3. Si nos despertamos debido al temporizador rtc, inmediatamente emita un comando "pm-hibernate" para entrar en hibernación.

Aquí hay un script que hace esto. Póngale un nombre 0000rtchibernatey colóquelo en el /etc/pm/sleep.ddirectorio (el 0000 es importante, de modo que la secuencia de comandos se ejecute primero al suspender y la última al reanudar).

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

Esperemos que este código aparezca en este tablero de mensajes (esta es mi primera publicación aquí).

Edite el valor de tiempo de espera autohibernate=7200en la parte superior, a cuantos segundos quiera dormir antes de entrar en hibernación. El valor actual anterior es de 2 horas. Tenga en cuenta que su computadora portátil se DESPERTARÁ en ese momento durante unos segundos, mientras ejecuta la función de hibernación.

Entonces, si planea colocar su computadora portátil en un estuche, no suspenda, sino hiberne en su lugar. De lo contrario, su computadora portátil podría sobrecalentarse especialmente. si está en una funda antideslizante ajustada (aunque solo estará encendida durante unos segundos a un minuto).

He estado usando este método durante los últimos días, hasta ahora ha sido exitoso (y me salvó de una batería agotada esta tarde). Disfrutar.

Para otras distribuciones de Linux que usan systemdy versiones más nuevas de Ubuntu, esto debería funcionar si coloca el script en /usr/lib/systemd/system-sleeplugar de /etc/pm/sleep.d. Además, reemplace el /usr/sbin/pm-hibernatecomando con systemctl hibernate.

Derek Pressnall
fuente
Funcionó aquí, pero solo después de que modifiqué el archivo para agregar X a todos. Soy un novato enorme y me llevó 2 días darme cuenta. Muy buen guión y espero que esto ayude a quien tenga problemas. Gracias.
2
¡Esto haría un paquete útil de Ubuntu / Debian!
Petr Pudlák
Solo me pregunto: ¿esto todavía sería válido para Ubuntu 13.04? Necesito exactamente esta solución, pero no quiero meterme con la computadora portátil de mi esposa si resulta que rompe las cosas en las versiones más nuevas.
Torben Gundtofte-Bruun
Gracias por el guion. ¡Funciona bien para mí en Ubuntu 14.04! Una mejora sería si cuando la computadora portátil se activa para hibernar, podría verificar si está conectada a la alimentación de CA. Si es así, me gustaría que se suspenda nuevamente en lugar de hibernar. Restaurar desde hibernación lleva más tiempo y realmente no necesito que hiberne cuando está enchufado ...
maddentim
¡¡¡¡Muchas gracias!!!! ¡Este guión es mágico con el que estaba soñando!
yanpas
12

Para explicar cómo funciona esto (esto es similar a Windows) en palabras simples: la máquina no se despierta del modo de espera cuando la batería está baja para poder guardar el estado de la máquina en la partición de intercambio, guarda todo en la partición de intercambio inmediatamente en espera, y cuando la batería se agota, se recuperará al cargar el estado de la partición de intercambio (como lo haría en caso de que hibernara).

AFAIK Linux utilizará / debería usar el modo de espera híbrido / hibernar en lugar del modo de espera "normal" si sabe que funciona para su hardware. También es posible que esto esté deshabilitado actualmente debido a demasiados errores o algo ...;)

Si te gusta experimentar, quizás puedas ver si puedes obtener buenos resultados con pm-suspend-hybrid .

Si lo siguiente dice que tienes suerte, entonces, en teoría, la suspensión híbrida es compatible con tu sistema:

pm-is-supported --suspend-hybrid && echo "you're lucky"
JanC
fuente
1
El único apóstrofe en su comando de shell podría ser engañoso y confuso ... por favor, escape.
ayan4m1
1
Bah, eso es lo que sucede cuando editas una línea de comando incrustada dentro de otro texto, sin pensarlo como una línea de comando ... Gracias y reparado.
JanC
No hay problema, sí entendí sobre los diferentes espacios de cabeza para los dos procesos.
ayan4m1
6

Te puede interesar s2both . Lo proporciona el paquete uswsuspen Ubuntu 10.10. Se suspende en el disco, pero en lugar de apagar el sistema, lo coloca en S3, que es el modo de energía generalmente asociado con la opción "Suspender" en Ubuntu. pm-suspend-hybrid es otra herramienta que pretende hacer lo mismo.

Para hacer esto automatizado al cerrar la tapa, eche un vistazo a la siguiente guía que le permite ejecutar un script arbitrario cuando se detecta un evento de tapa:

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

Si tiene un ThinkPad, la página de manual tpctlhace referencia a un argumento --pm-sedation-hibernate-from-suspend-timer, que parece proporcionar la función que está buscando. Le advertiría que no intente esto en hardware que no sea ThinkPad.

Como referencia, busqué en la página del manual hibernate.conf ; no parecía tener ninguna opción relevante, pero podría valer la pena una segunda lectura.

ayan4m1
fuente
5

Ubuntu 16.04: de suspender / dormir a hibernar después de un tiempo predeterminado

Parece que en Ubuntu 16.04 las cosas son un poco diferentes, así que los pasos que tomé para hacerlo funcionar fueron:

  1. Asegúrese de que la hibernación funcione como se esperaba cuando se ejecuta

    systemctl hibernate
    
  2. Copie el suspend.targetarchivo original :

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

    Luego edite el archivo /etc/systemd/system/suspend.targety agregue la línea:

    Requires=delayed-hibernation.service
    

    a la [Unit]sección de ese archivo.

  3. Cree el archivo /etc/systemd/system/delayed-hibernation.servicecon el siguiente contenido:

[Unidad]
Descripción = disparador de hibernación retardado
Antes = suspender.target
Conflictos = hibernate.target hybrid-suspend.target
StopWhenUnneeded = true

[Servicio]
Tipo = oneshot
RemainAfterExit = yes
ExecStart = / usr / local / bin / delayed-hibernation.sh pre suspend
ExecStop = / usr / local / bin / delayed-hibernation.sh post suspend

[Instalar en pc]
WantedBy = sleep.target
  1. Cree el archivo de configuración /etc/delayed-hibernation.confpara el script con el siguiente contenido:
# Archivo de configuración para el script 'delayed-hibernation.sh'

# Especifique el tiempo en segundos para pasar en modo de suspensión antes de que la computadora hiberne
TIEMPO DE ESPERA = 1200 # en segundos, da 20 minutos
  1. Cree el script que realmente hará el trabajo duro.

    Crear archivo /usr/local/bin/delayed-hibernation.shcon el contenido:

#! / bin / bash
# Nombre del script: delayed-hibernation.sh
# Propósito: el auto hiberna después de un período de sueño
# Edite la variable `TIMEOUT` en el archivo` $ hibernation_conf` para establecer el 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'

# Comprobando el archivo de configuración
Si [ ! -f $ hibernation_conf]; entonces
    echo "Falta el archivo de configuración ('$ hibernation_conf'), abortando".
    salida 1
fi
hibernation_timeout = $ (grep "^ [^ #]" $ hibernation_conf | grep "TIMEOUT =" | awk -F '=' '{print $ 2}' | awk -F '#' '{print $ 1}' | tr -d '[[\ t]]')
if ["$ hibernation_timeout" = ""]; entonces
    echo "Falta el parámetro 'TIMEOUT' del archivo de configuración ('$ hibernation_conf'), abortando".
    salida 1
elif [[! "$ hibernation_timeout" = ~ ^ [0-9] + $]]; entonces
    echo "Parámetro 'TIMEOUT' incorrecto ('$ hibernation_timeout') en el archivo de configuración ('$ hibernation_conf'), número esperado de segundos, abortando".
    salida 1
fi

# Procesar parámetros dados
if ["$ 2" = "suspender"]; entonces
    curtime = $ (fecha +% s)
    if ["$ 1" = "pre"]; entonces
        if [-f $ hibernation_fail]; entonces
            echo "Hibernación fallida detectada, omitiendo la configuración del temporizador de activación RTC".
        más
            echo "Suspender detectado. Tiempo de grabación, configurar temporizador RTC"
            echo "$ curtime"> $ hibernation_lock
            rtcwake -m no -s $ hibernation_timeout
        fi
    elif ["$ 1" = "publicación"]; entonces
        if [-f $ hibernation_fail]; entonces
            rm $ hibernation_fail
        fi
        if [-f $ hibernation_lock]; entonces
            sustime = $ (cat $ hibernation_lock)
            rm $ hibernation_lock
            if [$ (($ curtime - $ sustime)) -ge $ hibernation_timeout]; entonces
                echo "Reanudación automática de suspensión detectada. Hibernando ..."
                systemctl hibernate
                si [$? -ne 0]; entonces
                    echo "Hibernación automática falló. Intentando suspender en su lugar".
                    toque $ hibernation_fail
                    systemctl suspend
                    si [$? -ne 0]; entonces
                        echo "La hibernación automática y la suspensión de la conmutación por error fallaron. Nada más que probar".
                    fi
                fi
            más
                echo "Se ha detectado la reanudación manual de la suspensión. Borrado del temporizador RTC"
                rtcwake -m deshabilitar
            fi
        más
            echo "No se encontró el archivo '$ hibernation_lock', nada que hacer"
        fi
    más
        echo "Primer parámetro no reconocido: '$ 1', esperado 'pre' o 'post'"
    fi
más
    echo "Este script está destinado a ser ejecutado por systemctl delayed-hibernation.service (segundo parámetro esperado: 'suspender')"
fi
  1. Haga que el script sea ejecutable:
chmod 755 /usr/local/bin/delayed-hibernation.sh

Me tomó mucho tiempo escribir este script basado en otras respuestas en este hilo, cosas que encontré en Internet como https://bbs.archlinux.org/viewtopic.php?pid=1554259

Mi versión de la secuencia de comandos trata de resolver muchos problemas, como volver a suspender si la hibernación no tuvo éxito, pero no volver a despertar después del tiempo predeterminado una y otra vez.

  1. El último paso que supongo sería simplemente ejecutar

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

    para asegurarse de que se estén utilizando nuevos servicios / configuraciones.

Para verificar el registro del servicio, puede usar:

sudo systemctl status delayed-hibernation.service

o para un registro completo del uso del servicio:

sudo journalctl -u retraso-hibernación.service

Un registro normal que obtengo del servicio en ejecución es:

mile @ mile-ThinkPad: ~ $ sudo systemctl status retrasyed-hibernation.service 
● servicio de hibernación retrasada: desencadenante de hibernación retrasada
   Cargado: cargado (/etc/systemd/system/delayed-hibernation.service; activado; proveedor preestablecido: activado)
   Activo: inactivo (muerto)

09 de junio 20:35:42 mile-ThinkPad systemd [1]: Iniciando el desencadenante de hibernación retardado ...
09 de junio 20:35:42 mile-ThinkPad retrayed-hibernation.sh [2933]: Suspender detectado. Tiempo de grabación, configurar temporizador RTC
09 de junio 20:35:42 mile-ThinkPad delayed-hibernation.sh [2933]: rtcwake: suponiendo que RTC usa UTC ...
09 de junio 20:35:42 mile-ThinkPad delayed-hibernation.sh [2933]: rtcwake: wakeup using / dev / rtc0 at Thu Jun 9 18:55:43 2016
09 de junio 20:55:44 mile-ThinkPad systemd [1]: Iniciado el disparador de hibernación retrasada.
09 de junio 20:55:44 mile-ThinkPad systemd [1]: retraso-hibernación.service: ya no se necesita la unidad. Parandome, deteniendome.
09 de junio 20:55:44 mile-ThinkPad systemd [1]: Deteniendo el disparador de hibernación retardado ...
09 de junio 20:55:44 mile-ThinkPad delayed-hibernation.sh [3093]: reanudación automática de suspensión detectada. Hibernando ...
09 de junio 20:55:44 mile-ThinkPad systemd [1]: Detenido Disparador de hibernación retrasado.
mile @ mile-ThinkPad: ~ $ 

Así que esto sería todo, espero que realmente ayude a alguien, ya que pasé días tratando de encontrar la combinación correcta de configuraciones y versiones de script para que esta práctica función funcione.

mihai.ile
fuente
Gracias por la respuesta, esto todavía funciona como un encanto en Ubuntu 18.04. No pude obtener las respuestas anteriores para trabajar, la ejecución /bin/systemctl hibernatesiempre devolvería 1 cuando se ejecuta en el script systemd, a pesar de que funciona bien en la línea de comandos.
eugenhu
4

En caso de que algo salga mal pm-hibernate, preferiría suspender la computadora que dejarla funcionar. Entonces puedes usar:

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

Aquí está una versión actualizada de la respuesta de Derek Pressnall que funciona con SystemD e incluye la sugerencia de Elías Kagan , simplemente soltarlo en /usr/lib/systemd/system-sleep/delayed_hibernation.sh y hacerlo ejecutable:

#!/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
fuente
Esto funcionó muy bien durante varios meses en 15.10, pero algo sobre 16.04 impide que hiberne a pesar de que el script todavía se ejecuta.
Sean
@Sean, ¿has probado la solución en este hilo ?
Niccolò Maggioni
Gracias por señalarme en la dirección correcta. Creé un servicio systemd (/etc/systemd/system/delayed-hibernation.service) que hacía referencia a la secuencia de comandos anterior y luego modifiqué /etc/systemd/system/suspend.target para requerir el servicio de hibernación retardado.
Sean
2

Aquí está mi receta (la probé en dos portátiles Ubuntu 16.04):

Pon este script donde quieras (lo puse en la raíz /syspend.sh) y hazlo ejecutable ( 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

Luego cree el objetivo systemd: # touch /etc/systemd/system/suspend-to-sleep.target pegue este contenido:

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

Entonces habilítelo # systemctl enable suspend-to-sleep.target.

Me he enfrentado a un problema con el de los portátiles: cerrar la tapa no activó este objetivo. Esto se debió a xfce4-power-manager. Hay dos formas de solucionar este problema. El primero es editar el /etc/systemd/logind.confarchivo y reemplazarlo HandleLidSwitch=ignorecon HandleLidSwitch=suspend. Pero será todo el sistema, así que acabo de agregar un enlace simbólico a mi script# ln -s /suspend.sh /etc/pm/sleep.d/0000rtchibernate

yanpas
fuente
1

Otra solución más común que puede usar hybrid-sleep(como lo hace Mac OS). Si su computadora admite hibernación, puede usar esta función:

systemctl hybrid-sleep

Ese comando debe suspender y enviar al disco (hibernar) la computadora. Después de un tiempo, la computadora se apagará (cuando se encienda, usará los archivos de hibernación para despertarse).

PD: Sé que no es exactamente lo que publicó el OP, pero está bastante cerca

Morhook
fuente
0

No olvides chmod + x ese archivo, hazlo ejecutable.

Hay otra solución sin rtcwake, usando wakealarm en / sys / class / rtc / rtc0. Utilice el código obsoleto en las funciones pm (/ usr / lib / pm-utils) después de los comentarios # dado que el núcleo no admite directamente ..., (porque el núcleo actual (después de 3.6 algo) sí admite directamente). Revierta ese código y coloque la parte do_suspend () en lugar de do_suspend_hybrid ().

Código obsoleto (suspender e hibernar cuando se invoca 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

Recomendado. Aún más fácil de usar uswsusp mientras que al mismo tiempo maximiza el beneficio de s2both, es decir, s2both cuando se suspende. Ponga el código revertido en do_suspend () parte del módulo uswsusp (/usr/lib/pm-utils/module.d).

Código revertido (suspend_hybrid cuando se llama a suspender):

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      

Con uswsusp, podemos ver el progreso de la suspensión / hibernación y el proceso inverso que se muestra en el texto, incluso podemos abortarlo presionando la tecla de retroceso. Sin uswsusp, suspender / hibernar simplemente aparece-desaparece de manera molesta, especialmente cuando se activa wakealarm y ejecuta hibernate (s2disk en uswsusp). Establezca el período de sueño antes de hibernar en el lugar habitual en el archivo pm-functions.

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

Aquí está el mod uswsusp: (recuerde, este módulo se llama desde las funciones pm, por lo que las variables insertadas son las mismas)

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