システム起動時にコマンドを自動的に実行する方法には、以下の二種類があります。
- 初期化スクリプトとして登録する。
inittab
に登録する。
本章では、これらの方法について説明します。
8.1.1. 初期化スクリプトで自動実行する(一時的な方法)
起動時に特定のコマンドを自動実行したい場合、コマンドをスクリプトに記述し、それを初期化スクリプトとして登録[]します。
初期化スクリプトは、以下の順番で実行されます。
/etc/init.d/rc
ファイル。/etc/rc.d/
ディレクトリにあるファイル。/etc/config/rc.local
ファイル。
通常、/etc/init.d/rc
ファイルは固定で、/etc/rc.d
ディレクトリ内のファイルや/etc/config/rc.local
をシステムに合わせて変更します。
Armadilloでは、ルートファイルシステムにRAMディスクを置いているため、/etc/rc.d
ディレクトリのファイルをArmadillo上で変更しても、次回起動時にはその変更は失われます。/etc/rc.d
ディレクトリの内容を変更したい場合には、毎回ルートファイルシステムイメージを作成しなおさなければならないため、開発の初期段階などファイルの変更が頻繁にある場合、効率が良くありません。
一方で、/etc/config
ディレクトリの内容は、flatfsdコマンドでフラッシュメモリのコンフィグ領域に保存することができ、起動時に復元されます[]。そのため、/etc/config/rc.local
を使うと、ルートファイルシステムイメージを更新せずに自動実行するコマンドを変更することができます。
例として、Armadillo-440の標準イメージの/etc/config/rc.local
は以下のようになっています。
図8.1「Armadillo-440の標準イメージの/etc/config/rc.local」では、functesterコマンド[]をバックグラウンドプロセスとして実行しています。
/etc/config/rc.local
がない場合は、ファイルを新規作成し、実行権限を付けることで起動時に自動で実行されます。
/etc/config/rc.local
を新規作成したり、編集した場合、その内容をフラッシュメモリのコンフィグ領域に保存しなければなりません。コンフィグ領域に保存するには、flatfsdコマンドを使用します。
/etc/config/rc.local
ファイルを扱うコマンドは、以下のようになります。
| rc.local ファイルを新規作成または編集します。 |
| 実行権限を付けます。 |
| フラッシュメモリに保存します。 |
8.1.2. 初期化スクリプトで自動実行する(恒久的な方法)
/etc/config/rc.local
への変更は一時的なものです。開発の最終段階でルートファイルシステムのイメージを固める時には、自動実行するスクリプトは、/etc/rc.d
ディレクトリに登録します。
/etc/rc.d
ディレクトリのファイルはSで始まり、文字コード順でソートした場合に先にくるものから順番に実行されます。通常、実行される順番が分かりやすいように、Sの後には二桁の数値文字が続きます。
大抵の場合、/etc/rc.d
ディレクトリのファイルは、/etc/init.d
ディレクトリのファイルへのシンボリックリンクになっています。そのため、スクリプト本体のファイル名は固定で、シンボリックリンクの名前を変更するだけで、スクリプトの実行順番を変えることができます。
初期化スクリプトの実行順番には、注意が必要です。例えば、ネットワークの設定を行う前にWebサーバーを起動してはいけません。
また、バックグラウンドプロセスやデーモンとして起動したプロセスの実行順番には、より注意が必要です。バックグラウンドプロセスやデーモンを実行するコマンドは、プロセスを起動するとすぐに戻ってきます。そのため、後続のコマンドを実行する際に、それらのプロセスが行う処理が完了しているとは限りません。
Armadillo-400シリーズの標準イメージでは、/etc/rc.d
ディレクトリ内の初期化スクリプトは、以下の順番で実行されます。
ファイルやディレクトリの準備
- S03udevd:udevdの起動とデバイスノードの作成。
- S04flatfsd:コンフィグ領域に保存した内容を
/etc/config
ディレクトリに復元。 - S05checkroot:重要なファイルやディレクトリの権限の設定。
- S06checkftp:FTPサーバーが使用する
/home/ftp
ディレクトリの設定。
ログデーモンの起動
- S10syslogd:syslogデーモンの起動。
- S20klogd:カーネルログデーモンの起動。
ネットワークの設定
- S30firewall:ファイヤーウォール(iptables)の設定。
- S30hostname:ホストネームの設定。
- S40networking:ネットワークインターフェースの有効化。
各種ネットワークサーバーの起動
- S60inetd:inetd(スーパーサーバー)の起動。
- S70at-cgi:at-cgi[]で必要なファイルの設定。
- S70lighttpd:lighttpd(Webサーバー)の起動。
- S71avahi:avahi-daemon(Zeroconfサーバー)の起動。
その他
- S99misc:
/home/ftp/pub
ディレクトリをramfsでマウント。
rc.localの実行
- S99rc.local:
/etc/config/rc.local
ファイルが存在し、実行可能なファイルであれば実行。
新しく初期化スクリプトを追加する場合、どの順番でおこなうべきか、良く検討してください。
Atmark Distで作成するルートファイルシステムに初期化スクリプトを追加するには、以下のような手順でおこないます。
- プロダクトディレクトリ以下の
etc/init.d
ディレクトリに初期化スクリプトを追加する。 rc.d
ディレクトリのシンボリックリンクを作成するようプロダクトディレクトリ以下のMakefile
を修正する。
Atmark Distのプロダクトディレクトリ以下のetc/init.d
ディレクトリにファイルを追加すると、Armadilloのルートファイルシステムの/etc/init.d
ディレクトリにファイルが追加されます。
また、Atmark DistのプロダクトディレクトリのMakefile
に、Armadilloのルートファイルシステムの/etc/init.d
ディレクトリのファイルへのシンボリックリンクを/etc/rc.d
ディレクトリに作成するよう記述しておくと、make romfsを実行時に、シンボリックリンクが作成されます。
以下にMakefile
の変更箇所を示します。romfsターゲットで実行するコマンドに、$(ROMFSINST)コマンド[]を追加します。
Atmark Distへの修正をArmadilloに反映するには、通常通り、makeコマンドを実行してユーザーランドのルートファイルシステムイメージ(romfs.img.gz
)を作成しなおし、Armadilloのフラッシュメモリのユーザーランド領域に書き込んだ後、再起動してください。
起動時に自動実行するコマンドは、inittab
に記述することもできます。
第1部「Armadilloが動作する仕組み」の「ユーザーランドの初期化処理」にも記述したように、inittab
のactionに指定できる値のうち、起動時にコマンドを実行するアクションは、sysinitとrespawnです。
sysinitアクションのコマンドには、通常、初期化スクリプトの/etc/init.d/rc
を実行するよう記述します。
respawnアクションに記述されたコマンドは、sysinitアクションに記述されたコマンドが完了したあと、すなわち、初期化スクリプトがすべて完了した後に実行されます。また、そのコマンドによって起動されたプロセスが終了すると、そのコマンドを再度実行します。
Atmark Distで作成するルートファイルシステムの/etc/inittab
を変更するには、Atmark Distのプロダクトディレクトリ以下のetc/inittab
ファイルを変更します。
| respawnアクションの実行間隔 |
---|
Atmark Distに含まれるbusyboxのinitでは、inittab のrespawnアクションで指定されたコマンドが起動したプロセスが、起動してから5秒以内に終了した場合、約5秒後にコマンドを再度実行するようになっています。 また、その状況が5回続くと、次のコマンドの実行はプロセスが終了してから約5分後に設定されます。 ですので、すぐに終了するようなプログラムはinittab に登録するには向いていません。次章で紹介するcronの利用を検討してください。 |
| 一時的なinittab |
---|
Atmark Distに登録されているbusyboxのinitは/etc/inittab のほかに/etc/config/inittab も読み込みます。 そのため、開発初期段階で一時的に使用する初期化スクリプトとして/etc/config/rc.local を使用したように、一時的に使用するinittab として/etc/config/inittab を使用することができます。 なお、/etc/config/inittab には、respawnアクションのみ指定することができます。その他のアクションを指定しても実行されません。 |
前章では、起動時にコマンドを実行する方法を紹介しました。本章では、指定した時刻に定期的にコマンドを実行する方法として、cronを使う方法を紹介します。
cronは、指定した時刻に指定したコマンドを実行するための仕組みです。crontab
と呼ばれる設定ファイルに記述された内容に従って、crondがコマンドを実行します。
コマンドを実行する時刻は分単位で指定可能で、毎分実行するという設定もできるので、間隔が比較的長い周期的な処理を行うこともできます。
crondの設定ファイルであるcrontab
ファイルは、crontabコマンドを使用して作成することができます。
crontab
ファイルには1行に付き、1つの設定を記述します。1つの設定は、スペースまたはタブによって区切られた、複数のフィールドを持ちます。各行のフォーマットは以下のとおりです。
crondは、毎分crontab
ファイルの内容を調べます。分、時、月が現在のシステム時刻と一致し、かつ、月内日または曜日のいずれかが現在のシステム時刻と一致すれば、コマンドが実行されます。
それぞれのフィールドには以下の内容を指定できます。
表8.1 crontabファイルのフィールド
フィールド | 指定可能な値 |
---|
分 | 0-59 |
時 | 0-23 |
月内日 | 1-31 |
月 | 1-12(もしくは名前[]) |
曜日 | 0-7(0と7は日曜日、もしくは名前[]) |
各フィールドには、アスタリスク(*)も指定できます。アスタリスクを指定した場合、そのフィールドが取りうるすべての値を指定したことになります。また、上記の指定可能な値以外にも高度な設定が可能です。詳細はman 1 crontabやman 5
crontabを参照してください。
Armadillo-400シリーズの標準イメージでは、crondはユーザーランドのルートファイルシステムには含まれていますが、自動起動するようになっていません。そのため、crontab
ファイルも含まれていません。Atmark Distで作成するルートファイルシステムにcrontab
ファイルを追加し、crondを自動起動するには、以下のような手順でおこないます。
- プロダクトディレクトリに
crontab
ファイルを追加する。 crontab
ファイルをルートファイルシステムに含めるよう、プロダクトディレクトリ以下のMakefile
を修正する。- crondを起動する初期化スクリプトをプロダクトディレクトリに追加する。
- crondを起動する初期化スクリプトを自動実行するよう、プロダクトディレクトリ以下の
Makefile
を修正する。
まず、Atmark Distのプロダクトディレクトリに、crontab
を追加します。
Armadilloの標準イメージに含まれるcrondは、BusyBoxのものです。BusyBoxのcrondは、/var/spool/cron/crontabs/[ユーザー
名]
をcrontab
として読み込みます。
このファイルは、Armadillo-400シリーズの標準イメージにはありませんので、新しく追加する必要があります。rootユーザー用のcrontab
ファイルは、プロダクトディレクトリ以下のvar/spool/cron/crontabs/root
というファイル名で追加します。
crontab
ファイルをルートファイルシステムイメージに追加するには、プロダクトディレクトリ以下のMakefile
を修正する必要があります。具体的な変更方法については「ファイルの追加、変更」を参照してください。
crondを起動する初期化スクリプトは、以下のようになります。この起動スクリプトをプロダクトディレクトリ以下のetc/init.d/crond
というファイル名で追加します。
図8.5「crondを起動する初期化スクリプト」が起動時に実行されるようにMakefile
を修正する方法は、「初期化スクリプトで自動実行する(恒久的な方法)」を参照してください。
一度起動したシステムがいつまでも元気に動き続けるという保証はありません。システムが正常に動かなくなる原因には、ソフトウェアのバグやハードウェアの故障などが考えられます。
システムは停止することがある、ということを前提として、停止した場合の対処についても、システム設計時に考慮しておかなければなりません。ここでは、問題が発生した場合、自動的に再起動する方法について説明します。
「inittabで自動実行する」で紹介したように、inittab
のrespawnアクションによって起動されたプロセスがなんらかの理由により意図せず終了してしまった場合、initが自動的にそのプロセスを再起動します。
プロセスで起動時や一定時間毎にログを出力しておけば、いつ頃異常終了したかを特定できるので、障害解析時に重要な情報となります。
8.3.2. ウォッチドッグタイマーによるシステムの再起動
アプリケーションプログラムのプロセスが異常終了したのであれば、initによってそのことを検出し、再起動することができます。しかし、カーネルがハングアップ(停止)してしまった場合、ソフトウェア的にそのことを検出する手段はありません。
システム全体がハングアップしてしまった場合、そのことを検出するための仕組みとして、ウォッチドッグタイマーがあります。
ウォッチドッグタイマーは、有効にされると内部のタイマーのカウントを開始します。システム側は、正常に動作している間はウォッチドッグタイマーに対して、定期的に信号を送ります[]。ウォッチドッグタイマーは、信号を受け取るとタイマーのカウントを最初からやり直します。もし、システム側に問題が発生し、信号を送ることができなくなったら、ウォッチドッグタイマーがタイムアウトし、システムのリセットをおこないます。
Armadillo-400シリーズでは、標準でi.MX25が持つハードウェアウォッチドッグタイマーが有効になっています。
Hermit-Atブートローダーによって、ウォッチドッグタイマーのタイムアウト時間が10秒に設定されてから、Linuxカーネルが起動されます。カーネルは、自動でウォッチドッグタイマーをキックします。
もし、何らかの要因でカーネルがハングアップしてウォッチドッグタイマーをキックできなくなりタイムアウトが発生すると、システムが再起動します。
Linuxカーネルに手を入れるようなことがなければ、通常、カーネルのハングアップに気を配る必要はありませんが、このような仕組みがArmadillo-400シリーズには組み込まれていることを覚えておいてください。
Linuxシステムでは、ログの管理はsyslogでおこなうことが一般的です。
各アプリケーションプログラムは、loggerコマンドやC言語のsyslog関数で、ログ記録用プログラムであるsyslogデーモンにメッセージを送ります。syslogデーモンは、送られてきたメッセージをファイルに記録したり、別サーバーへの転送、ログファイルのローテーションなど、ログの管理を一括して行います。
syslogデーモンには、オリジナルのsyslogdの他に、いくつかのバリエーションがあります。
Atmark Distで作成したユーザーランドの場合、syslogデーモンとしてBusyBoxのsyslogdを使用します。
BusyBoxのsyslogdは機能が基本的なものに限られているため、設定ファイルを持たず、設定はすべてコマンドラインオプションで指定します。
Armadillo-400シリーズの標準設定では、初期化スクリプトの/etc/rc.d/S10syslogd
(/etc/init.d/syslogd
へのシンボリックリンク)でsyslogdを起動しています。ログは、/var/log/messages
へ書き込まれます。
Debian GNU/Linux 5.0(コードネーム "lenny")では、rsyslogdが標準です。rsyslogdの設定方法については、「man rsyslogd」や「man rsyslog.conf」を参照してください。
ログファイルにログを書き込み続けると、ファイルサイズがどんどん大きくなり、いずれストレージの限界に達してしまいます。このような事態を避けるため、通常、ログファイルのローテーションをおこないます。ログファイルのローテーションは、一定の期間(1日や1週間など)や、一定のサイズごとに行います。
BusyBoxのsyslogdでは、サイズ毎のローテーションをサポートしています。
ログのローテートに関連するオプションは、-s
SIZE
と-b
NUM
です。SIZE
[KB]になる前にログファイルをローテートします。-s
オプションを指定しない場合のSIZE
のデフォルト値は200[KB]です。また、ローテートされたファイルをNUM個分保持します。-b
オプションを指定しない場合のデフォルト値は、1です。
Armadillo-400シリーズの標準設定では、-s
と-b
オプションを指定していないので、200[KB]になる前にローテートが行われ、過去のログファイルを1個だけ保持します。最新のログは/var/log/messages
に書き込まれ、一つ過去のログファイルは/var/log/messages.0
となります。
BusyBoxのsyslogdは、別のサーバーで動作しているsyslogデーモンへメッセージを転送できます。
メッセージの転送も、コマンドラインオプションで指定します。メッセージの転送を指定するオプションは、-R
HOST[:PORT]
です。HOSTには、転送先サーバーのIPアドレスかホスト名を指定します。PORTには、転送先サーバーのポート番号と転送に使用するプロトコルを指定します。デフォルトの値は、514/UDPで、UDPプロトコルで514番ポートに転送します。プロトコルには、TCPも指定できます。UDPは到達保証のないプロトコルですので、TCPを使うのが良いでしょう。
具体的な設定方法を、ArmadilloからATDE3にログを転送する場合を例として説明します。ATDE3のIPアドレスは192.168.0.1となっているとします。メッセージの待ち受けには、TCPの514番ポートを使用します。
まず、ATDE3側の設定をおこないます。/etc/rsyslog.conf
のUDPとTCPの待ち受けに関する設定を有効にします。/etc/rsyslog.conf
の編集は、sudoコマンドを使い、特権ユーザー権限で行う必要がありますので、注意してください。
# provides UDP syslog reception
#$ModLoad imudp
#$UDPServerRun 514
# provides TCP syslog reception
#$ModLoad imtcp
#$InputTCPServerRun 514
を以下のように、修正します。
# provides UDP syslog reception
$ModLoad imudp
$UDPServerRun 514
# provides TCP syslog reception
$ModLoad imtcp
$InputTCPServerRun 514
設定を反映させるために、rsyslogdを再起動します。Debian GNU/Linuxでは、サーバーの起動、停止、再起動などは、/etc/init.d/
ディレクトリ以下のスクリプトでおこないます。
[ATDE ~]$ sudo /etc/init.d/rsyslog restart
次に、Armadilloのsyslogdを、-R
オプション付きで起動します。既にsyslogdが起動しているので、一度終了させてから再起動します。
[armadillo ~]$ ps | grep syslog
334 root 484 S syslogd -L
[armadillo ~]$ kill 334
[armadillo ~]$ syslogd -L -R 192.168.0.1:514/TCP
以上の設定を行うと、ArmadilloでloggerコマンドまたはC言語のsyslog関数で送ったメッセージが、ATDE3のrsyslogdによって/var/log/messages
に記録されます。
Armadilloでは、USBメモリやSD/microSDカードなどの外部ストレージを使用することができます。これらのストレージデバイスは、大容量のデータを保存するために大変便利ですが、扱い方に注意が必要です。
本章では、外部ストレージのデータを安全に扱う方法を紹介します。
8.5.1. データがストレージに書き込まれたことを保証する
ストレージデバイスに対するデータの読み書き速度は、CPUの動作速度やメモリの読み書きの速度と比べると、非常に遅いです。そのため、Linuxシステムでは、色々な場所にバッファを設けてストレージとのデータのやりとりを効率化しています。プログラムでファイルに対して書き込みを行った後、そのデータがストレージデバイスに書き込まれたことを保証するためには、すべてのバッファされているデータをフラッシュ(書き出し)しなければなりません。
ストリームに対するフラッシュは、fflushライブラリ関数でおこないます。しかし、fflushライブラリ関数は、ユーザー空間でバッファされているデータをフラッシュするだけで、カーネル空間でバッファされているデータはフラッシュされませんので、これでは不十分です。
syncシステムコールはカーネル空間のバッファをフラッシュします。syncシステムコールは、デバイスへの書き込みが終了するまで返ってきません。そのため、このシステムコールを使用すると、データの書き込みを保証できるように思われます。しかし、最近のストレージデバイスは、デバイス側で大きなキャッシュを持っているため、syncシステムコールから返ってきても、データは実際にはストレージデバイスに書き込まれていないかもしれません。syncコマンドでも同様です。
データがストレージに書き込まれたことを保証する最も確実な方法は、umountシステムコールかumountコマンドで、デバイスをアンマウントすることです。アンマウントが完了した時点で、すべてのデータがストレージデバイスに書き込まれていることが保証されます。
組み込みシステムでは、予期せぬタイミングで電源が遮断される状況への対応は必須ともいえるでしょう。特に、ストレージにデータを書き込みしている最中に電源断が発生すると、どうしてもデータの不整合が発生して、ファイルシステムが破壊されてしまいます。
このような状況への対処として、ジャーナリングファイルシステムを用いる方法と、ファイルシステムをリードオンリーでマウントする方法があります。
ジャーナリングファイルシステムとは、定期的にファイルシステムの状態(ジャーナル)を保存しておくことで、クラッシュが発生した場合に、ジャーナルを元に状態を復元できるファイルシステムです。ジャーナリングファイルシステムを用いると、フラッシュされていないデータがある状況で不意な電源断が発生した場合でも、少し前の正常な状態にファイルシステムを復元することができます。
Linuxシステムで標準的なジャーナリングファイルシステムは、ext3ファイルシステムです。
ext3ファイルシステムで、デバイスをフォーマットするには、mke2fsコマンドに-jオプションを付ける(Atmark Distベースのユーザーランドの場合)か、mkfs.ext3コマンド(ATDE3の場合)を使用します。
ストレージへの書き込みが必要ない場合、デバイスをリードオンリー(読み込みのみ)でマウントするのが最も確実で安全な方法です。mountシステムコールやmountコマンドには、リマウント(再マウント)オプションがあります。書き込みが必要ない場合は、リードオンリーでマウントしておき、書き込みが必要になった時だけ、読み書き可能でリマウントすることで、ファイルシステムが破壊される危険性を少なくすることができます。(もちろん、読み込みの必要すらないときは、アンマウントしておくのが一番安全です。)
ストレージに保存するデータの内容をよく吟味して、リードオンリーで済むデータがあるのならば、デバイスをリードオンリーのパーティションと書き込み可能なパーティションに分割するという方法もあります。
パーティションを分割するには、fdiskコマンドを使用します。
組み込みシステムで制限の厳しいリソースの一つが、ストレージ容量でしょう。
Armadilloでは標準のルートファイルシステムとしてRAMディスクを使用しているので、ログを出力しているだけでもルートファイルシステムの容量を使い切ってしまう、という状況に陥りがちです。
本章では、ストレージの使用状況を調べ、使用できるストレージの容量を増やす方法について説明します。
システムで使用しているストレージのサイズと、その使用量を調べるにはdfコマンドを使用します。
Armadillo-440の標準イメージでdfコマンドを実行すると、以下のように表示されます。-h
オプションにより、人間に読みやすい形式にしています。
この表示から、/dev/ram0
(ルートファイルシステムに使用しているRAMディスク)のサイズは26.9MByteで、23.9Mbyte使用されており、残り1.2MByteなので、使用率は95%であることが読み取れます。
どのファイルやディレクトリが容量を使用しているのか調べるには、duコマンドを使用します。
ルートディレクトリ直下のディレクトリの使用量を、人間に読みやすい形式で表示しています。全部で23.9Mbyte使用しているうち、半分以上の13.2MByteは/lib
ディレクトリが使用していることが分かります。
8.6.2. ルートファイルシステムの空き容量を増やす
Atmark Distでルートファイルシステムを作成すると、ルートファイルシステムのサイズは、標準では必要最小限になるよう自動で調整されます。概ね、空き容量は10%以下となります。
ルートファイルシステムのサイズを手動で設定することで、空き容量を増やすことができます。
Atmark Distのmenuconfigの「Userland Configuration[] → Vendor specific→ generate file-system option」をAutoからManualにすることで、ルートファイルシステムのサイズを手動で設定できるようになります。
「Size of the image in blocks」で、ユーザーランドのサイズをブロック単位で指定します。1ブロックは1024Byteです。
「Maximum number of inodes」で、ファイルシステムに保存できるファイルやディレクトリの数を指定します。
自動でサイズ設定されたユーザーランドがどのようなパラメータを持っているかは、make時のログから確認することができます。
一度ビルド済みのatmark-dist
ディレクトリで、make imageを実行することで、現在の設定を確認できます。以下は、Armadillo-440の標準イメージをビルドしたときの設定です。
「--size-in-blocks
」で指定されているオプションがブロック単位でのサイズで、「--number-of-inodes
」で指定されているオプションがinodeの数となります。この例では、それぞれ27241と1280となっています。手動でサイズを指定する場合は、これらの値を参考にしながら、設定してください。
例として、ルートファイルシステムのサイズを約32MByte、inode数2048に設定するには、以下のようにコンフィギュレーションをおこないます。
コンフィギュレーションを変更したあと、makeまたはmake imageを実行すると、設定したサイズでイメージが生成されます。あとは、通常と同様にromfs.img.gz
をArmadilloのユーザーランド領域に書き込んで再起動すると、ルートファイルシステムのサイズが約32MByteになります。
| ルートファイルシステムの最大サイズ |
---|
ルートファイルシステムはRAMディスクのサイズより大きくすることはできません。 RAMディスクのサイズは、カーネルの設定で決まります。Armadilloの標準設定では、32MByteとなっています。 RAMディスクのサイズを増やすには、カーネルコンフィギュレーションの「Linux Kernel Configuration → Device Drivers → Block devices →Default RAM disk size (kbytes)」を変更してください。 |
8.6.3. 一時RAMファイルシステムを使用する
ログローテーションをおこないログファイルを保存するなど、使用するファイルサイズがあらかじめ計算できる場合は、ルートファイルシステムのサイズを変更して空き容量を増やすことで対応できます。しかし、ArmadilloがFTPサーバーになっていて最大サイズの分からないファイルを受信する場合など、使用するサイズが計算できない場合は、いくらルートファイルシステムのサイズを大きくしておいても、容量不足の懸念が残ります。
そのような場合は、ルートファイルシステム以外に、別のファイルシステムを用意することで対応します。最大サイズが計算できないファイルをルートファイルシステムとは別のファイルシステムに保存することで、そのファイルシステムが容量不足になったとしても、システム全体が動作不能になる事態は避けることができます。
通常のPCやサーバーなどのLinuxシステムでは、HDDのパーテーションを分けることで、ファイルシステムを分割します。Armadillo-400シリーズでは、microSDが使えますので、それを使用するのも良いでしょう。
microSDが使えない場合は、一時RAMファイルシステム(tmpfs)を使うことができます。tmpfsは、RAMディスクと同様に、RAMの一部をストレージとして使用する機能です。
最大1MByteのRAMをtmpfsに割り当て、/mnt
ディレクトリにマウントするには、以下のようにします。
tmpfsでマウントした/mnt
ディレクトリには、ルートファイルシステムにあるファイルとは別に、合計1MByteまでのファイルやディレクトリを置くことができます。
mountコマンドをオプションを指定せずに実行すると、現在マウントされているすべてのディレクトリを確認することができます。
tmpfsをマウントする際のオプションについては、man 8
mountを参照してください。
| ramfs |
---|
tmpfsとほぼ同じ機能を提供するものとして、ramfsもあります。Armadillo-400シリーズの標準設定では、/home/ftp/pub ディレクトリがramfsでマウントされています。 ramfsは最大サイズの指定ができないため、ファイルを追加していくと、いずれRAMを使い切ってしまいます。実運用するシステムでは、ramfsではなく最大サイズを指定したtmpfsを使用する方が良いでしょう。 |
開発段階で、Armadilloのイメージをアップデートする方法には以下のものがあります。
- Hermit-At ダウンローダーを使用して、シリアル経由で書き換える。
- Hermit-At ブートローダーの tftpdl 機能を使用して、ネットワーク経由で書き換える。
- netflash コマンドを使用して、ネットワーク経由で書き換える。
- at-cgi のファームウェアアップデート機能を使用して、ネットワーク経由で書き換える。
これらの方法は、いずれも人手での操作を伴います。製品出荷後でもイメージアップデートできるような機能をつける場合、可能な限り簡単な手順でアップデートできることが望ましいところです。
本章では、なるべく人手を介さない自動アップデート機能の実現方法を紹介します。
8.7.1. USBメモリを使用してのアップデート
udevdを使用して、USBメモリを接続するだけでイメージのアップデートを自動で行う方法を紹介します。
例として、次のような動作を考えます。
USBポートにUSBメモリが接続されたら、以下の処理を行う。
- USBメモリのマウント。
- USBメモリにカーネルまたはユーザーランドのイメージファイルがあれば、フラッシュメモリをアップデート。
USBメモリが抜かれ、フラッシュメモリのアップデートが正常に終了していたら、以下の処理を行う。
USBメモリが接続されたことを検知して、特定の動作を行わせるにはudevdの機能を使用します。
udevdは、/etc/udev/rules.d/
ディレクトリに、どのようなデバイスが接続された時にどのような動作を行うか、というルールを記述したファイルを置いておくと、そのルールに従って処理をおこないます。udevルールについての詳細は、man 7 udevを参照してください。
上下いずれかのUSBポートにマスストレージクラスのUSBメモリが接続されたら、または、USBメモリが抜かれたら、/etc/config/usb_image_update.sh
という名前のシェルスクリプトを実行するルールは、以下のようになります。
$kernelには、USBメモリが接続された時に/dev
ディレクトリに作成される、「sd*[0-9]*」にマッチしたデバイスファイル名が入ります。通常、sda1になるでしょう。
上記の内容を、/etc/udev/rules.d/z99_usb_image_update.rules
という名前で保存します。
設定内容をすぐに反映するには、udevdを一度終了して再起動します。
udevdから実行されるusb_image_update.sh
は、次のようになります。
USBメモリが接続されたときは、第一引数にstartという文字列が指定されるので、start_action関数を実行します。/dev/$kernel
という名前のデバイスファイルを/mnt/auto_image_update
ディレクトリにマウントし、ファイル名がlinux*.bin.gz
またはromfs.*.bin.gz
にマッチするイメージファイルでフラッシュメモリをアップデートします。処理中は、red LEDを点滅させます。
USBメモリが抜かれた時には、第一引数にstopという文字列が指定されるので、stop_action関数を実行します。フラッシュメモリが正常に更新されていれば、rebootコマンドを実行し、再起動します。
| 注意: セキュリティホール |
---|
USBメモリを使用してのアップデート機能は、第三者がUSBポートに触れることができる環境下では、その第三者によってイメージを書き換えられる危険性が伴います。 本方法を適用できる状況であるか否かについては、十分ご検討ください。 |
8.7.2. Webサーバーを使用してのアップデート
Webサーバーにイメージファイルを置くと、自動でイメージをアップデートする方法を紹介します。
例として、次のような動作を考えます。
- 毎日定時に特定のシェルスクリプトを実行する。
シェルスクリプトでは、以下の処理をおこなう。
- Webサーバーにアクセスし、更新すべきイメージファイルがあるか確認する。
- ファイルがある場合取得し、フラッシュメモリをアップデート。
- 正常に書き込みが完了したら、変更を反映するためにリブート。
毎日定時にスクリプトを実行する処理は、cronに任せることにします。cronの設定は、「cronで定期実行する」を参照してください。
毎日4:00に処理を実行する場合のcrontab
の設定は以下のようになるでしょう。イメージのアップデートを行うスクリプトは、/etc/config/web_image_update.sh
という名前だとします。
cronから実行されるweb_image_update.sh
は、次のようになります。wgetコマンドでイメージファイルを取得し、netflashコマンドでフラッシュメモリを書き換えます。SERVER_IP_ADDRESS(WebサーバーのIPアドレス)、PROTCOL(httpまたはhttps)、USER_NAME(認証を行う場合のユーザー名)、PASSWORD(認証を行う場合のパスワード)、KERNEL_IMG_PATH(カーネルイメージのパス)、USERLAND_IMG_PATH(ユーザーランドイメージのパス)の各変数は、環境に合わせて書き換えてください。
wgetコマンドを使用することで、httpプロトコルだけでなく、httpsプロトコルも使用することができます。また、USER_NAMEとPASSWORD変数を指定することで、basic認証またはdigest認証を利用できます。