web-dev-qa-db-ja.com

Linux:一定期間の睡眠後に冬眠する方法

Linuxで私が見逃しているWindowsの機能の1つは、次のとおりです。Windowsでは、ノートブックの蓋を閉じると、システムがRAMに一時停止します。しばらくすると(構成可能)、コンピューターが自動的に起動し、ディスクへの一時停止に進みます。 Linuxにはsuspend2bothモードが存在することは知っていますが、これはバッテリーがなくなる直前にディスクにサスペンドすることで機能します。これは私が避けようとしていることです。

編集:回答データで検索した後に見つかったより詳細な回答

https://askubuntu.com/questions/12383/how-to-go-automatically-from-suspend-into-hibernate

EDIT2:これらは、MSI WindU100でUbuntu11.04を使用して実行した手順です。

まず、ネットブックで休止状態が機能していなかったため、tuxoniceをインストールしました。副作用として、休止状態とウェイクアッププロセスは非常に高速で、非常に安定しています。唯一の欠点は、休止状態/再開時の表示がテキストモードであるということです。 tuxoniceをインストールする最も簡単な方法は、対応するppaを追加することです。 https://launchpad.net/~tuxonice/+archive/ppa

休止状態が機能すると、このスクリプトはすべての魔法を実行します

#!/bin/bash
# Script name: /etc/pm/sleep.d/00rtchibernate
# 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

自動休止状態の値を変更することにより、マシンがウェイクアップして即座に休止状態になるまでのスリープ時間を変更します。

注:rtcwakeをインストールする必要がある場合があります。すでにインストールしていますが、自分でパッケージをインストールしたかどうかを思い出せません。

5
DrNoone

systemdを使用するCentOS、Fedor、Redhatなどの他のディストリビューションの場合。スクリプトを/etc/pm/sleep.d/に配置する代わりに/usr/lib/systemd/system-sleep/に配置する代わりにスクリプトの場所を変更する必要があります。0000rtchibernate.shchmod +xを使用して実行可能にします。

最後に、スクリプトをsystemdと互換性を持たせるために、スクリプトにもいくつかの調整が必要です。簡単にするために、私は完全に書き直されたスクリプトを提供しています

#!/bin/bash
# Script name: /usr/lib/systemd/system-sleep/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=3600 #number is second
lock=/tmp/rtchibernate.lock
echo "$curtime $1" >>/tmp/autohibernate.log
if [ "$1" = "pre" ]
then
    # Suspending.  Record current time, and set a wake up timer.
    echo "$curtime" > $lock
    rtcwake -m no -s $autohibernate
fi

if [ "$1" = "post" ]
then
    # Coming out of sleep
    sustime=`cat $lock`
    rm $lock
    # Did we wake up due to the rtc timer above?
    if [ $(($curtime - $sustime)) -ge $autohibernate ]
    then
        # Then hibernate
        systemctl hibernate
    else
        # Otherwise cancel the rtc timer and wake up normally.
        rtcwake -m no -s 1
    fi
fi

autohibernate変数は数秒で適切と思われるように変更します。

4
Dr. Xperience

私はあなたが望むものは http://www.linuxcertif.com/man/8/rtcwake/ のようなものだと思います。これはデフォルトのS2R(別名スリープ)プログラムの代わりに使用できます。これにより、マシンが(たとえば)20分以上スリープ状態になっている場合にマシンがウェイクアップし、休止状態がトリガーされる可能性があります。

4
Haqa

そのファイルを_chmod +x_して、実行可能にすることを忘れないでください。

_/sys/class/rtc/rtc0_でrtcwakeを使用して、wakealarmを使用しない別のソリューションがあります。コメントの後のpm-functions(_/usr/lib/pm-utils_)で廃止されたコードを使用してください#カーネルは直接サポートしていないので...、( 'cos現在のカーネル(3.6以降)は直接サポートしています)。そのコードを元に戻し、do_suspend()の代わりにdo_suspend_hybrid()部分を配置します。

廃止されたコード(suspend_hybridが呼び出されると、サスペンドしてから休止状態になります):

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

推奨。 uswsuspをさらに使いやすくすると同時に、_s2both_、つまり_s2both when suspend_のメリットを最大化します。戻されたコードをuswsuspモジュールのdo_suspend()部分(_/usr/lib/pm-utils/module.d_)に配置します。

戻されたコード(サスペンドが呼び出されたときのsuspend_hybrid):

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

uswsuspを使用すると、一時停止/休止状態の進行状況と逆のプロセスがテキストで表示され、バックスペースを押して中止することもできます。 uswsuspがないと、サスペンド/ハイバネートが表示されます-特にwakealarmがトリガーされ、hibernate(uswsuspでは_s2disk_)を実行すると、煩わしく消えます。 _pm-functions_ファイルの通常の場所で休止状態になる前のスリープ期間を設定します。

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

これがuswsusp modです:(このモジュールは_pm-functions_から呼び出されるため、挿入される変数は同じです)

_#!/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
_
1
mark