66 votes

Comment passer automatiquement de Suspend à Hibernate ?

Est-il possible de faire en sorte qu'Ubuntu passe en état d'hibernation à partir de la suspension, alias "sédation de la suspension" ?

Ce que je cherche, c'est ça :
Lorsque je ferme le couvercle, l'ordinateur portable est mis en veille. Ensuite, après un temps prédéterminé (même si la batterie est forte), si je ne l'utilise toujours pas, il se met en veille prolongée pour économiser la batterie.

Par exemple, mon ordinateur portable est configuré pour se mettre en veille lorsque je ferme le couvercle. Si je ne l'utilise pas pendant toute une journée, la batterie se vide, car même en mode suspension, le matériel consomme toujours une petite quantité d'énergie, et la batterie finit par se décharger. Ce que je veux, c'est pouvoir dire à Ubuntu que même s'il est suspendu, il doit passer en Hibernation après quelques heures d'inactivité.

Windows peut le faire. Ubuntu peut être programmé pour se mettre en veille. oder Hibernation sur minuterie, mais pas les deux.

4voto

iiegn Points 141

Juste au cas où quelque chose tourne mal pendant pm-hibernate Je préfère mettre l'ordinateur en veille plutôt que de le laisser tourner. Donc vous pouvez utiliser :

   ...
/usr/sbin/pm-hibernate || /usr/sbin/pm-suspend
   ...

3voto

Voici une version mise à jour de La réponse de Derek Pressnall qui fonctionne avec systemd et comprend La suggestion d'Eliah Kagan il suffit de le déposer dans /usr/lib/systemd/system-sleep/delayed_hibernation.sh et le rendre exécutable :

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

2voto

Robert O. Points 11

Voici ma recette (je l'ai testée sur deux ordinateurs portables Ubuntu 16.04) :

Mettez ce script où vous voulez (je l'ai mis à la racine, /syspend.sh ) et le rendre exécutable ( 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

Puis créez la cible systemd : # touch /etc/systemd/system/suspend-to-sleep.target Collez ce contenu :

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

Puis l'activer # systemctl enable suspend-to-sleep.target .

J'ai rencontré un problème sur celui des ordinateurs portables : la fermeture du couvercle ne déclenchait pas cette cible. Ceci était dû à xfce4-power-manager. Il y a deux façons de contourner ce problème. La première consiste à modifier /etc/systemd/logind.conf et remplacer HandleLidSwitch=ignore con HandleLidSwitch=suspend . Mais ce sera dans tout le système, donc j'ai juste ajouté un lien symbolique à mon script. # ln -s /suspend.sh /etc/pm/sleep.d/0000rtchibernate

1voto

morhook Points 1467

Une autre solution de contournement plus courante que vous pouvez utiliser hybrid-sleep (comme le fait le Mac OS). Si votre ordinateur prend en charge la mise en veille prolongée, vous pouvez utiliser cette fonction :

systemctl hybrid-sleep

Cette commande devrait suspendre et envoyer sur disque (hiberner) l'ordinateur. Au bout d'un certain temps, l'ordinateur s'éteindra (au moment du démarrage, il utilisera les fichiers d'hibernation pour se réveiller).

p.s. : Je sais que ce n'est pas exactement ce que le PO a posté, mais c'est assez proche.

0voto

mark Points 19

N'oubliez pas de chmod +x ce fichier, pour le rendre exécutable.

Il y a une autre solution sans rtcwake, en utilisant wakealarm dans /sys/class/rtc/rtc0. Utilisez le code obsolète dans pm-functions (/usr/lib/pm-utils) après les commentaires #puisque le noyau ne supporte pas directement .... ('car le noyau actuel (après 3.6 quelque chose) le supporte directement). Revenir sur ce code et mettre la partie do_suspend() au lieu de do_suspend_hybrid().

Code obsolète (suspendre puis hiberner lorsque suspend_hybrid est appelé) :

# 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

Recommandé. Encore plus facile d'utiliser uswsusp tout en maximisant les avantages de s2both, c'est-à-dire s2both lors de la suspension. Mettre le code inversé dans la partie do_suspend() du module uswsusp (/usr/lib/pm-utils/module.d).

Code inversé (suspend_hybrid lorsque suspend est appelé) :

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      

Avec uswsusp, nous pouvons voir la progression de la suspension/hibernation et le processus inverse affiché en texte, même nous pouvons l'interrompre en appuyant sur backspace. Sans uswsusp, suspend/hibernate apparaît/disparaît de manière ennuyeuse, surtout lorsque l'alarme de réveil est déclenchée et que l'hibernation est exécutée (s2disk dans uswsusp). Définissez la période de sommeil avant hibernation à l'endroit habituel du fichier pm-functions.

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

Voici le mod uswsusp : (rappelez-vous, ce module est appelé depuis pm-functions donc les variables insérées sont les mêmes)

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

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X