RHEL6 シリアルコンソール設定とupstartイベント

SysVinit から upstart

RHEL6では init system が SysVinit から upstart に変わって、upstart なんか弄ったことが無かったので最初はおっかなびっくりだったんだけど、runlevel変更(設定)時のサービス実行については基本的に同じで、各種デーモンのrcスクリプトもそのまま使えたので一安心。(まあRHEL6が出てからずいぶん経つので、今頃いろいろ悩むのも遅れているわけだけど)
ただ、/etc/inittab は大きく変わっていて、これまでの設定は基本的に /etc/init/*.conf のジョブ定義ファイルにバラされて、そこに設定するようになっている。こっちの方が本命で、できれば全てのサービス起動・終了をconfファイルで記述してイベントベースにしたいんだろうけど、いきなりそれは無理なので、こんな構成になっている模様。
なので、現時点ではシステム起動時間の短縮とかも限定的な感じ。

シリアルコンソール設定も inittab から confファイルに移ってて、しかも、シリアルコンソールがプライマリのシステムコンソールになる場合は特別な設定も必要ない。まあ、シリアルをプライマリのコンソールにするための設定(grub)は必要なわけだけど。
それで、プライマリになっていない場合の対処をどうするかで、ちょこっと調査してみたので記録しておく。

シリアルコンソール設定の基本

シリアルコンソール立ち上げのジョブは、/etc/init/serial.conf であって、そこには以下のように記述してある。

# Automatically start a configured serial console
#
# How this works:
#
# On boot, a udev helper examines /dev/console. If a serial console is the
# primary console (last console on the commandline in grub), the event
# 'fedora.serial-console-available ' is emitted, which
# triggers this script. It waits for the runlevel to finish, ensures
# the proper port is in /etc/securetty, and starts the getty.
#
# If your serial console is not the primary console, or you want a getty
# on serial even if it's not the console, create your own event by copying
# /etc/init/tty.conf, and changing the getty line in that file.

start on fedora.serial-console-available DEV=* and stopped rc RUNLEVEL=[2345]
stop on runlevel [S016]

instance $DEV
respawn
pre-start exec /sbin/securetty $DEV
exec /sbin/agetty /dev/$DEV $SPEED vt100-nav

つまりは、自動でシリアルコンソールが起動するのは fedora.serial-console-available イベントが emit されたときで、通常は grub の記述で決まると。そして、シリアルコンソールがプライマリのシステムコンソールになっていれば、このイベントが発生する模様。
一方、プライマリでない(これは例えば /dev/console と /dev/ttyS0 が同じでない)場合は、上記のイベントが飛ばないので /etc/init/tty.conf 等を元にして対応するジョブを作成し起動用のイベントを決めろ、と。

RHEL6移行計画ガイドの説明

RHEL6移行計画ガイド - 4.2. サービスの初期化によると、以下のような方法を説明してある。

デフォルト以外のシリアルコンソールで実行している getty を設定するには、 /etc/inittab を編集するのではなく、 Upstart ジョブを記述する必要があります。 例えば、 ttyS1 上の getty を設定したい場合は、 以下のようなジョブファイル (/etc/init/serial-ttyS1.conf) になるでしょう。

          • -

# This service maintains a getty on /dev/ttyS1.

start on stopped rc RUNLEVEL=[2345]
stop on starting runlevel [016]

respawn
exec /sbin/agetty /dev/ttyS1 115200 vt100-nav

          • -

runlevel-2345の設定処理が完了(rcジョブが終了)したら、agetty を立ち上げるというシンプルなもの。確かにこれでうまくいく。終了。

他の手段

RHELのドキュメントに書いてあるようにやればよかったんだけど、以下のような方法も(試してないけど)いけそうな気がする。

  1. fedora.serial-console-availableイベントを発行する新規ジョブを定義するか、既存のstart-ttys.confの末尾に追加する
    • initctl emit fedora.serial-console-available DEV=ttyS1 SPEED=....
  2. serialジョブを実行する新規ジョブを定義するか、既存のstart-ttys.confの末尾に追加する
    • initctl start serial DEV=ttyS1 SPEED=....

両方とも、既存のserialジョブを生かして利用する方向で考えたんだけど、正直あまり意味は無いし、start-ttys.conf に追加する場合は既存のジョブ定義を変更するので筋が悪いんでやらないけど、まあ、何か上手くハマル場合もあるかもしれない。

fedora.serial-console-availableイベントは誰が発行するのか?

肝心の、このイベントを誰が発行しているのかが気になったんで見てみる。
serial.conf の上記引用中に udev についての記述があったので、udev設定辺りを見てみると、/lib/udev/rules.d/10-console.rules とかいうルールファイルがあって、その中で console_init とか console_check コマンドを使っているようなので、なんかそれっぽい。このファイルは rpm -qf で調べると initscripts パッケージに入っている。このパッケージには /etc/init 下のほとんどのジョブ定義ファイル(serial.confとか)も入っているので、ちゃんと見てみることにする。

早速src.rpmを取得して、ソースを展開した後の構成と関連するファイルは以下のようになっている。

initscripts-9.03.27
   /init
      serial.conf
      tty.conf
      .....
   /src
      console_check.c
      .....
   /udev/rules.d/10-console.rules

そして、先ほどあった console_check に対応する console_check.c を読むと、所定の条件チェックを行った後で、/sbin/initctl を呼び出し、fedora.serial-console-available イベントを emit するコードがしっかり書かれていた。
条件は幾つかあって、多くの場合は合致するのだろうが、プライマリでなかったり、仮想コンソールのような場合は合致しないのでイベントが飛ばず、上述のような対応が必要となる、ということのようだ。すっきり。

思っていたより時間を使ってしまった

わかってしまえば単純だけど、設定作業の最初は戸惑うばかりだった。幸い、RHEL6が出てから時間が経っているので、既に先達が書かれた情報もあり助かったけど、やっぱり初めてのソフトの設定は面倒だわ。時間に迫られている時にやるとしんどい。