2012年10月23日

開発用のrootfsで起動後すぐにシリアルコンソールでrootで自動ログインする方法

開発ボードでカーネルをいじるときには、rootfsとしてLinaroのサイトにあるnanoやALIPを私はよく使用します。

これらの便利なところは、起動するとすぐにシリアルコンソールにrootで自動ログインしてshellのプロンプトが出るところです。しかも、rootfsの中では、明示的にシリアルコンソールのデバイス名を指定しなくても自動で判別してくれています。

これがどのような仕組みになっているのかを少し調べました。そのメモを残します。



いままで (その1)

昔のSystemV方式のinitでは、どのデバイスでgettyを動かすかは、 /etc/inittab に記述していました。 /dev/console でgettyを通さずに直接/bin/shを起動するには、そのように書くことができたと思います。

しかし、最近はこの方式を使うことがないので詳細を思い出せません。

いままで (その2)

Ubuntuでは早々にSystemV方式からupstartに移行しました。gettyを動かすデバイスを指定するためには、/etc/initの下に、デバイス名.conf のファイルを作っておく必要がありました。つまりシリアルコンソールが/dev/ttyS1ならば、ttyS1.confです。内容はtty1.confからコピーして、シリアルのボーレイトのパラメータとデバイス名だけを修正するだけで済みます。

/etc/init/ttyS1.conf

# ttyS1 - getty
#
# This service maintains a getty on tty1 from the point the system is
# started until it is shut down again.

start on stopped rc RUNLEVEL=[2345] and (
            not-container or
            container CONTAINER=lxc or
            container CONTAINER=lxc-libvirt)

stop on runlevel [!2345]

respawn
exec /sbin/getty -8 115200 ttyS1

とりあえずこれでシリアルコンソール/dev/ttyS1にログインプロンプトが出るようになります。

しかし、評価ボードによってはシリアルコンソールのデバイスは異なります。例えば、KZM-A9-DualボードではttyS1ですが、KZM-A9-GTボードではttySC4です。両方のボードを交互に試す場合、その度にttyS1.confとttySC4.confを作ったり消したりしなければなりません。両方をそのまま置いておくと、存在しないデバイスに対してgettyを実行することになり、エラーメッセージが繰り返しコンソールに表示されるので、わずらわしいことになります。結局ボードごとにrootfsを分けて準備しておく必要がありました。

Linaroの開発用rootfsでの仕組み

LinaroのnanoやALIPなどの開発用rootfsでは、シリアルコンソールのデバイスを自動判別します。このため、複数のボードで同じrootfsを使用可能です。ボードをとっかえひっかえしながら実験している時にはこれはありがたいことです。

シリアルコンソールのデバイスの自動判別は、カーネルに渡されたブートパラメータのconsole= の部分を見て行っていました。rootで自動ログインするには、gettyから実行するlogin用のプログラムとして、login -f root を使用するようになっていました。 -f でパスワードの入力を省略できます。

関連するファイルは以下のとおり。

  • /etc/init/auto-serial-console.conf
  • /bin/auto-serial-console
  • /etc/default/autogetty
  • /bin/auto-root-login

/etc/init/auto-serial-console.conf

# auto-serial-console - autostarts getty on serial console
#
# This service maintains a getty on serial port given as 'console' kernel argument.
#
# Last 'console' argument is used
#

start on runlevel [23]
stop on runlevel [!23]

respawn

exec /bin/auto-serial-console

/bin/auto-serial-console

#!/bin/sh -e

[ -f /etc/default/autogetty ] && . /etc/default/autogetty

[ 1 -gt $ENABLED ] && exit

for arg in $(cat /proc/cmdline)
do
    case $arg in
	console=*)
	    tty=${arg#console=}
	    tty=${tty#/dev/}

	    case $tty in
		tty[a-zA-Z]* )
		    PORT=${tty%%,*}

		    # check for service which do something on this port
		    if [ -f /etc/init/$PORT.conf ];then continue;fi 

		    tmp=${tty##$PORT,}
		    SPEED=${tmp%%n*}
		    BITS=${tmp##${SPEED}n}

		    # 8bit serial is default
		    [ -z $BITS ] && BITS=8
		    [ 8 -eq $BITS ] && GETTY_ARGS="$GETTY_ARGS -8 "

		    [ -z $SPEED ] && SPEED='115200,57600,38400,19200,9600'

		    GETTY_ARGS="$AUTOGETTY_ARGS $GETTY_ARGS $SPEED $PORT"
		    exec /sbin/getty $GETTY_ARGS
	    esac
    esac
done

/etc/default/autogetty

# here you can provide what to run instead of /bin/login
AUTOGETTY_ARGS="-n -l /bin/auto-root-login"

# Should autogetty be enabled?
ENABLED=1

/bin/auto-root-login

#!/bin/sh

exec /bin/login -f root

shellスクリプトの細かい技が勉強になりますね。



トラックバックURL

コメントする

名前
URL
 
  絵文字
 
 
記事検索
最新コメント
アクセスカウンター
  • 今日:
  • 昨日:
  • 累計:

QRコード
QRコード