Ubuntu 16.04 - 在预定时间后从挂起/睡眠状态进入休眠状态

Ubuntu 16.04 - 在预定时间后从挂起/睡眠状态进入休眠状态

是否可以让 Ubuntu 从挂起状态进入休眠状态,又称“挂起镇静”?

我想要的是:
当我合上盖子时,笔记本电脑会进入挂起状态。然后,在预定的时间后(即使电池电量充足),如果我仍然不使用它,它应该进入休眠状态以节省电池电量。

例如,我的笔记本电脑设置为一旦合上盖子就进入挂起状态。如果我一整天都不使用它,电池就会没电,因为即使在挂起模式下,硬件仍然会消耗少量电量,并且电池最终会放电。我想要的是能够告诉 Ubuntu,即使它处于挂起状态,在几个小时不活动后它仍然需要进入休眠状态。

Windows 可以做到这一点。Ubuntu 可以编程进入待机状态或者按定时器休眠,但不能同时休眠。

答案1

Ubuntu 18.04 及更高版本更容易。systemd有新模式暂停然后休眠。要开始使用此功能,您需要创建一份文件/etc/systemd/sleep.conf内容如下:

[Sleep]
HibernateDelaySec=3600

然后就可以通过命令来测试了:

sudo systemctl suspend-then-hibernate

您可以进行编辑HibernateDelaySec以减少休眠延迟。


如果一切正常,您可以更改盖子关闭动作,为此您需要编辑文件/etc/systemd/logind.conf

您需要找到选项HandleLidSwitch=,取消注释并更改为HandleLidSwitch=suspend-then-hibernate。然后您需要通过以下命令重新启动 systemd-logind 服务(警告!您的用户会话将重新启动):

sudo systemctl restart systemd-logind.service

就这样!现在您可以使用这个好用的功能了。

答案2

解决方案很简单。首先,在挂起和恢复时,pm-suspend 程序会执行/etc/pm/sleep.d和中的一系列脚本/usr/lib/pm-utils/sleep.d。因此,我的解决方案是添加一个执行以下操作的脚本:

  1. 挂起时,记录当前时间并使用 rtcwake 注册唤醒事件。
  2. 恢复后,检查当前时间与上面记录的时间。如果已经过去了足够的时间,那么我们可能是由于 rtc 计时器事件而唤醒的。否则,我们是由于用户事件(例如打开笔记本电脑屏幕)而提前唤醒的。
  3. 如果我们由于 rtc 计时器而醒来,则立即发出“pm-hibernate”命令进入休眠状态。

下面是一个可以完成此操作的脚本。命名它0000rtchibernate并将其放在/etc/pm/sleep.d目录中(0000 很重要,因为脚本在挂起时首先执行,在恢复时最后执行)。

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

希望这个代码能够通过这个留言板传达(这是我在这里的第一篇帖子)。

在顶部编辑超时值autohibernate=7200,将其设置为进入休眠状态前需要休眠的秒数。上面的当前值为 2 小时。请注意,您的笔记本电脑将在执行休眠功能时被唤醒几秒钟。

因此,如果您打算将笔记本电脑放入保护套中,请不要暂停,而是休眠。否则,您的笔记本电脑可能会过热,尤其是当它放在紧密贴合的保护套中时(尽管它只会打开几秒钟到一分钟)。

过去几天我一直在使用这种方法,到目前为止效果不错(并且让我今天下午免于电池没电)。尽情享受吧。

对于使用较新 Ubuntu 版本的其他 Linux 发行systemd版,如果将脚本放在/usr/lib/systemd/system-sleep而不是 中,此方法仍然有效/etc/pm/sleep.d。此外,将/usr/sbin/pm-hibernate命令替换为systemctl hibernate

答案3

用简单的话来解释它的工作原理(这与 Windows 类似):当电池电量不足时,机器不会从待机状态唤醒以便将机器状态保存到交换分区,它会在待机状态下立即将所有内容保存到交换分区,当电池耗尽时,它将通过从交换分区加载状态来恢复(就像您休眠时一样)。

据我所知,如果 Linux 知道它适用于您的硬件,它将/应该使用混合待机/休眠而不是“正常”待机。也可能由于太多错误或其他原因,此功能目前被禁用... ;)

如果你喜欢尝试,也许你可以看看是否能得到好的结果pm-暂停-混合

如果以下情况表明您很幸运,那么理论上您的系统支持混合暂停:

pm-is-supported --suspend-hybrid && echo "you're lucky"

答案4

Ubuntu 16.04 - 在预定时间后从挂起/睡眠状态进入休眠状态

在 Ubuntu 16.04 上情况似乎有些不同,因此我采取了以下步骤使其正常运行:

  1. 确保运行时休眠功能按预期工作

    systemctl hibernate
    
  2. 复制原始suspend.target文件:

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

    然后编辑文件/etc/systemd/system/suspend.target并添加以下行:

    Requires=delayed-hibernation.service
    

    [Unit]该文件的部分。

  3. /etc/systemd/system/delayed-hibernation.service创建包含以下内容的文件:

[单元]
描述=延迟休眠触发器
之前=suspend.target
冲突=hibernate.target hybrid-suspend.target
StopWhenUnneeded=true

[服务]
类型=oneshot
退出后继续保留=是
ExecStart=/usr/local/bin/delayed-hibernation.sh 预挂起
ExecStop=/usr/local/bin/delayed-hibernation.sh 挂起后

[安装]
WantedBy=sleep.target
  1. 创建脚本的配置文件/etc/delayed-hibernation.conf,内容如下:
#“delayed-hibernation.sh”脚本的配置文件

# 指定计算机休眠前处于睡眠模式的时间(以秒为单位)
TIMEOUT=1200 #以秒为单位,表示 20 分钟
  1. 创建实际上完成艰苦工作的脚本。

    创建内容/usr/local/bin/delayed-hibernation.sh为以下内容的文件:

/bin/bash #!/bin/bash
#脚本名称:delayed-hibernation.sh
# 目的:睡眠一段时间后自动休眠
# 编辑“$hibernation_conf”文件中的“TIMEOUT”变量来设置睡眠秒数。

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

# 检查配置文件
如果 [ !-f $hibernation_conf ]; 那么
    echo "缺少配置文件('$hibernation_conf'),中止。"
    出口 1
hibernation_timeout=$(grep "^[^#]" $hibernation_conf | grep "TIMEOUT=" | awk -F'=' '{print $2}' | awk -F'#' '{print $1}' | tr -d '[[ \t]]')
如果 [ “$hibernation_timeout” = “” ]; 然后
    echo “配置文件('$hibernation_conf')中缺少'TIMEOUT'参数,中止。”
    出口 1
elif [[ !"$hibernation_timeout" =~ ^[0-9]+$ ]]; 然后
    echo "配置文件('$hibernation_conf')中的'TIMEOUT'参数('$hibernation_timeout')错误,预计秒数,中止。"
    出口 1

# 处理给定的参数
如果 [ “$2” = “暂停” ]; 然后
    curtime=$(日期+%s)
    如果 [ “$1” = “pre” ]; 然后
        如果[-f $hibernation_fail];则
            echo “检测到休眠失败,跳过设置 RTC 唤醒计时器。”
        别的
            echo "检测到暂停。录制时间,设置 RTC 计时器"
            回显“$curtime”> $hibernation_lock
            rtcwake -m 否 -s $休眠超时
    elif [ "$1" = "post" ]; 然后
        如果[-f $hibernation_fail];则
            rm $hibernation_fail
        如果[-f $ hibernation_lock];则
            sustime=$(猫$hibernation_lock)
            rm $hibernation_lock
            如果 [ $(($curtime - $sustime)) -ge $hibernation_timeout ]; 然后
                echo “检测到从暂停状态自动恢复。正在休眠……”
                systemctl 休眠
                如果 [ $? -ne 0 ]; 那么
                    echo “自动休眠失败。正在尝试暂停。”
                    触摸$hibernation_fail
                    systemctl 暂停
                    如果 [ $? -ne 0 ]; 那么
                        echo “自动休眠和挂起故障转移失败。没有其他可尝试。”
            别的
                echo “检测到从暂停状态手动恢复。清除 RTC 计时器”
                rtcwake-m禁用
        别的
            echo“未找到文件‘$hibernation_lock’,无需执行任何操作”
    别的
        echo "无法识别的第一个参数:'$1',预期为'pre'或'post'"
别的
    echo “此脚本旨在由 systemctl delayed-hibernation.service 运行(预期第二个参数:'suspend')”
  1. 使脚本可执行:
chmod 755 /usr/local/bin/delayed-hibernation.sh

我花了很长时间才根据这个帖子中的其他回复编写了这个脚本,这些回复是我在网上找到的,比如https://bbs.archlinux.org/viewtopic.php?pid=1554259

我的脚本版本尝试解决许多问题,例如,如果休眠不成功则再次进入挂起状态,但在预定时间之后不会再次唤醒。

  1. 我认为最后一步就是执行

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

    以确保新的服务/配置正在被使用。

要检查服务日志,您可以使用:

sudo systemctl status 延迟休眠服务.

或者查看完整的服务使用日志:

sudo journalctl -u 延迟休眠.服务

我从正在运行的服务中获取的正常日志是:

mile@mile-ThinkPad:~$ sudo systemctl status delayed-hibernation.service
● delayed-hibernation.service - 延迟休眠触发器
   已加载:已加载(/etc/systemd/system/delayed-hibernation.service;已启用;供应商预设:已启用)
   活跃:不活跃(死亡)

6月9日 20:35:42 mile-ThinkPad systemd[1]: 正在启动延迟休眠触发器...
6月9日 20:35:42 mile-ThinkPad delayed-hibernation.sh[2933]: 检测到暂停。记录时间,设置 RTC 计时器
6月9日 20:35:42 mile-ThinkPad delayed-hibernation.sh[2933]: rtcwake: 假设 RTC 使用 UTC ...
2016 年 6 月 9 日星期四 18:55:43,2016 年 6 月 9 日 20:35:42 mile-ThinkPad delayed-hibernation.sh[2933]: rtcwake: 使用 /dev/rtc0 唤醒
6月9日 20:55:44 mile-ThinkPad systemd[1]:已启动延迟休眠触发器。
6月9日 20:55:44 mile-ThinkPad systemd[1]: delayed-hibernation.service: 不再需要该单元。正在停止。
6月9日 20:55:44 mile-ThinkPad systemd[1]: 停止延迟休眠触发器...
6月09日 20:55:44 mile-ThinkPad delayed-hibernation.sh[3093]: 检测到自动从暂停状态恢复。正在休眠...
6月9日 20:55:44 mile-ThinkPad systemd[1]: 已停止延迟休眠触发器。
英里@英里-ThinkPad:~$

就是这样了,我希望它真的能帮助到某些人,因为我花了好几天的时间试图找出正确的配置和脚本版本组合,以使这个方便的功能发挥作用。

相关内容