2013年5月22日 星期三

Linux 及 Mac 休眠的兩三事


Linux 這玩意,每次出問題後都讓我 "驚豔",今次我們來談談 Linux 上令人髮指的睡眠 / 休眠功能。

"睡眠" 及 "休眠" 在電腦中屬於電源管理的一個環節,真正的名字是 "Advanced Configuration and Power Interface" (ACPI),旨在用軟體控制電源的開關。很多人並不熟悉這個,除了它本身有些複雜之外,主要的原因是它需要軟硬體的深度搭配,如果做不好,就會發生一睡不醒或是無故醒來的慘劇。最好的例子就是 Windows 的睡眠或休眠功能幾乎是沒人用的,因為實在太多出包的案例,所以使用者很自然地被教育成 "不使用就直接關機",平常這樣做是沒有什麼影響,但如果你是個帶著筆電到處跑來跑去的人,每次在那裡開關機不僅很蠢,而且非常浪費時間。

對於 Mac 使用者來說,使用睡眠或休眠是再平常也不過的事了 [1],原因在於軟硬體的整合就是 Apple 的強項,由於軟硬體都是他們家指定的,品質的控管當然比較好。相較之下,Windows 及 Linux 必須安裝在各家 PC 中,自然很容易出現相容性問題,也難怪之前有則新聞說 "表現最好的 Windows 筆電:蘋果 MacBook Pro?",原因就出在於硬體的驅動程式,其他硬體廠商在缺乏軟體資源的情況下沒辦法寫得比 Apple 更好。

OK,如我前面的段落所說,睡眠及休眠其實是相當複雜的,嚴格來說有很多種,但是一般使用者沒必要知道全部,因為實際用到的幾乎不會超過三種,以我自己當例子,我使用過其中兩種,而最常用的只有一種。下面我來簡單地介紹一下:


以 Linux 中 pm 指令的操作說明為例,大約分為三種。
  1. pm-suspend:別名為 "Suspend to RAM" (STR),在 Mac OSX 裡就是 "Sleep",故我都稱它 "睡眠",為 Mac 桌機的預設值。pm-suspend 所做的事就是把系統當時的狀態保留在 RAM 裡,隨即切斷其餘大部分的電源 (如 CPU 及硬碟等)。由於 RAM 本來就是在裝這些東西,所以睡眠速度很快,而且喚醒時的回復速度也很快,一兩秒之內就可以搞定,但缺點就是電腦必須保持 RAM 的電力,不然資料就會流失,故 "睡眠" 本身相對耗電一些。
  2. pm-hibernate:別名為 "Suspend to Disk" (STD),在 Mac OSX 裡就是 "Hibernate",故我都稱它 "休眠",它是將記憶體紀錄的系統狀態全部儲存到硬碟中,以 Mac OSX  來說,儲存的位置為 /private/var/vm/sleepimage,而在 Linux 裡則是儲存在 swap 磁區裡,若 swap 不夠用則再寫到其他磁區 [2]。休眠的好處在於它相當省電,幾乎完全不耗電,把電源移除都沒有關係,開機之後就會回復到休眠前的狀態,但缺點就是進入休眠及喚醒的時間相當長,在過程中最好不要移動機器,因為休眠過程涉及硬碟的讀寫。
  3. pm-suspend-hybrid:這種休眠方式是上述兩者的總和,也就是記憶體及硬碟內都擺一份系統狀態檔,如此一來喚醒的速度很快,而且若電源被移除也有硬碟內的備份可供回復。由此可知,這種方法兼具上述兩者的優點,故在 Mac OSX 上被稱為 "Safe Sleep",意指 "就算失去電源也無所謂的安全睡眠",且為 Mac 筆電的預設值。然而,有得就有失,它連上述兩者的缺點也一併保留 -- 耗電、入睡時間長。
上面三種是最常見也最實用的三種電源管理方式,而各家作業系統所使用的名稱也不太相同,故使用前還是先看過定義再決定比較好。不過,應該有人注意到我在文章中有順道將 Mac OSX 使用的名稱一併附上,但為何我不將 Windows 使用的名稱也加入對照呢?原因在於 Windows 使用的名稱相當詭異,硬是跟 ACPI 規格的定義相悖,比如說 "Suspend to RAM" 在 Windows 內是 "Standby" (待命),而在 ACPI 的規格中,Standby 跟 Suspend to RAM 是完全不同的兩種東西,更討厭的是,綜合型的休眠方式 pm-suspend-hybrid (或 Safe Sleep) 在 Windows 中就是簡單的 "Sleep" 一字,十分容易讓人混淆,反正 Windows 用戶也很少使用睡眠或休眠,故乾脆不管它了 [3]。

OK,那 ..... 有什麼問題呢?大家請看下圖:


這是我家桌機的 Linux Mint 之 "系統設定值" > "電源" 的視窗擷圖,在此設定選項中我可以設定當系統閒置多久後即進入睡眠狀態,看起來很正常,但有兩個不方便的地方:
  1. 不能指定睡眠 / 休眠的模式
  2. 不能立即進入睡眠狀態
其實最主要的不便來自於第二點,因為我希望能將系統設定成 "不要暫停" (不要睡眠),讓睡眠的時間由我自己決定,我要它睡的時候它才睡,不要我去洗個澡或上個大號就睡了。當然,在要睡眠時進入這個選單中去設定也可以,但仍無法讓其直接進入睡眠狀態,只能設定閒置倒數時間,而且老是要進入這個選單中去調整很不方便。


Mac 上的作法

這樣的問題 (或說是需求) 在 Mac 上同樣也會發生,但要解決簡直是 "不費吹灰之力",比如說 Mac 筆電只要將螢幕蓋下即可 (如果這還不會我也認了),若為 Mac 桌機則可用特定的睡眠快速鍵,或是寫個 script 存放在桌面上,要睡眠時點兩下啟動即可,作法如下 ....
  1. 鍵盤快速鍵:同時按下下面三個鍵即可,但有些不附光碟機的 Mac 沒有 Eject 鍵,而一般鍵盤當然也沒有 Eject 鍵,更糟糕的是這個快速鍵是無法更改的 (不過我認為這個快速鍵組合遲早會被 Apple 改掉),所以很多 Mac 用戶無法使用這種方法。
    Command + Option + Eject
  2. 硬體快速鍵:按下電源鍵後可以直接啟動睡眠,可是電源鍵是實體按鈕,常按不知道會不會跟 iOS device 的 Home 鍵一樣變得不靈敏。
  3. AppleScript:打開 AppleScript 編寫程式,輸入以下指令並儲存成應用程式即可。
    Tell application "Finder" to sleep
  4. Shell script:打開文字編輯軟體,輸入以下指令並儲存成純文字 txt 檔,隨即改成 sh 檔及加入 "執行" 權限即可。
    pmset sleepnow
以上是大家所熟知的睡眠啟動方法,使用任何一種都可以,我是比較偏好第三種。此外,若要更改睡眠模式也很容易,只要使用別的 shell script (或稱 shell cammand,也就是俗稱的終端機指令),或是安裝 SmartSleep 來做自動化的調整即可,有此需求的人可以看這個網站 -- OSX: Changing Hibernation Mode

如何?如果是已經知道指令的人,不用兩分鐘就可以解決了,就算不知道指令,隨便搜尋一下也可以在半小時內解決。但是呢,就這麼一個簡單的需求,Linux 的複雜就是可以把你搞到瘋掉。


Linux 的 "自由"

Linux 最大的優勢就是 "自由",它不像 Google 搞的是假自由、假開放,它是玩真的。可是 "自由" 的代價也很明顯,就是 "混亂"

在這裡我先不提自由軟體的優劣,因為要扯這些歷史故事實在太累人了,我們只要從本文主旨 -- "電源管理" 就可以見微知著。如前幾段所述,我希望能找到一個快速睡眠的方法,所以我仿效在 Mac 上的作法,考慮快速鍵及 script。但是,Linux 幾乎沒有快速鍵這種東西,這裡每個軟體各自為政,系統層級的快速鍵少之又少,就算有,你可能也不知道。更糟糕的是,同樣的一組快速鍵,在不同的 Linux distro 上,功能可能還不同 (比如說 Ubuntu 的 "Ctrl + Alt + Backspace" 就跟 Mint 的功用不同),實在是讓人無言阿,所以還是不要倚靠這條路吧,更何況各位可以去逛逛 Linux 討論區,網友們根本不在意這個。

OK,既然 Linux 社群這麼喜愛文字指令,那就用這種方法也不錯,更何況把指令製作成 script 檔 (sh) 擺在桌面也很方便。可是一開始搜尋之後我就傻了 .....

怪怪!不過是電源管理,你們要搞幾套軟體出來才過癮?

不信嗎?我列舉我有找到的軟體 (只有文字介面的軟體,其實就是指令) 給大家開開眼界:

  1. sudo echo "mem" > /sys/power/state
  2. sudo echo "shutdown" > /sys/power/disk; echo "disk" > /sys/power/state
這兩個指令分別是 "睡眠" 及 "休眠",光看指令本身其實很神奇,因為它不過是塞一個 "mem" 或 "disk" 的字串給 "state" 這個文字檔而已,就能有睡眠或休眠的效果。不過,"mem" 及 "disk" 字串的選用是有但書的,你必須要先看過 "state" 的內容 (可用 cat /sys/power/state 指令去看),若內容為 "standby  disk",則 "睡眠" 的指令需改為 echo "standby" > /sys/power/state。

至於 "休眠" 指令的前一段 echo "shutdown" > /sys/power/disk 是啥意思呢?簡單的說就是 Linux 的休眠有兩種,分為 "shutdown" 及 "platform",我查到的資料是說若該電腦之硬體對於 ACPI 的支援 "比較好" 才可用 "platform" .... 這部份我不太懂,也沒時間再去深入研究了。

  1. sudo pm-suspend
  2. sudo pm-hibernate
  3. sudo pm-suspend-hybrid
這部份我在本文的一開頭就解釋過了,而我之所以說 "以 Linux 中 pm 指令的操作說明為例",就是因為這種指令有一狗票阿!

  1. sudo /etc/acpi/sleep.sh
  2. sudo /etc/acpi/hibernate.sh
簡單明瞭,啟動 /etc/acpi/ 裡的 script 檔 (/etc/acpi/ 裡還有關閉電源及關閉螢幕的 script,東西還不少 ....)。

  1. sudo s2ram
  2. sudo s2disk
  3. sudo s2both
 s2ramSuspend 專案的一部份,需要另外安裝。我個人並沒有實際安裝過,因為它不是很容易安裝,我從官網的下載連結進去之後,彷彿走迷宮般找到 "Suspend" 軟體,若用套件庫去找則是找到 "uswsusp" 軟體,我知道它們似乎是同一個東西,但這段過程讓我十分不悅 ....


要有 root 權限才能睡眠?

OK,上述的指令有沒有讓各位眼花撩亂?說真的我不覺得這種自由會帶給大家方便,只是很 "搞剛" 而已,不過 Linux 本來就不在意使用者體驗就是了。好,講了那麼多,但是上述的功能我一個都看不上眼,也不建議各位使用,因為實在太蠢了,看看每句指令前的 "sudo",也就是說你只不過是要讓自己的電腦睡眠,卻要管理者 (root) 權限

當然,技術上來說,要以軟體直接與硬體溝通,的確應該要有管理者權限,但還是覺得很不甘心,而且調整 "電源" 的設定又不需要管理者權限 (如本文第三張圖),表示以 GUI 層級就能辦到,擁有管理者權限不是必要條件。所以我又找到了幾種方法 (X 的,到底還有幾種) ...

  1. gnome-power-cmd suspend
  2. gnome-power-cmd hibernate
很明顯地,這種方法只有 Gnome 圖形介面才可以使用,但 "號稱" 不需要管理者權限。為什麼說 "號稱" 呢?因為我的 Mint 雖然是用 Gnome 介面,但沒有內建這種指令,所以我沒試過,而後來在網路上找到它已往生的訊息 ..... orz

  1. pmi action suspend
  2. pmi action hibernate
pmi 是另一種電源管理程式,也需要另外安裝,而我安裝了之後卻不能使用,執行時會出現 "..... was not provided by any .service files" 的錯誤訊息,看起來似乎是缺少了什麼東西,那為何在安裝時不會以套件相依性一併安裝呢?唉 .... 這讓我想起之前在 Linx Mint 上安裝 xbmc 的慘況,過了這麼久,在 Linux 上連安裝一個軟體都有這麼多問題,我認為 "自由"、"無私奉獻".... 這些自由軟體社群常掛在嘴邊的話不能當作藉口。

  1. dbus-send --print-reply \ --system \ --dest=org.freedesktop.DeviceKit.Power \ /org/freedesktop/DeviceKit/Power \ org.freedesktop.DeviceKit.Power.Suspend
  2. dbus-send --print-reply \ --system \ --dest=org.freedesktop.DeviceKit.Power \ /org/freedesktop/DeviceKit/Power \ org.freedesktop.DeviceKit.Power.Hibernate
這是我最後找到的解法,不需管理者權限,且的確可用!(瞧瞧我有多感動就知道我有多杜爛) 它們常常以好幾行的型式呈現 (如前面所提及的參考網站),不過把它們接成一行也是可以的。這兩段指令用的都是 D-Bus 及 UPower,其中 D-Bus 有點類似 Mac OSX 的 AppleScript,它能提供應用程式間彼此溝通的管道,而這也正是 Linux 長久以來一直欠缺的東西之一 (據說目前正在計劃移植到 Windows 上)。如今 D-bus 提供一系列的 "溝通管道" (或者說是 API),其中一種就是 UPower (org.freedesktop.DeviceKit.Power),這種 API 能讓使用者在不具備管理者權限的情況下,直接讓電腦睡眠或休眠,故完全符合我的需求,也分享給大家。[4]

=======================

"自由"?科科。

20130610 Update:感謝各位的捧場,本文的點閱率相當不錯 (似乎只要是 Linux 的相關文章都是如此,可能是 Linux 的中文資源真的太貧瘠),故我補充一點東西。在本文中提到的 "睡眠" 及 "休眠" 都是遵循 ACPI 的定義,比如說前者是 "只留下 RAM 的電源紀錄系統狀態,其他部分不供電",故若要喚醒 "睡眠" 中的電腦,必須按下電源鍵才可以。可是 Mac 的 "睡眠" 或 "休眠" 都與之不同,Mac 利用軟硬整合的優勢,讓它的睡眠及休眠狀態都仍以低電源的方式,持續供電給週邊設備,如鍵盤及滑鼠,所以使用者能以鍵盤或滑鼠喚醒他們的 Mac,以上是一點小補充。

20190407 Update:Linux 的 Kernel 更新好像完全不管兼容性的 .... 我使用的是 Linux Mint MATE,上述 D-Bus 的休眠指令只在 Linux Mint 17 (含) 之前有效,我沒用過 Mint 18,目前確定 Mint 19 的 Kernel 相容於新的休眠指令:

  1. dbus-send --print-reply --system --dest=org.freedesktop.login1 /org/freedesktop/login1 org.freedesktop.login1.Manager.Suspend boolean:true
簡單地說就是 UPower suspend 已經不能用了,所以指令要改。相容不同硬體是很難的,電源管理的確是 Linux 的罩門,Mac 就是最好的反例,封閉的硬體造就極度快速且穩定的休眠。



附註
1. 當然我也遇過用了十多年 Mac,還堅持每次都要關機的 Mac 使用者,然後在客戶那裡都要花幾分鐘等開機 .... 算了,他喜歡就好。
2. 不過 Linux 沒這麼自動化,一旦出問題你還是要自己去調整休眠檔的存放位置。
3. 其實 Windows 的 "Standby" 有兩種型式,另一種就是 ACPI 定義的 Standby .... 如果覺得很複雜也無所謂,不要去用就沒事了,因為出包案例幾乎都發生在 Standby 模式。另外,Windows 的 "Sleep" 是到 Vista 推出後才加入的,之前完全沒這玩意,不過在意的人也不是很多就是了 ....
4. 以 D-bus 及 UPower 寫成的睡眠或休眠指令不只有一種寫法,只要看到 "dbus-send" 開頭,以及內容有提到 "org.freedesktop" 的指令,基本上功能都是相同的。

22 則留言:

  1. 自由的代價就是混亂,實在說的太棒了XD

    回覆刪除
    回覆
    1. 強烈建議很閒的人再去用 Linux。

      刪除
    2. 可惡,Linux可是我的工作系統。Laptop也是關了就走走.不過建議要用Linux最好用有牌子賣的好的電腦,不然真的會搞到死。

      刪除
    3. 由於 Linux 有太多問題需要自己解決,所以若無熱情及時間,應該會用得很辛苦。

      另外,雖然我這篇文章旨在分享 Linux 的休眠方法,但用於筆電時會不會無故醒來,我也不敢保證。

      刪除
    4. 當初有想過要從win跳liunx嘗鮮,但不管試幾次都一直被打臉...

      最後一次嘗試,為了避免被打臉,拿去朋友家請他教我設定pppoe
      我確定學會了,也在他家成功pppoe播接上adsl
      結果電腦拿回家用同樣的流程還是無法播接...orz
      所以我決定再也不碰這個麻煩的系統了

      刪除
    5. 我第一次接觸 Ubuntu Linux 的時候,也是很不解為何 PPPoE 的設定介面沒有 GUI,那時候已經 2006 年了,居然還有這種荒唐事,可是社群還是自我感覺良好,沒辦法。

      直到今天,Linux 始終在追趕,但 "內部阻力" 非常大,而且令我十分驚訝的是,Linux 至今居然還是沒有一套登得上檯面的繁中輸入法,要馬是與程式的連結有問題,要馬沒有學習能力,要馬安裝後無法啟動 .... 想想 SCIM 及 gcin 發展多少年了,居然還跟 beta 版沒兩樣 (iBus 完全是垃圾,我根本懶得噴了)。

      不能怪大家愛用 Win 或 OSX,"便宜沒好貨" 也不見得是真理,但 Linux 至今仍未突破這層魔咒。

      刪除
    6. 試試看Debian的繁中輸入法?

      刪除
    7. Try Debian Linux 6 (Squeeze).
      Use "apt-get install ibus-chewing"

      刪除
    8. Sorry! Its Debian GNU/Linux.

      刪除
  2. 我記得Eject那個位子被改成電源鍵,所有的快速鍵還是可以照用啊,至少在我的MacBook Air上是這樣。

    回覆刪除
    回覆
    1. 我有在某個外國論壇看到某老外說他的 MacBook Air 沒有 Eject 鍵,然後求休眠快速鍵的替代方法,但文後也沒有人跟他說電源鍵可以替代 .... 所以你可以用 "Command + Option + Power" 去使 Mac 睡眠?

      不過對我是沒差啦,因為我只有 Mac mini (2006 的老機及老系統根本不支援這組快速鍵),而我的鍵盤是雜牌的。

      刪除
    2. 作者已經移除這則留言。

      刪除
    3. 可以的呀
      cmd opt power 可以睡眠
      ctrl cmd power 可以重開機
      ctrl opt cmd power 可以關機
      ctrl shift power 可以關螢幕
      這些都可以用~

      刪除
    4. 感謝你的情報,可惜我的雜牌鍵盤沒有 power 鍵,而這個鍵也沒有對應到一般鍵盤上的其他鍵,所以我個人是無法使用了 orz

      刪除
  3. D-BUS移植應該已經有了。
    我之前很無聊裝了KDE SC for Windows就發現裡面包了這玩意。
    不過...有些軟體還不是很穩,像是看圖用的Gwenview,根本就是每開必當。
    後來我發現每個動作之間都要停個1-2秒才不會當,WTF!

    回覆刪除
    回覆
    1. 自由軟體就是這樣,很多東西還來不及測試完畢就發布了,想當初 Ubuntu 6.0 的年代,自由軟體社群最熱門的繪圖軟體 GIMP 居然每開必當,實在是扯到不行,到後來幾版才有改善。

      刪除
  4. 其實Windows Vista之後的Sleep已經寫得算不錯了
    如果不計較吃電像喝水的老問題其實已經看得到OSX的車尾燈

    回覆刪除
    回覆
    1. 另外Windows從NT6.1(Win7)開始好像改成這樣:
      Sleep=STR
      Hibernate=STD
      在控制台裡開啟混合式休眠(hybrid sleep)=uspend-hybrid
      同時Hibernate選項會消失

      刪除
  5. 網誌管理員已經移除這則留言。

    回覆刪除