Debian vs Ubuntu: 電源を切る

Debian と Ubuntu を両方使って気づいた些細な違いをその経緯も含めて深追いすることで、ディストリビューションの多様性について考えてみます (ほとんどは自分がはまったことの覚え書きですが)。

最初は電源を切ることについて。この記事では x86 の PC ベースのハードウェアを前提とします。

2013/07/03 追記: 仮想化環境について加筆しました。

halt コマンド

Ubuntu では halt コマンドでシステムを終了させると System halted とコンソールに出した時点で停止し、ホストの電源は切れません。電源を切るには poweroff コマンドまたは halt -p を使用します。

なにをあたりまえのことを、と言われるかもしれませんが、私の過去の経験から halt して電源が落ちない Linux ホストはすなわち APM とか ACPI とかハードウェアに問題があるか、カーネルの設定間違えてるかのイケてないホストであるという先入観があったため、これを異常と認識してしまい、見当違いな調査と検証でえらく時間を無駄にしました。

この問題の真相は Debian が採用する伝統的な sysvinit と、その置き換えとして Ubuntu が採用する upstart の違いにあります。 halt poweroff reboot shutdown といったコマンドは、これらのパッケージの一部です。

upstart の halt も当初は sysvinit と同じように電源が切れていたらしいのですが、 upstart 1.1バグ #532366 が修正されており、ここで現在の挙動に変更されたようです。

1.1  2011-03-16  "It's probably 'cause you think you're cooler than me"

        * When /sbin/halt is called (without -p), this now results in the
          system being halted and not powered down. If you meant it to be
          powered down, use /sbin/poweroff.  (Bug: #532366)

この upstart が Ubuntu リリースに含まれるようになったのは oneiric (11.10) からで、実際には precise (12.04 LTS) になってこの挙動の変化に気づいた人が多かったと見受けられます。

なおシステム停止コマンドとしてよく使われる shutdown -h now も、必ず電源が切れると決まっているわけではありません。これは /etc/default/halt の設定で決まります。

# Default behaviour of shutdown -h / halt. Set to "halt" or "poweroff".
HALT=poweroff

この設定によらず電源を切りたいとき、切りたくないときは、それぞれ shutdown -P now ないし shutdown -H now を使用してください。

電源ボタン

次は電源ボタンによるシステムのシャットダウンについて。

PC ベースのハードウェアでは、筐体の電源ボタンが押されたことは ACPI のイベントとして取得できることになっています。

Ubuntu ではこのときに acpid パッケージ がインストールされていれば、それに含まれる /etc/acpi/events/powerbtn/etc/acpi/powerbtn.sh スクリプトを起動してシステムをシャットダウンしてくれます。

Debian では acpid パッケージ がインストールしてあるだけでは電源が落ちず、 /etc/acpi/powerbtn-acpi-support および /etc/acpi/powerbtn-acpi-support.sh を含む acpi-support-base パッケージ をインストールする必要があります。このパッケージはミニマルなインストールにこだわっていると見落とされがちなので注意が必要です。

Debian の acpi-support は実は Ubuntu が upstream なのですが、 Debian 側で独自の変更を加えすぎた結果、このようなパッケージ構成の違いを生み出してしまいました。

このあおりで Ubuntu の acpid は Debian の acpid に素直に追従できなくなりました (Ubuntu の changelog を読むとメンテナの苦労が偲ばれます)。 acpid も acpi-support も、upstream のリリースごとに互いの変更点を適用してリリースするという面倒くさいメンテナンス体制になっています。

Ubuntu が Debian パッケージに独自の変更を加えすぎてしまい、メンテナの手間やユーザの覚えることが増えて不幸になるのはよくある光景ですが、 acpi-support はその立場が逆になっており、さらに他のパッケージまで巻き込んでいるという、どうしてこうなった的なパッケージなのでした。

仮想化環境

KVM/QEMUVirtualBox などの PC ベースハードウェア仮想化技術のゲストとして稼働する Debian/Ubuntu でも、 halt コマンドや電源ボタンについては上述の通りの挙動を示します。試していませんが XenVMware など他の製品でも同様でしょう。

Ubuntu ゲストでうっかり halt してしまうと、そのゲストはメモリや CPU のリソースを掴んだまま、ホストから強制電源断の操作をするまで使用不能になってしまいます。

そして最も重要なことは、ホストによるゲストのシャットダウン操作は、通常はゲストの電源ボタンを押す操作に相当するということです。

なんからの理由でゲスト稼働中のホストがシャットダウンする場合、ホストはゲストの電源ボタンを押した上でしばらく待ち、その後まだ残っているゲストを強制電源断という処理になるでしょう。ここでゲストが正しくシャットダウンできるかどうかは、ゲストの OS が電源ボタンに反応できるかどうかにかかっているわけです。

ホストが高価な UPS などを装備していても、ゲストが正しくシャットダウンできなければ意味がありません。ということで、仮想化環境においてはゲストの電源設定も軽視せず、きちんとセットアップした上でシャットダウンのテストをしておくことをお勧めします。

おまけ: libvirt および virtualbox のシャットダウン設定

仮想化ホストのシャットダウン時の具体的な挙動や設定は、もちろん製品やディストリビューションにより異なります。

Debian の libvirt パッケージ では /etc/default/libvirt-guests でホストがシャットダウンするときの挙動を設定できます。ゲストのシャットダウンを待つタイムアウトが指定でき、また ドライバが virDomainManagedSave に対応していれば サスペンド動作も指定できるようです。

# action taken on host shutdown
# - suspend   all running guests are suspended using virsh managedsave
# - shutdown  all running guests are asked to shutdown. Please be careful with
#             this settings since there is no way to distinguish between a
#             guest which is stuck or ignores shutdown requests and a guest
#             which just needs a long time to shutdown. When setting
#             ON_SHUTDOWN=shutdown, you must also set SHUTDOWN_TIMEOUT to a
#             value suitable for your guests.
#ON_SHUTDOWN=shutdown

# If set to non-zero, shutdown will suspend guests concurrently. Number of
# guests on shutdown at any time will not exceed number set in this variable.
#PARALLEL_SHUTDOWN=0

# Number of seconds we're willing to wait for a guest to shut down. If parallel
# shutdown is enabled, this timeout applies as a timeout for shutting down all
# guests on a single URI defined in the variable URIS. If this is 0, then there
# is no time out (use with caution, as guests might not respond to a shutdown
# request). The default value is 300 seconds (5 minutes).
#SHUTDOWN_TIMEOUT=300

一方 Ubuntu の libvirt パッケージ は upstart 化されており設定も Debian とは異なります。 /etc/init/libvirt-bin.conf を見たところ Debian のようにサスペンド動作は設定できないようです。唯一変更できそうな設定はシャットダウンのタイムアウト値だけです。

# by default wait 30 seconds for vms to shut down
env libvirtd_shutdown_timeout=30

/etc/default/libvirt-bin を読み込んでいるので、設定を変えたければここに書いておけばよさそうです。

libvirtd_shutdown_timeout=180

Debian の virtualbox パッケージ については /etc/default/virtualbox に設定があるようです。

# SHUTDOWN_USERS="foo bar"  
#   check for running VMs of user 'foo' and user 'bar'
#   'all' checks for all active users
# SHUTDOWN=poweroff
# SHUTDOWN=acpibutton
# SHUTDOWN=savestate
#   select one of these shutdown methods for running VMs
#   acpibutton and savestate causes the init script to wait
#   30 seconds for the VMs to shutdown
SHUTDOWN_USERS=""
SHUTDOWN=poweroff

Ubuntu の virtualbox パッケージ は multiverse パッケージであり upstart 化されておらず設定は Debian と共通です。

2013/06/30 20:05:00 JST