จะไปโดยอัตโนมัติจาก Suspend สู่ Hibernate ได้อย่างไร


53

เป็นไปได้หรือไม่ที่จะทำให้ Ubuntu เข้าสู่สถานะไฮเบอร์เนตจาก Suspend หรือที่รู้จักว่า "Suspend Sedation"

สิ่งที่ฉันกำลังมองหาคือ:
เมื่อฉันปิดฝาแล็ปท็อปจะถูกวางใน Suspend จากนั้นหลังจากเวลาที่กำหนดไว้ล่วงหน้า (แม้ว่าแบตเตอรี่จะแข็งแกร่ง) หากฉันยังไม่ได้ใช้งานก็ควรใส่ตัวเองลงในไฮเบอร์เนตเพื่อประหยัดพลังงานแบตเตอรี่

ตัวอย่างเช่นแล็ปท็อปของฉันถูกตั้งค่าให้เข้าสู่ Suspend เมื่อฉันปิดฝา ถ้าฉันไม่ใช้งานตลอดทั้งวันแบตเตอรี่ก็จะแบนเนื่องจากแม้ในโหมด suspend ฮาร์ดแวร์ก็ยังใช้พลังงานเล็กน้อยและในที่สุดแบตเตอรี่ก็จะหมด สิ่งที่ฉันต้องการคือสามารถบอก Ubuntu ได้ว่าแม้ว่ามันจะถูกระงับ แต่ก็ยังต้องเข้าสู่โหมดไฮเบอร์เนตหลังจากไม่ได้ใช้งานเป็นเวลาหลายชั่วโมง

Windows สามารถทำได้ อูบุนตูสามารถตั้งโปรแกรมให้เข้าสู่โหมดสแตนด์บายหรือไฮเบอร์เนตตามเวลา แต่ไม่ใช่ทั้งสองอย่าง


ในการวิจัยของฉันฉันพบเธรด Linux Mint เหมือนกัน แต่ "Suspend Sedation" ไม่ใช่คำศัพท์อย่างเป็นทางการของ Microsoft สำหรับคุณลักษณะนั้นและเท่าที่ฉันสามารถบอกได้นั้นถูกคิดค้นโดยผู้ใช้ฟอรัม Linux Mint ที่กล่าวถึง
ayan4m1

มีชื่อที่ดีกว่าสำหรับคุณสมบัตินั้นหรือไม่?
Sergey Stadnik

เท่าที่ฉันสามารถบอกได้ไม่มีชื่อที่ยอมรับในระดับสากลสำหรับสถานที่ "Hybrid suspend" ถูกใช้โดยบางคน "suspend sedation" ถูกใช้โดยผู้ใช้ฟอรัม Linux Mint คนหนึ่งและฉันเคยได้ยิน "hibernate and suspend" เคยอ้างถึงกระบวนการก่อนหน้านี้ Microsoft อ้างอย่างเป็นทางการว่า "ไฮบริดสลีป" สำหรับ Windows 7 เป็นอย่างน้อย
ayan4m1

2
@ ayan4m1 ฉันรู้ว่านี่เป็นคำถามเก่า แต่ฉันคิดว่ามันเป็นสิ่งสำคัญที่จะชี้แจงนี้ Hyrbid sleep นั้นไม่เหมือนกับ "Sleep และ hibernate หลังจากเวลาที่กำหนด" ไฮบริดสลีปจะกลายเป็นไฮเบอร์เนตเมื่อไฟฟ้าดับโดยแบตเตอรี่หมด พฤติกรรมที่อธิบายโดย OP ไม่จำเป็นต้องเปิดใช้งานไฮบริดสลีป
Paul

คำตอบ:


20

ในUbuntu 18.04มันง่ายกว่ามาก ในsystemdใช้ได้โหมดใหม่Suspend-แล้วจำศีล ในการเริ่มใช้งานฟังก์ชั่นนี้คุณต้องสร้างไฟล์/etc/systemd/sleep.confด้วยเนื้อหาถัดไป:

[Sleep]
HibernateDelaySec=3600

จากนั้นคุณสามารถทดสอบโดยใช้คำสั่ง:

sudo systemctl suspend-then-hibernate

คุณสามารถแก้ไขHibernateDelaySecเพื่อลดความล่าช้าในการจำศีล


หากทุกอย่างทำงานได้ดีคุณสามารถเปลี่ยน Lid Close Action ได้คุณต้องแก้ไขไฟล์/etc/systemd/logind.conf

คุณต้องไปหาตัวเลือกHandleLidSwitch=, uncomment HandleLidSwitch=suspend-then-hibernateมันและเปลี่ยนไป จากนั้นคุณต้องรีสตาร์ทเซอร์วิส systemd-logind (คำเตือน! เซสชันผู้ใช้ของคุณจะถูกรีสตาร์ท) โดยคำสั่งถัดไป:

sudo systemctl restart systemd-logind.service

นั่นคือทั้งหมด! ตอนนี้คุณสามารถใช้ฟังก์ชั่นที่ดีนี้ได้แล้ว


นี่คือจุดที่ ใช้งานบน Pop! _OS 18.10 (หรือ Ubuntu 18.10)
eduncan911

ยอดเยี่ยมมากขอบคุณ! sleep.conf มีผลต่อโหมดไฮเบอร์เนตด้วยหรือไม่หรือมีผลกับโหมดหยุดชั่วคราวเท่านั้น
user2428107

@ user2428107 คุณสามารถอ่านเกี่ยวกับตัวเลือกต่างๆในคู่มือsystutorials.com/docs/linux/man/5-systemd-sleep
PRIHLOP

35

วิธีแก้ปัญหานี้ง่าย ครั้งแรกเมื่อระงับและดำเนินการโปรแกรม PM-ระงับการดำเนินการชุดของสคริปต์ในและ/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 ชั่วโมง โปรดทราบว่าแล็ปท็อปของคุณจะตื่นขึ้นมาในเวลานั้นเป็นเวลาสองสามวินาทีขณะที่มันกำลังเรียกใช้ฟังก์ชันไฮเบอร์เนต

ดังนั้นหากคุณวางแผนที่จะวางแล็ปท็อปของคุณไว้ในเคสอย่าเพิ่งระงับ แต่จำศีลแทน ไม่เช่นนั้นแล็ปท็อปของคุณอาจร้อนจัดโดยเฉพาะ ถ้าอยู่ในกล่องใส่อุปกรณ์ที่รัดแน่น (แม้ว่าจะเปิดเพียงไม่กี่วินาทีถึงหนึ่งนาที)

ฉันใช้วิธีนี้ในช่วงสองสามวันที่ผ่านมาจนถึงตอนนี้ก็ประสบความสำเร็จ (และช่วยฉันด้วยแบตเตอรี่ที่ตายในบ่ายวันนี้) สนุก.

สำหรับลินุกซ์อื่น ๆ ที่ใช้systemdและรุ่นใหม่ Ubuntu นี้ยังควรจะทำงานถ้าคุณวางสคริปต์ในแทน/usr/lib/systemd/system-sleep /etc/pm/sleep.dนอกจากนี้แทนที่คำสั่งด้วย/usr/sbin/pm-hibernatesystemctl hibernate


มันทำงานได้ที่นี่ แต่หลังจากฉัน chmoded ไฟล์เพื่อเพิ่ม X ให้กับทุกคน ฉันเป็นมือใหม่ตัวใหญ่และใช้เวลา 2 วันในการคิดออก สคริปต์ที่ดีมากและฉันหวังว่านี่จะช่วยให้ใครก็ตามที่มีปัญหา ขอขอบคุณ.

2
สิ่งนี้จะทำให้แพ็คเกจ Ubuntu / Debian มีประโยชน์!
Petr Pudlák

แค่สงสัยว่า: จะยังคงใช้ได้สำหรับ Ubuntu 13.04 หรือไม่ ฉันต้องการโซลูชันนี้อย่างแน่นอน แต่ฉันไม่ต้องการยุ่งกับแล็ปท็อปของภรรยาถ้ามันกลายเป็นสิ่งที่แตกต่างในรุ่นที่ใหม่กว่า
Torben Gundtofte-Bruun

ขอบคุณสำหรับสคริปต์ ทำงานได้ดีสำหรับฉันบน Ubuntu 14.04! การปรับปรุงอย่างหนึ่งคือหากเมื่อแล็ปท็อปตื่นขึ้นมาถึงโหมดไฮเบอร์เนตมันอาจตรวจสอบเพื่อดูว่าเสียบเข้ากับไฟ AC หรือไม่ ถ้าเป็นเช่นนั้นฉันอยากให้มันระงับอีกครั้งแทนที่จะจำศีล การกู้คืนจากโหมดไฮเบอร์เนตใช้เวลานานขึ้นและฉันไม่ต้องการใช้โหมดไฮเบอร์เนตเมื่อเสียบปลั๊ก ...
maddentim

ขอบคุณมาก!!!! สคริปต์นี้เป็นเวทย์มนตร์ที่ฉันใฝ่ฝัน !!
yanpas

12

เพื่ออธิบายวิธีการทำงาน (คล้ายกับ Windows) ในคำง่ายๆ: เครื่องไม่ตื่นจากโหมดเตรียมพร้อมเมื่อแบตเตอรี่เหลือน้อยเพื่อให้สามารถบันทึกสถานะของเครื่องไปยังพาร์ติชัน swap ได้มันจะบันทึกทุกอย่างในพาร์ติชัน swap ทันที ในโหมดแสตนด์บายและเมื่อแบตเตอรี่หมดแบตเตอรี่จะทำการกู้คืนจากสถานะนั้นโดยการโหลดสถานะจากพาร์ติชั่นสว็อป (เช่นเดียวกับที่คุณทำในกรณีที่คุณจำศีล)

ลินุกซ์ AFAIK จะ / ควรใช้ไฮบริดสแตนบาย / ไฮเบอร์เนตแทน "ปกติ" สแตนด์บายถ้ามันรู้ว่ามันทำงานได้ดีสำหรับฮาร์ดแวร์ของคุณ อาจเป็นไปได้ว่าสิ่งนี้ถูกปิดใช้งานในขณะนี้เนื่องจากมีข้อบกพร่องมากเกินไปหรือบางอย่าง ... ;)

หากคุณชอบการทดลองบางทีคุณสามารถดูว่าคุณจะได้รับผลลัพธ์ที่ดีด้วยpm-suspend-hybridหรือไม่

หากข้อความต่อไปนี้บอกว่าคุณโชคดีระบบสนับสนุนของคุณในแบบทฤษฎีไฮบริด:

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

1
อะพอสโทรฟีเดียวในคำสั่งเชลล์ของคุณอาจทำให้เข้าใจผิดและทำให้สับสน ... โปรดหลีกเลี่ยง
ayan4m1

1
เฮ้นั่นคือสิ่งที่เกิดขึ้นเมื่อคุณแก้ไข commandline ที่ฝังอยู่ในข้อความอื่นโดยไม่ต้องคิดว่ามันเป็น commandline ... ขอบคุณ & แก้ไข
JanC

ไม่มีปัญหาใช่เข้าใจเกี่ยวกับ headspaces ที่แตกต่างกันสำหรับทั้งสองกระบวนการ
ayan4m1

6

คุณอาจจะสนใจในs2both จัดทำโดยแพ็คเกจuswsuspใน Ubuntu 10.10 มันหยุดการทำงานของดิสก์ แต่แทนที่จะปิดระบบแทนที่จะวางไว้ใน S3 ซึ่งเป็นโหมดพลังงานที่มักจะเกี่ยวข้องกับตัวเลือก "Suspend" ใน Ubuntu pm-suspend-hybridเป็นอีกเครื่องมือหนึ่งที่อ้างว่าทำสิ่งเดียวกัน

ในการทำให้การปิดฝาแบบอัตโนมัตินี้ดูที่คำแนะนำต่อไปนี้ซึ่งช่วยให้คุณเรียกใช้สคริปต์โดยพลการเมื่อมีการปิดเหตุการณ์ฝา:

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

หากคุณมี ThinkPad ก็จะมี manpage สำหรับtpctlอ้างอิงถึงข้อโต้แย้ง--pm-sedation-hibernate-from-suspend-timerซึ่งดูเหมือนจะเป็นคุณสมบัติที่คุณต้องการ ฉันจะเตือนคุณไม่ให้ลองสิ่งนี้กับฮาร์ดแวร์ที่ไม่ใช่ของ ThinkPad

สำหรับการอ้างอิงฉันดู manpage เพื่อหาhibernate.conf ; ดูเหมือนจะไม่มีตัวเลือกที่เกี่ยวข้อง แต่อาจคุ้มค่ากับการอ่านครั้งที่สอง


5

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ด้วยเนื้อหาดังต่อไปนี้:

[Unit]
รายละเอียด = ทริกเกอร์จำศีลล่าช้า
ก่อน = suspend.target
ความขัดแย้ง = hibernate.target hybrid-suspend.target
StopWhenUnneeded = true

[บริการ]
พิมพ์ = Oneshot
RemainAfterExit = yes
ExecStart = / usr / local / bin / delay-hibernation.sh ก่อนระงับ
ExecStop = / usr / local / bin / delay-hibernation.sh ระงับการโพสต์

[ติดตั้ง]
WantedBy = sleep.target
  1. สร้างไฟล์กำหนดค่า /etc/delayed-hibernation.confสำหรับสคริปต์ด้วยเนื้อหาดังต่อไปนี้:
# ไฟล์การกำหนดค่าสำหรับสคริปต์ 'delay-hibernation.sh'

# ระบุเวลาเป็นวินาทีเพื่อใช้ในโหมดสลีปก่อนที่คอมพิวเตอร์จะจำศีล
TIMEOUT = 1200 # ในวินาทีให้เวลา 20 นาที
  1. สร้างสคริปต์ที่ใช้งานได้จริง

    สร้างไฟล์/usr/local/bin/delayed-hibernation.shด้วยเนื้อหา:

#! / bin / ทุบตี
# ชื่อสคริปต์: delay-hibernation.sh
# วัตถุประสงค์: จำศีลอัตโนมัติหลังจากช่วงเวลาแห่งการนอนหลับ
# แก้ไขตัวแปร `TIMEOUT` ในไฟล์` $ hibernation_conf` เพื่อกำหนดจำนวนวินาทีที่จะเข้าสู่โหมดสลีป

hibernation_lock = '/ var / วิ่ง / ล่าช้า hibernation.lock'
hibernation_fail = '/ var / ทำงาน / delayed-hibernation.fail'
hibernation_conf = '/ etc / ล่าช้า hibernation.conf'

# ตรวจสอบไฟล์กำหนดค่า
ถ้า [! -f $ hibernation_conf]; แล้วก็
    echo "ไฟล์การกำหนดค่าที่หายไป ('$ hibernation_conf') ถูกยกเลิก"
    ทางออก 1
Fi
hibernation_timeout = $ (grep "^ [^ #]" $ hibernation_conf | grep "TIMEOUT =" | awk -F '=' '{พิมพ์ $ 2}' | awk -F '#' '{พิมพ์ $ 1}' | tr -d '[[\ t]]')
ถ้า ["$ hibernation_timeout" = ""]; แล้วก็
    echo "พารามิเตอร์" TIMEOUT "หายไปจากไฟล์กำหนดค่า ('$ hibernation_conf') ยกเลิก
    ทางออก 1
elif [[! "$ hibernation_timeout" = ~ ^ [0-9] + $]]; แล้วก็
    echo "พารามิเตอร์ 'TIMEOUT' ไม่ดี ('$ hibernation_timeout') ในไฟล์กำหนดค่า ('$ hibernation_conf'), จำนวนวินาทีที่คาดไว้, ยกเลิก"
    ทางออก 1
Fi

# การประมวลผลพารามิเตอร์ที่กำหนด
ถ้า ["$ 2" = "ระงับ"]; แล้วก็
    curtime = $ (วันที่ +% s)
    ถ้า ["$ 1" = "ก่อน"]; แล้วก็
        ถ้า [-f $ hibernation_fail]; แล้วก็
            echo "ตรวจพบการไฮเบอร์เนตล้มเหลวข้ามการตั้งค่าตัวจับเวลา RTC wakeup"
        อื่น
            echo "ตรวจพบการหยุดชั่วคราวเวลาบันทึกตั้งตัวจับเวลา RTC"
            echo "$ curtime"> $ hibernation_lock
            rtcwake -m no -s $ hibernation_timeout
        Fi
    elif ["$ 1" = "โพสต์"]; แล้วก็
        ถ้า [-f $ hibernation_fail]; แล้วก็
            rm $ hibernation_fail
        Fi
        ถ้า [-f $ hibernation_lock]; แล้วก็
            sustime = $ (แมว $ hibernation_lock)
            rm $ hibernation_lock
            ถ้า [$ (($ curtime - $ ยั่งยืน)) -ge $ hibernation_timeout]; แล้วก็
                echo "ตรวจหาการดำเนินการต่ออัตโนมัติจากการระงับชั่วคราวกำลังจำ ...
                systemctl จำศีล
                ถ้า [$? -ne 0]; แล้วก็
                    echo "การจำศีลอัตโนมัติล้มเหลวพยายามที่จะระงับแทน"
                    แตะ $ hibernation_fail
                    systemctl ระงับ
                    ถ้า [$? -ne 0]; แล้วก็
                        echo "การไฮเบอร์เนตอัตโนมัติและหยุดการทำงานล้มเหลวล้มเหลวไม่มีสิ่งอื่นให้ลอง"
                    Fi
                Fi
            อื่น
                echo "ดำเนินการต่อด้วยตนเองจากการตรวจพบการระงับการล้างตัวจับเวลา RTC"
                rtcwake -m ปิดใช้งาน
            Fi
        อื่น
            echo "ไม่พบไฟล์ '$ hibernation_lock' ไม่มีอะไรให้ทำ"
        Fi
    อื่น
        echo "พารามิเตอร์แรกที่ไม่รู้จัก: '$ 1', คาดว่า 'ก่อน' หรือ 'โพสต์'"
    Fi
อื่น
    echo "สคริปต์นี้ตั้งใจให้รันโดย systemctl delay-hibernation.service (พารามิเตอร์ตัวที่สองที่คาดไว้: 'suspend')"
Fi
  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 delay-hibernation.service

หรือสำหรับบันทึกการใช้บริการที่สมบูรณ์:

sudo journalctl -u delay-hibernation.service

บันทึกปกติที่ฉันได้รับจากบริการที่ใช้คือ:

mile @ mile-ThinkPad: ~ $ sudo สถานะ systemctl ล่าช้า - hibernation.service 
●ล่าช้าไฮเบอร์เนตบริการ - ทริกเกอร์จำศีลล่าช้า
   โหลดแล้ว: โหลดแล้ว (/etc/systemd/system/delayed-hibernation.service; เปิดใช้งาน; ตั้งไว้ล่วงหน้าของผู้ขาย: เปิดใช้งาน)
   ใช้งาน: ไม่ได้ใช้งาน (ตาย)

มิ.ย. 09 20:35:42 mile-ThinkPad systemd [1]: การเริ่มต้นทริกเกอร์การไฮเบอร์เนตล่าช้า ...
มิ.ย. 09 20:35:42 ไมล์ - ThinkPad ล่าช้า --hibernation.sh [2933]: ตรวจพบการระงับ เวลาในการบันทึกตั้งตัวจับเวลา RTC
มิ.ย. 09 20:35:42 ไมล์ - ThinkPad ล่าช้า --hibernation.sh [2933]: rtcwake: สมมติว่า RTC ใช้ UTC ...
Jun 09 20:35:42 mile-ThinkPad ล่าช้า-hibernation.sh [2933]: rtcwake: wakeup using / dev / rtc0 at Thu Jun 9 18:55:43 2016
มิ.ย. 09 20:55:44 ไมล์ - ระบบ ThinkPad [1]: เริ่มทริกเกอร์การไฮเบอร์เนตล่าช้า
มิ.ย. 09 20:55:44 ไมล์ - ระบบ ThinkPad [1]: ล่าช้า - ไฮเบอร์เนสบริการ: ไม่ต้องการยูนิตอีกต่อไป การหยุด
09 มิ.ย. 20:55:44 Mile-ThinkPad systemd [1]: การหยุดทริกเกอร์การจำศีลล่าช้า ...
มิ. ย. 09 20:55:44 ไมล์ - ThinkPad ล่าช้า --hibernation.sh [3093]: ตรวจสอบประวัติอัตโนมัติจากการหยุดชั่วคราว จำศีล ...
มิ.ย. 09 20:55:44 Mile-ThinkPad systemd [1]: หยุดการกระตุ้นการจำศีลล่าช้า
ไมล์ @ ไมล์ ThinkPad: ~ $ 

ดังนั้นนี่คือมันฉันหวังว่ามันจะช่วยใครบางคนจริงๆตั้งแต่ฉันใช้เวลาหลายวันเพื่อหาการผสมผสานที่ลงตัวระหว่างการกำหนดค่าและเวอร์ชันของสคริปต์เพื่อให้คุณสมบัติที่มีประโยชน์นี้ทำงานได้


ขอบคุณสำหรับคำตอบสิ่งนี้ยังคงใช้งานได้เหมือนมีเสน่ห์บน Ubuntu 18.04 ฉันไม่สามารถรับคำตอบข้างต้นเพื่อทำงานการดำเนินการ/bin/systemctl hibernateจะกลับ 1 เมื่อทำงานในสคริปต์ systemd แม้ว่ามันจะทำงานได้ดีในบรรทัดคำสั่ง
eugenhu

4

ในกรณีที่มีสิ่งผิดปกติเกิดขึ้นในระหว่างที่pm-hibernateฉันต้องการให้คอมพิวเตอร์หยุดทำงานชั่วคราวกว่าปล่อยให้มันทำงาน ดังนั้นคุณสามารถใช้:

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

3

นี่คือคำตอบของDerek Pressnallรุ่นปรับปรุงที่ทำงานกับ systemd และรวมถึงข้อเสนอแนะของ Eliah Kaganเพียงวางไว้ใน/usr/lib/systemd/system-sleep/delayed_hibernation.shและทำให้มันปฏิบัติการได้:

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

สิ่งนี้ใช้ได้ดีเป็นเวลาหลายเดือนในวันที่ 15.10 แต่มีบางอย่างเกี่ยวกับ 16.04 ที่ป้องกันไม่ให้จำศีลแม้ว่าสคริปต์จะยังทำงานอยู่
ฌอน

@Sean คุณได้ลองวิธีแก้ปัญหาในหัวข้อนี้หรือไม่?
Niccolò Maggioni

ขอบคุณที่ชี้นำฉันในทิศทางที่ถูกต้อง ฉันสร้างเซอร์วิส systemd (/etc/systemd/system/delayed-hibernation.service) ที่อ้างถึงสคริปต์ข้างต้นแล้วแก้ไข /etc/systemd/system/suspend.target เพื่อให้ล่าช้า - hibernation.service
ฌอน

2

นี่คือสูตรของฉัน (ทดสอบในสองโน๊ตบุ๊ค Ubuntu 16.04):

ใส่สคริปต์นี้เมื่อใดก็ตามที่คุณต้องการ (ฉันใส่ไว้ในราก/syspend.sh) และทำให้มันปฏิบัติ ( 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

จากนั้นสร้างเป้าหมาย systemd: # touch /etc/systemd/system/suspend-to-sleep.target วางเนื้อหานี้:

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

# systemctl enable suspend-to-sleep.targetจากนั้นเปิดใช้งานได้

ฉันประสบปัญหากับสมุดบันทึกหนึ่งเล่ม: ฝาปิดไม่ได้กระตุ้นเป้าหมายนี้ นี่เป็นเพราะ xfce4-power-manager มีสองวิธีในการแก้ไขปัญหานี้ คนแรกคือการแก้ไข/etc/systemd/logind.confไฟล์และแทนที่ด้วยHandleLidSwitch=ignore HandleLidSwitch=suspendแต่มันจะเป็นระบบทั้งระบบดังนั้นฉันเพิ่งเพิ่ม symlink ไปยังสคริปต์ของฉัน# ln -s /suspend.sh /etc/pm/sleep.d/0000rtchibernate


1

วิธีแก้ปัญหาทั่วไปเพิ่มเติมอื่น ๆ ที่คุณสามารถใช้ได้hybrid-sleep(เช่นเดียวกับ Mac OS) หากคอมพิวเตอร์ของคุณรองรับการไฮเบอร์เนตคุณสามารถใช้คุณสมบัตินี้:

systemctl hybrid-sleep

คำสั่งนั้นควรหยุดและส่งไปยังดิสก์ (จำศีล) คอมพิวเตอร์ หลังจากเวลาหนึ่งคอมพิวเตอร์จะปิด (เมื่อเปิดเครื่องจะใช้ไฟล์ไฮเบอร์เนตเพื่อปลุก)

ps: ฉันรู้ว่ามันไม่ตรงกับที่ OP โพสต์ แต่มันค่อนข้างใกล้เคียง


0

อย่าลืมที่จะ chmod + x ไฟล์นั้นทำให้มันปฏิบัติการ

มีวิธีแก้ไขปัญหาอื่นที่ไม่มี rtcwake โดยใช้ wakealarm ใน / sys / class / rtc / rtc0 ทำให้ใช้รหัสล้าสมัยในฟังก์ชั่น pm (/ usr / lib / pm-utils) หลังจากความคิดเห็น #since เคอร์เนลไม่สนับสนุนโดยตรง ... , ('เพราะเคอร์เนลปัจจุบัน (หลังจาก 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 เมื่อถูกระงับ วางโค้ดการย้อนกลับใน do_suspend () ส่วนหนึ่งของโมดูล uswsusp (/usr/lib/pm-utils/module.d)

เปลี่ยนรหัส (suspend_hybrid เมื่อเรียกว่า 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      

ด้วย uswsusp เราสามารถเห็นความคืบหน้าของการหยุดชั่วคราว / จำศีลและกระบวนการย้อนกลับที่แสดงในข้อความแม้เราสามารถยกเลิกได้โดยการกด backspace หากไม่มี uswsusp ให้ระงับ / จำศีลเพียงแค่ปรากฏขึ้น - หายไปอย่างน่ารำคาญโดยเฉพาะอย่างยิ่งเมื่อ Wakealarm ถูกเรียกใช้และดำเนินการจำศีล (s2disk ใน uswsusp) กำหนดช่วงเวลาของการนอนหลับก่อนที่จะจำศีลในสถานที่ปกติในไฟล์ฟังก์ชั่นน

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

นี่คือ mod ของ uswsusp: (จำไว้ว่าโมดูลนี้ถูกเรียกจากฟังก์ชั่น pm เพื่อให้ตัวแปรที่ใส่เข้าไปเหมือนกัน)

#!/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  
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.