Jak przejść automatycznie z Suspend do Hibernacji?

53

Czy to możliwe, aby Ubuntu przeszło w stan hibernacji z Suspend, czyli „Suspend Sedation”?

To, czego szukam, to:
kiedy zamykam pokrywę, laptop przechodzi w tryb zawieszenia. Następnie, po określonym czasie (nawet jeśli bateria się rozładowuje), jeśli nadal go nie używam, powinien przełączyć się w stan hibernacji, aby oszczędzać energię baterii.

Na przykład, mój laptop jest skonfigurowany do zawieszenia, gdy zamknę pokrywę. Jeśli wtedy nie używam go przez cały dzień, bateria się rozładowuje, ponieważ nawet w trybie zawieszenia sprzęt nadal zużywa niewielką ilość energii, a bateria ostatecznie się rozładowuje. Chcę, aby móc powiedzieć Ubuntu, że nawet jeśli jest zawieszone, nadal musi przejść w stan hibernacji po kilku godzinach bezczynności.

Windows może to zrobić. Ubuntu można zaprogramować tak, aby przechodziło w tryb gotowości lub hibernacji w trybie timera, ale nie w obu przypadkach.

Sergey Stadnik
źródło
W moich badaniach znalazłem ten sam wątek Linux Mint, ale „Suspend Sedation” nie jest oficjalnym terminem Microsoft dla tej funkcji i, o ile wiem, został wymyślony przez użytkownika forum Linux Mint, który o nim wspominał.
ayan4m1
Czy jest lepsza nazwa tej funkcji?
Sergey Stadnik
O ile mi wiadomo, nie ma powszechnie akceptowanej nazwy tej funkcji. „Hybrid suspend” jest używane przez niektórych, „suspend sedation” jest używane przez tego jednego użytkownika forum Linux Mint, i słyszałem, że „hibernacja i zawieszenie” odnosiły się wcześniej do tego procesu. Microsoft oficjalnie nazywa to „uśpieniem hybrydowym”, przynajmniej dla Windows 7.
ayan4m1
2
@ ayan4m1 Zdaję sobie sprawę, że to stare pytanie, ale myślę, że ważne jest, aby to wyjaśnić. Sen Hyrbid nie jest tym samym, co „Sen, a następnie hibernacja po określonym czasie”. Sen hybrydowy po prostu hibernuje po utracie zasilania z powodu wyczerpania baterii. Zachowanie opisane przez OP nie wymaga włączenia Hybrid Sleep.
Paul,

Odpowiedzi:

20

W Ubuntu 18.04 jest o wiele łatwiej. W systemd dostępny jest nowy tryb wstrzymania, a następnie hibernacji . Aby rozpocząć korzystanie z tej funkcji, musisz utworzyć plik /etc/systemd/sleep.conf z następną zawartością:

[Sleep]
HibernateDelaySec=3600

Następnie możesz to przetestować za pomocą polecenia:

sudo systemctl suspend-then-hibernate

możesz edytować, HibernateDelaySecaby zmniejszyć opóźnienie do hibernacji.


Jeśli wszystko działa poprawnie, możesz zmienić akcję Zamknij pokrywkę, aby to zrobić, musisz edytować plik /etc/systemd/logind.conf

Musisz znaleźć opcję HandleLidSwitch=, odkomentować ją i zmienić na HandleLidSwitch=suspend-then-hibernate. Następnie musisz zrestartować usługę logd systemd (ostrzeżenie! Sesja użytkownika zostanie zrestartowana) za pomocą następnego polecenia:

sudo systemctl restart systemd-logind.service

To wszystko! Teraz możesz użyć tej ładnej funkcji.

PRIHLOP
źródło
To było na miejscu. Używanie go w Pop! _OS 18.10 (alias Ubuntu 18.10).
eduncan911
Świetnie dziękuję! Czy sleep.conf w jakiś sposób wpływa również na tryb hibernacji, czy tylko wpływa na zawieszenie, a następnie hibernację?
user2428107
@ user2428107 możesz przeczytać o opcjach w podręczniku systutorials.com/docs/linux/man/5-systemd-sleep
PRIHLOP
35

Rozwiązanie tego jest proste. Po pierwsze, po zawieszeniu i wznowieniu program PM-suspend wykonuje serię skryptów w /etc/pm/sleep.di /usr/lib/pm-utils/sleep.d. Więc moim rozwiązaniem jest dodanie skryptu, który wykonuje następujące czynności:

  1. Po zawieszeniu zapisz bieżącą godzinę i zarejestruj zdarzenie budzenia za pomocą rtcwake.
  2. Po wznowieniu sprawdź bieżący czas w porównaniu do czasu nagranego z góry. Jeśli minęło wystarczająco dużo czasu, prawdopodobnie obudziliśmy się z powodu zdarzenia timera rtc. W przeciwnym razie obudziliśmy się wcześnie z powodu zdarzenia użytkownika (takiego jak otwarcie ekranu laptopa).
  3. Jeśli obudziliśmy się z powodu timera rtc, natychmiast wydaj polecenie „pm-hibernacja”, aby przejść w stan hibernacji.

Oto skrypt, który to robi. Nazwij go 0000rtchibernatei umieść w /etc/pm/sleep.dkatalogu (0000 jest ważne, aby skrypt był wykonywany najpierw po zawieszeniu, a ostatni po wznowieniu).

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

Mam nadzieję, że ten kod pojawia się na tym forum (jest to mój pierwszy post tutaj).

Edytuj wartość limitu czasu autohibernate=7200u góry, bez względu na to, ile sekund będziesz spać przed przejściem w stan hibernacji. Obecna wartość powyżej wynosi 2 godziny. Pamiętaj, że Twój laptop obudzi się w tym czasie na kilka sekund, podczas gdy wykonuje funkcję hibernacji.

Jeśli więc planujesz umieścić laptopa w etui, nie zawieszaj go, ale zamiast tego hibernuj. W przeciwnym razie laptop może się przegrzać w esp. jeśli jest w ciasno przylegającym futerale (chociaż będzie włączony tylko przez kilka sekund do minuty).

Używam tej metody przez ostatnie kilka dni, jak dotąd była skuteczna (i uratowała mnie przed wyczerpaniem baterii tego popołudnia). Cieszyć się.

W przypadku innych dystrybucji Linuksa, które używają systemdi nowszych wersjach Ubuntu to powinien nadal działać, jeśli umieścić skrypt w /usr/lib/systemd/system-sleepzamiast /etc/pm/sleep.d. Również zamień /usr/sbin/pm-hibernatepolecenie na systemctl hibernate.

Derek Pressnall
źródło
To działało tutaj, ale dopiero po tym, jak przeskoczyłem do pliku, aby dodać X do wszystkich. Jestem ogromnym nowicjuszem i zajęło mi to 2 dni. Bardzo dobry skrypt i mam nadzieję, że pomoże to każdemu, kto może mieć problemy. Dziękuję Ci.
2
Byłby to użyteczny pakiet Ubuntu / Debian!
Petr Pudlák,
Zastanawiam się: czy nadal będzie to ważne dla Ubuntu 13.04? Potrzebuję dokładnie tego rozwiązania, ale nie chcę zadzierać z laptopem żony, jeśli okaże się, że psuje to nowe wersje.
Torben Gundtofte-Bruun
Dzięki za skrypt. Działa dla mnie dobrze na Ubuntu 14.04! Jednym z ulepszeń byłoby, gdyby laptop budził się do hibernacji, mógłby sprawdzić, czy jest podłączony do zasilania sieciowego. Jeśli tak, chciałbym, aby zawiesił się ponownie zamiast hibernować. Przywracanie ze stanu hibernacji trwa dłużej i tak naprawdę nie potrzebuję go do hibernacji, gdy jest podłączony ...
maddentim
Dziękuję bardzo!!!! Ten scenariusz to magia, o której marzyłem !!
yanpas,
12

Aby wyjaśnić, jak to działa (jest to podobne do systemu Windows) w prostych słowach: maszyna nie budzi się ze stanu gotowości, gdy bateria się rozładuje, aby móc zapisać stan maszyny na partycji wymiany, natychmiast zapisuje wszystko na partycji wymiany w trybie gotowości, a kiedy bateria się wyczerpie, odzyska energię po załadowaniu stanu z partycji wymiany (tak jak w przypadku hibernacji).

AFAIK linux będzie / powinien używać hybrydowego trybu gotowości / hibernacji zamiast „normalnego” trybu gotowości, jeśli wie, że działa na twoim sprzęcie. Możliwe jest również, że jest to obecnie wyłączone z powodu zbyt wielu błędów lub czegoś takiego;)

Jeśli lubisz eksperymentować, być może zobaczysz, czy możesz uzyskać dobre wyniki dzięki PM-Suspend-Hybrid .

Jeśli poniższe informacje mówią, że masz szczęście, to teoretycznie w systemie obsługiwane jest zawieszenie hybrydowe:

pm-is-supported --suspend-hybrid && echo "you're lucky"
JanC
źródło
1
Pojedynczy apostrof w twoim poleceniu powłoki może wprowadzać w błąd i dezorientować ... unikaj go.
ayan4m1
1
Bah, to dzieje się, gdy edytujesz wiersz poleceń osadzony w innym tekście, nie myśląc o nim jako o wierszu poleceń ... Dzięki i naprawione.
JanC
Nie ma problemu, tak, rozumiem różne przestrzenie głowy dla tych dwóch procesów.
ayan4m1
6

Możesz być zainteresowany s2both . Jest dostarczany przez pakiet uswsuspw Ubuntu 10.10. Zawiesza się na dysku, ale zamiast zamykać system zamiast tego umieszcza go w S3, co jest trybem zasilania zwykle kojarzonym z opcją „Zawieś” w Ubuntu. pm-suspend-hybrid to kolejne narzędzie, które rzekomo robi to samo.

Aby to zautomatyzować przy zamykaniu pokrywy, zapoznaj się z poniższym przewodnikiem, który pozwala uruchomić dowolny skrypt po wykryciu zdarzenia blokady:

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

Jeśli zdarzy ci się mieć ThinkPada, strona podręcznika użytkownika tpctlzawiera odwołanie do argumentu --pm-sedation-hibernate-from-suspend-timer, który wydaje się zapewniać funkcję, której szukasz. Ostrzegam cię przed wypróbowaniem tego na sprzęcie innym niż ThinkPad.

Dla porównania, przejrzałem stronę podręcznika dla hibernacji.conf ; wydawało się, że nie ma żadnych istotnych opcji, ale może być warte drugiego czytania.

ayan4m1
źródło
5

Ubuntu 16.04 - od zawieszenia / uśpienia do hibernacji po określonym czasie

Wygląda na to, że w Ubuntu 16.04 sprawy wyglądają trochę inaczej, więc kroki, które podjąłem, aby działały, to:

  1. Upewnij się, że hibernacja działa zgodnie z oczekiwaniami podczas uruchamiania

    systemctl hibernate
    
  2. Skopiuj oryginalny suspend.targetplik:

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

    Następnie edytuj plik /etc/systemd/system/suspend.targeti dodaj wiersz:

    Requires=delayed-hibernation.service
    

    do [Unit]sekcji tego pliku.

  3. Utwórz plik /etc/systemd/system/delayed-hibernation.serviceo następującej treści:

[Jednostka]
Opis = Opóźniony wyzwalacz hibernacji
Przed = zawiesić. Cel
Conflicts = hibernate.target hybrid-suspend.target
StopWhenUnneeded = true

[Usługa]
Wpisz = oneshot
RemainAfterExit = tak
ExecStart = / usr / local / bin / delayed-hibernation.sh pre suspend
ExecStop = / usr / local / bin / delayed-hibernation.sh post zawiesza

[Zainstalować]
WantedBy = sleep.target
  1. Utwórz plik konfiguracyjny /etc/delayed-hibernation.confskryptu o następującej treści:
# Plik konfiguracyjny dla skryptu „delayed-hibernation.sh”

# Określ czas (w sekundach) spędzony w trybie uśpienia przed hibernacją komputera
TIMEOUT = 1200 #in sekund, daje 20 minut
  1. Utwórz skrypt, który faktycznie wykona ciężką pracę.

    Utwórz plik /usr/local/bin/delayed-hibernation.shz zawartością:

#! / bin / bash
# Nazwa skryptu: opóźniona-berberacja.sh
# Cel: Auto hibernuje po okresie snu
# Edytuj zmienną `TIMEOUT` w pliku` $ hibernation_conf`, aby ustawić liczbę sekund do uśpienia.

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

# Sprawdzanie pliku konfiguracyjnego
Jeśli [ ! -f $ hibernacja_konf]; następnie
    echo „Brak pliku konfiguracyjnego („ $ hibernation_conf ”), przerywanie.”
    wyjście 1
fi
hibernation_timeout = $ (grep "^ [^ #]" $ hibernation_conf | grep "TIMEOUT =" | awk -F '=' '{print 2 $}' | awk -F '#' '{print $ 1}' | tr -d „[[\ t]]”)
if ["$ hibernation_timeout" = ""]; następnie
    echo „Brak parametru„ TIMEOUT ”z pliku konfiguracyjnego („ $ hibernation_conf ”), przerywanie.”
    wyjście 1
elif [[! „$ hibernation_timeout” = ~ ^ [0-9] + $]]; następnie
    echo „Zły” parametr TIMEOUT („$ hibernacja_czas”) w pliku konfiguracyjnym („$ hibernacja_konf”), oczekiwana liczba sekund, przerwanie. ”
    wyjście 1
fi

# Przetwarzanie podanych parametrów
if ["$ 2" = "suspend"]; następnie
    curtime = $ (data +% s)
    if [„$ 1” = „pre”]; następnie
        if [-f $ hibernation_fail]; następnie
            echo „Wykryto nieudaną hibernację, pomijam ustawienie timera budzenia RTC”.
        jeszcze
            echo „Zawieszenie wykryte. Czas nagrywania, ustaw zegar RTC”
            echo „$ curtime”> $ hibernation_lock
            rtcwake -m no -s $ hibernation_timeout
        fi
    elif [„$ 1” = „post”]; następnie
        if [-f $ hibernation_fail]; następnie
            rm $ hibernation_fail
        fi
        if [-f $ hibernation_lock]; następnie
            sustime = $ (cat $ hibernation_lock)
            rm $ hibernation_lock
            if [$ (($ curtime - $ sustime)) -ge $ hibernation_timeout]; następnie
                echo „Wykryto automatyczne wznawianie działania po zawieszeniu. Hibernacja ...”
                hibernacja systemctl
                jeśli [$? -ne 0]; następnie
                    echo „Automatyczna hibernacja nie powiodła się. Zamiast tego próba zawieszenia.”
                    dotknij $ hibernation_fail
                    systemctl zawiesza
                    jeśli [$? -ne 0]; następnie
                        echo „Automatyczne hibernacja i zawieszenie przełączania awaryjnego nie powiodło się. Nic więcej nie można spróbować.”
                    fi
                fi
            jeszcze
                echo „Wykryto ręczne wznowienie działania po zawieszeniu. Kasowanie timera RTC”
                rtcwake -m wyłącz
            fi
        jeszcze
            echo „Plik„ $ hibernation_lock ”nie został znaleziony, nic nie można zrobić”
        fi
    jeszcze
        echo „Nierozpoznany pierwszy parametr:„ $ 1 ”, oczekiwany„ przed ”lub„ po ”
    fi
jeszcze
    echo "Ten skrypt jest przeznaczony do uruchomienia przez systemctl delayed-hibernation.service (oczekiwany drugi parametr:„ suspend ”)”
fi
  1. Ustaw skrypt jako wykonywalny:
chmod 755 /usr/local/bin/delayed-hibernation.sh

Sporo czasu zajęło mi napisanie tego skryptu na podstawie innych odpowiedzi w tym wątku. Rzeczy, które znalazłem w Internecie, takie jak https://bbs.archlinux.org/viewtopic.php?pid=1554259

Moja wersja skryptu próbuje poradzić sobie z wieloma problemami, takimi jak ponowne zawieszenie, jeśli hibernacja nie powiodła się, ale nie budzę się ponownie po określonym czasie w kółko.

  1. Zakładam, że ostatnim krokiem byłoby po prostu wykonanie

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

    aby upewnić się, że używane są nowe usługi / konfiguracje.

Aby sprawdzić dziennik usług, możesz użyć:

sudo systemctl status delay-hibernation.service

lub dla pełnego dziennika korzystania z usługi:

sudo journalctl -u delayed-hibernation.service

Normalny dziennik, który otrzymuję z uruchomionej usługi, to:

mile @ mile-ThinkPad: ~ $ sudo systemctl status delayed-hibernation.service 
● delayed-hibernation.service - Opóźniony wyzwalacz hibernacji
   Załadowano: załadowano (/etc/systemd/system/delayed-hibernation.service; włączony; preset dostawcy: włączony)
   Aktywny: nieaktywny (martwy)

09 czerwca 20:35:42 mile-ThinkPad systemd [1]: Uruchamianie wyzwalacza opóźnionej hibernacji ...
09 czerwca 20:35:42 mile-ThinkPad opóźniony-hibernation.sh [2933]: Zawieszenie wykryte. Czas nagrywania, ustaw zegar RTC
09 czerwca 20:35:42 mile-ThinkPad opóźniony-berberation.sh [2933]: rtcwake: zakładając, że RTC używa UTC ...
09 czerwca 20:35:42 mile-ThinkPad delayed-hibernation.sh [2933]: rtcwake: wakeup using / dev / rtc0 at Thu Jun 9 18:55:43 2016
09 czerwca 20:55:44 mile-ThinkPad systemd [1]: Uruchomiono opóźniony wyzwalacz hibernacji.
09 czerwca 20:55:44 mile-ThinkPad systemd [1]: opóźniony hibernacja. Usługa: Jednostka nie jest już potrzebna. Zatrzymanie.
09 czerwca 20:55:44 mile-ThinkPad systemd [1]: Zatrzymywanie opóźnionego wyzwalacza hibernacji ...
09 czerwca 20:55:44 mile-ThinkPad opóźniony-hibernation.sh [3093]: Wykryto automatyczne wznawianie po zawieszeniu. Hibernacja ...
09 czerwca 20:55:44 mile-ThinkPad systemd [1]: Zatrzymano opóźniony wyzwalacz hibernacji.
mile @ mile-ThinkPad: ~ $ 

Więc to by było na tyle, mam nadzieję, że to naprawdę komuś pomaga, ponieważ spędziłem dni próbując znaleźć odpowiednią kombinację konfiguracji i wersji skryptu, aby ta przydatna funkcja działała.

mihai.ile
źródło
Dzięki za odpowiedź, nadal działa to jak urok w Ubuntu 18.04. Nie udało mi się uzyskać odpowiedzi na powyższe odpowiedzi, wykonanie /bin/systemctl hibernatezawsze zwróciłoby 1 podczas działania w skrypcie systemd, nawet jeśli działa dobrze w wierszu poleceń.
eugenhu
4

Na wypadek, gdyby coś poszło nie pm-hibernatetak, wolę zawiesić komputer niż pozwolić mu działać. Możesz więc użyć:

   ...
/usr/sbin/pm-hibernate || /usr/sbin/pm-suspend
   ...
iiegn
źródło
3

Oto zaktualizowana wersja odpowiedzi Dereka Pressnalla, która działa z systemd i zawiera sugestię Eliasza Kagana , po prostu upuść ją w /usr/lib/systemd/system-sleep/delayed_hibernation.sh i uczyń ją wykonywalną:

#!/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
źródło
Działa to świetnie przez kilka miesięcy 15.10, ale coś o 16.04 uniemożliwia hibernację, nawet jeśli skrypt nadal działa.
Sean
@ Sean, czy próbowałeś obejścia tego wątku ?
Niccolò Maggioni
Dzięki za wskazanie mi właściwego kierunku. Utworzyłem usługę systemd (/etc/systemd/system/delayed-hibernation.service), która odwoływała się do powyższego skryptu, a następnie zmodyfikowałem /etc/systemd/system/suspend.target, aby wymagać usługi opóźnionej hibernacji.
Sean
2

Oto mój przepis (przetestowałem go na dwóch notebookach Ubuntu 16.04):

Umieść ten skrypt gdziekolwiek chcesz (ustawiam go na rootowanie /syspend.sh) i uczyń go wykonywalnym ( 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

Następnie utwórz systemowy cel: # touch /etc/systemd/system/suspend-to-sleep.target wklej tę treść:

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

Następnie włącz to # systemctl enable suspend-to-sleep.target.

Mam problem z jednym z notebooków: zamknięcie pokrywy nie uruchomiło tego celu. Stało się tak dzięki xfce4-power-manager. Istnieją dwa sposoby obejścia tego problemu. Pierwszym z nich jest edycja /etc/systemd/logind.confpliku i zastąpienie HandleLidSwitch=ignorego HandleLidSwitch=suspend. Ale będzie miało charakter ogólnosystemowy, więc właśnie dodałem dowiązanie symboliczne do mojego skryptu# ln -s /suspend.sh /etc/pm/sleep.d/0000rtchibernate

yanpas
źródło
1

Kolejne bardziej powszechne obejście, którego można użyć hybrid-sleep(podobnie jak Mac OS). Jeśli twój komputer obsługuje hibernację, możesz użyć tej funkcji:

systemctl hybrid-sleep

To polecenie powinno zawiesić i wysłać na dysk (hibernację) komputer. Po pewnym czasie komputer wyłączy się (po włączeniu użyje plików hibernacji, aby się obudzić).

ps: Wiem, że nie jest to dokładnie to, co opublikował PO, ale jest dość blisko

morhook
źródło
0

Nie zapomnij chmod + x tego pliku, aby był wykonywalny.

Istnieje inne rozwiązanie bez rtcwake, używając wakealarm w / sys / class / rtc / rtc0. Używaj przestarzałego kodu w funkcjach pm (/ usr / lib / pm-utils) po komentarzach #, ponieważ jądro nie obsługuje bezpośrednio ..., (ponieważ obecne jądro (po 3.6 coś) bezpośrednio obsługuje). Cofnij ten kod i wstaw część do_suspend () zamiast do_suspend_hybrid ().

Przestarzały kod (wstrzymaj, a następnie hibernuj, gdy wywołane zostanie zawieszenie_hybryd):

# 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

Zalecana. Jeszcze łatwiejszy w użyciu uswsusp, jednocześnie maksymalizując korzyści z s2both, tj. S2both po zawieszeniu. Umieść odwrócony kod w części do_suspend () modułu uswsusp (/usr/lib/pm-utils/module.d).

Cofnięty kod (suspend_hybrid po wywołaniu zawieszenia):

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      

Za pomocą uswsusp możemy zobaczyć postęp zawieszenia / hibernacji i proces odwrotny wyświetlany w tekście, nawet możemy go przerwać, naciskając klawisz Backspace. Bez uswsusp, zawieszanie / hibernacja po prostu pojawiają się - znikają irytujące, szczególnie gdy wakealarm jest uruchamiany i wykonuje hibernację (s2disk w uswsusp). Ustaw czas snu przed hibernacją w zwykłym miejscu w pliku funkcji pm.

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

Oto mod uswsusp: (pamiętaj, ten moduł jest wywoływany z funkcji pm, więc wstawiane zmienne są takie same)

#!/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  
znak
źródło