ハイバネート
Ubuntu 22.04でのハイバネーション - Journal InTime(2023-01-03) を見て、自分の ThinkPad T14 Gen3 はそんなでもないけどサスペンド時にまあまあバッテリーが減るので、自分もハイバネートしようかと思ってやってみた。
ハイバネートの設定手順は上のブログに書いてあるのそのまま:
# swapoff -a300 # grep -q swapfile/etc/fstab || echo "/swapfile none swap sw 0 0" >> /etc/fstab # fallocate -l 32G /swapfile # chown 0 /swapfile # chmod 0600 /swapfile # mkswap /swapfile # swapon /swapfile # findmnt / -o UUID UUID 90263320-8701-4639-b7b9-9705677d9c7a # filefrag -v /swapfile |grep " 0:"| awk '{print $4}' 34816..
/etc/default/grub を編集:
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash resume=UUID=90263320-8701-4639-b7b9-9705677d9c7a resume_offset=34816"
# update-grub
メモリ 24GB なのでスワップは 32GB にした。 ファイルシステム上にあるスワップファイルの物理位置を指定するのってなんか怖いんだけど大丈夫なのかな。 スワップ専用パーテイションを用意する方が安全なんじゃないかと思ってしまう。
ハイバネートのテスト:
# systemctl hibernate
ちゃんとハイバネートして、電源ボタンで復帰すればOK。
でも復帰時に画面が真っ暗のままで syslog に延々と [drm] *ERROR* Fault errors on pipe A: 0x00000080
が出力されてしまう。
その状態で Ctrl-Alt-F1 押して Alt-F7 を押すとログイン画面が表示されてログも止まるんだけど、ログがすごい勢いで溜まってディスクを圧迫するので止めたい。
どうやらカーネル 6.0.3 で直ってるらしいので、mainline から 6.0.19 を取ってきてインストールしたら直った。
6.1 を使ったほうがいいのかな、実は…。
蓋を閉じたときにハイバネート
Xubuntu は蓋を閉じたときの振る舞いとしてハイバネートを設定できない。 何かやればできるようになるのかもしれないけど、軽くググったくらいだと見つからなかったので自力でなんとかする。
LID イベントを拾えればいいので、入力デバイスを調べる:
% sudo evtest No device specified, trying to scan all of /dev/input/event* Available devices: /dev/input/event0: Sleep Button /dev/input/event1: Lid Switch /dev/input/event10: sof-hda-dsp Mic /dev/input/event11: sof-hda-dsp Headphone /dev/input/event12: sof-hda-dsp HDMI/DP,pcm=3 /dev/input/event13: sof-hda-dsp HDMI/DP,pcm=4 /dev/input/event14: sof-hda-dsp HDMI/DP,pcm=5 /dev/input/event15: Integrated Camera: Integrated C /dev/input/event16: rkremap /dev/input/event2: Power Button /dev/input/event3: AT Translated Set 2 keyboard /dev/input/event4: ThinkPad Extra Buttons /dev/input/event5: ELAN0676:00 04F3:3195 Mouse /dev/input/event6: TPPS/2 Elan TrackPoint /dev/input/event7: Video Bus /dev/input/event8: Intel HID events /dev/input/event9: ELAN0676:00 04F3:3195 Touchpad Select the device event number [0-16]: ^C
/dev/input/event1
がそれっぽい。
自作 gem の rkremap をインストールした状態で、こんな感じにすると蓋を閉じたイベントを拾って systemctl hibernate
を実行することができた。
% sudo ruby -rrkremap -e 'dev = Rkremap::Evdev.new("/dev/input/event1"); dev.grab; loop{e = dev.read_event; system("systemctl hibernate") if e.ev_type == 5 && e.value == 1 }'
grab してるので普通の電源設定の方のサスペンドとかが動いちゃうこともない。 もっと簡単な方法もあるような気がするけどまあいいや。
サスペンドしてしばらくしてからハイバネート
ハイバネートはサスペンドに比べると復帰までに時間が掛かるので、蓋を閉じるたびにハイバネートするのはいまいち。
サスペンドしてしばらくしてからハイバネートする suspend-then-hibernate
というのがあったので、これを使ってみる。
% sudo ruby -rrkremap -e 'dev = Rkremap::Evdev.new("/dev/input/event1"); dev.grab; loop{e = dev.read_event; system("systemctl suspend-then-hibernate") if e.ev_type == 5 && e.value == 1 }'
サスペンドしてからハイバネートするまでの時間は /etc/systemd/sleep.conf の HibernateDelaySec
で設定できる。デフォルトは 120min
らしい。ちょっと長いので 30min
にしてみた。
勝手にハイバネートが解除される
これで完成!…と思ったけど、蓋閉じてるのになぜか普通に電源が入ってバッテリを食い尽くしてサスペンドになっていたことがあった。
systemctl hibernate
を何回か実行して試してみたら 4〜5回に1回くらいはハイバネート直後に復帰しちゃう。
復帰トリガー - ArchWiki を見て、次のように対処してみた。
S4(ハイバネート)の復帰トリガーとして有効なものをリスト:
% cat /proc/acpi/wakeup | grep 'S4.*enabled' PEG0 S4 *enabled pci:0000:00:06.0 TXHC S4 *enabled pci:0000:00:0d.0 TDM0 S4 *enabled pci:0000:00:0d.2 TDM1 S4 *enabled pci:0000:00:0d.3 TRP0 S4 *enabled pci:0000:00:07.0 TRP2 S4 *enabled pci:0000:00:07.2 AWAC S4 *enabled platform:ACPI000E:00 LID S4 *enabled platform:PNP0C0D:00
LID
は蓋なので有効でもいい。それ以外はよくわからなかったけど echo XXX > /proc/acpi/wakeup
で全部無効化した。
この状態で試してみたら勝手に復帰しちゃうことはなくなったっぽいので、この設定を永続化する。 udev をいじったりすると永続化設定できるみたいなんだけど、難しくてよくわからなかったので、起動スクリプトを作った。
/etc/init.d/disable-wakeup:
#!/bin/sh ### BEGIN INIT INFO # Default-Start: 2 3 4 5 ### END INIT INFO cat /proc/acpi/wakeup | grep 'S4.*enabled' | awk '{print $1}' | grep -v LID | while read x; do echo "$x" > /proc/acpi/wakeup done
というファイルを作って、 sudo update-rc.d disable-wakeup defaults
で Linux 起動時に自動実行されるようにした。
しばらく使ってみてるけど大丈夫っぽい。 念の為、電源設定で、バッテリ駆動時に無操作状態が15分続くとサスペンドするように設定しておいてある。