起動スクリプトを知って基礎を理解しよう〜FreeBSD/Solaris編〜
![]() |
![]() |
![]() |
いちばん近道なLinuxマスター術 |
連載第1回目では,Linuxの起動プロセスを紹介した。今回は,FreeBSDとSolarisの起動プロセスを解説しよう。UNIXは起動プロセスを知ってこそ,基礎が理解できることを忘れないでほしい。FreeBSD,Solaris共にLinuxの起動プロセスとの共通点はあるものの,それぞれ特有の部分も多いのだ。 |
起動スクリプトを知って基礎を理解しよう〜FreeBSD/Solaris編〜
起動プロセスはFreeBSDやSolarisであっても,Linuxと同じくinitがいちばん最初に起動される。今回は,2つのOSでの処理内容を紹介していこう。まず最初はFreeBSDの起動処理パターンだ。
FreeBSDは,initの最後に「/etc/rc」というファイル名のシェルスクリプトを実行する。このrcスクリプトに記述された順番に起動処理が行われるのだ。rcスクリプトの処理が終わると,「/etc/ttys」スクリプトを実行し,「login:」というログインプロンプトを表示してユーザーのログイン待ち状態になる。FreeBSDでは,ほとんどの起動処理がrcスクリプトの中で行われることを覚えておこう。
どのような初期化を行うかは,rcスクリプトの最初で読み込む/etc/rc.confによって設定する。このファイル内に設定を記述することにより,特定のプログラムを起動させることが可能だ。このため,rc.confファイルは管理者がもっともよく知らなければならないファイルの1つといえる。
rcスクリプトの処理プロセスを具体的に追っていこう。rcスクリプトでは,おもに次のような処理が順番に行われている。ただし,例として挙げている内容のため,SendmailなどのMTAは,インストール環境によって異なるため注意が必要だ。
PATH の設定 | 内 容 |
/etc/rc.diskless1 の実行 | ディスクレスブートの際の設定 |
/etc/rc.conf の読み込み | 設定項目の読み込み |
ファイルシステムのマウント | fstab の内容にそってディスクをマウント |
adjkerntz の実行 | |
/var の中を削除 | 一時ファイルを削除 |
/etc/rc.sysctl を実行 | |
/etc/rc.serial を実行 | シリアルの設定を行う |
/etc/rc.pccard を実行 | PCカードサービスを起動する |
/etc/rc.network を実行 | ネットワークサービスを開始する |
/tmp の中を削除 | 一時ファイルを削除 |
syslogd を実行 | syslog を起動する |
quota の有効化 | quota を有効にする |
inetd の実行 | inetd を起動する |
cron の実行 | cron を起動する |
lpd の実行 | lpd を起動する |
sendmail の実行 | sendmail を起動する |
usbd の実行 | usbd を起動する |
/etc/rc.i386 の実行 | アーキテクチャ依存(APMなど)の設定を行う |
/etc/rc.devfs の実行 | devfs の設定を行う |
rc.d の実行 | /usr/local/etc/rc.d /usr/X11R6/etc/rc.d の中にある *.sh スクリプトを実行 |
/etc/rc.local の実行 | 独自の設定を行う |
rc スクリプトでは、各種の外部スクリプトを呼ぶことによって rc スクリプトそのものを編集する必要を極力減らしている。
rc.confは,/etc/または/etc/default/ディレクトリに置かれている。ただし,/etc/default/の方が先に読み込まれる。ファイル内容を変更する場合には,変更するものだけ,もしくは標準のrc.confを/etcディレクトリにコピーしてから編集するようにしたい。
次に独自に処理を追加する方法を解説しよう。ここでは,例としてhttpサーバのApacheを自分でインストールして起動スクリプトを追加する手順を見る。Apacheのインストール先は,/usr/local/apacheディレクトリだ。
Apacheの起動スクリプト例は,次の通りだ。
#!/bin/sh APACHE=/usr/local/apache if [ -x $APACHE/bin/httpd -a -x $APACHE/bin/apachectl ]; then $APACHE/bin/apachectl start echo -n 'apache ' fi |
次にこのスクリプトを apache.sh というファイル名で,/usr/local/etc/rc.dディレクトリに保存する。ファイルのパーミッションは,必ず755に設定しておくことを忘れずに。
# cp apache.sh /usr/local/etc/rc.d # cd /usr/local/etc/rc.d # chmod 755 apache.sh |
これで,次回のマシン起動時から自動的に実行されるようになる。これは,先に紹介したrcスクリプトの中で,/etc/rc.d や/usr/local/etc/rc.dディレクトリの中の「*.sh」スクリプトを自動的に実行するようになっているからである。
このように,独自に追加したサーバの自動起動は /etc/rc.dディレクトリ,あるいは/usr/local/etc/rc.dディレクトリに起動用シェルスクリプトを作成しておくのだ。
マシンをシャットダウンする際に何らかの特定の終了処理を行わなければならないような場合もあるだろう。こんな時は,起動スクリプトを設置するだけでは不十分である。そのような場合には,/etc/rc.shutdownファイルのスクリプトの中で,終了のための処理ファイルを別に呼び出すようにする。
例えば,Apacheの場合には,「Insert shutdown procedures here」という記述の後に,次のように追加しよう。このように,FreeBSDではRedHat Linuxなどと比べて比較的シンプルに設定を行うことが可能である。
echo -n Shutting down daemon processes: # Insert shutdown procedures here /usr/local/apache/bin/apachectl stop |
ここまでに紹介したように/etc/rc.dや, /usr/local/etc/rc.d に置かれた *.sh スクリプトは無条件に実行される。サーバの起動であってもその他の処理であってもまったく同じように起動時に実行することができるのだ。
しかし,ちょっとしたコマンドの実行などで,専用スクリプトを用意するまでもないという場合もあるだろう。そのような場合には,/etc/rc.localスクリプトに記述しておくのがよい。
このスクリプトファイルは,rc.d ディレクトリのスクリプトの実行が終わった後に実行されるファイルだ。インターネットサービスの起動以外のちょっとしたツールの起動処理などに適している。
Solarisの起動プロセスについて解説しよう。Solarisでも,LinuxやFreeBSDと同じくinitが最初のプロセスとなり起動処理が行われる。initの動作設定は,/etc/inittabファイルに記述されている。
また,inittabファイル内では,次のような共通書式になっているため,基本さえ押さえておけば内容を理解するのは難しくないだろう。
<id>:<rstate>:<action>:<process>
フィールド | 内容 | 例 |
id | 1,2 | 文字のユニークな文字列ap, fs, s0 |
rstate | エントリを処理する | run level |
action | エントリのふるまい | |
process | 実行するプログラム | /sbin/rc3 |
実際のinittabファイルを見てみよう。
「id」フィールドは,そのエントリを識別するための1文字,ないしは2文字のユニークな文字列を指定する。「rstate」では,そのエントリを実行するrun levelを指定する。例えば,そのエントリをrun level「2,3,4,5」で実行する場合,「2345」と記述する。「s」という文字列がついている場合,シングルユーザーモードの場合に実行される。
「action」は,そのエントリの挙動を指定するもので,ここで指定されているものの内容は以下の通りである。
オプション | 処理内容 |
initdefault | initが最初に起動された時に実行される |
sysinit | initの起動後,特定のrun levelに移行する前に実行される |
respawn | プロセスが実行されていなければ実行される |
wait | 該当するrun levelに入ったらprocessを実行してその終了を待つ |
powerfail | initがSIGPWRシグナルを受けた時に実行される |
「process」フィールドは,そのエントリで実行されるプロセスを指定する。これらを総合すると,Solarisの起動時には,まずinitが起動され,
ap::sysinit:/sbin/autopush -f /etc/iu.ap ap::sysinit:/sbin/soconfig -f /etc/sock2path fs::sysinit:/sbin/rcS sysinit >/dev/msglog 2<>/dev/msglog </dev/console |
が実行される。次の行が読み取られ結果としてrunlevel 3に移行する。
is:3:initdefault: |
さらに,次の行が読みとられ,必要なアプリケーションの起動などが行われる。
s2:23:wait:/sbin/rc2 >/dev/msglog 2<>/dev/msglog </dev/console s3:3:wait:/sbin/rc3 >/dev/msglog 2<>/dev/msglog </dev/console |
最後には,次の行が読み込まれて完了する。
c:234:respawn:/usr/lib/saf/sac -t 300 co:234:respawn: /usr/lib/saf/ttymon -g -h -p "`uname -n` console login: " -T sun-color -d /dev/console -l console -m ldterm,ttcompat |
スクリプトファイルの中を見てみよう。rcスクリプトの仕組みは次のようになっている。
Solaris では起動時の初期化やサーバアプリケーションの起動などは,/etc/rc2.d,/etc/rc3.dの中にあるスクリプトで行われる。initによって実行される/sbin/rc2,/sbin/rc3は,それぞれ/etc/rc2.dや,/etc/rc3.d の中のスクリプトを実行するのだ。
ここでは,実際に起動時の run level において,どのような処理が行われているのかを順を追って見ていき,その後で独自のプログラムの起動などを追加したい場合の方法を解説する。inittabによると,起動時のrun levelは「3」となっており,run levelが3の場合に実行される処理は次の2つである。
s2:23:wait:/sbin/rc2 >/dev/msglog 2<>/dev/msglog </dev/console s3:3:wait:/sbin/rc3 >/dev/msglog 2<>/dev/msglog </dev/console |
/sbin/rc2 は,/etc/rc2.d の中のスクリプトを実行する。rc2.dディレクトリの中を確認すれば,実行されるサービスが確認できる。
% ls /etc/rc2.d/ |
まず,「K」で始まるスクリプトを次のように実行した後,
/etc/rc2.d/K07dmi stop /etc/rc2.d/K07snmpdx stop /etc/rc2.d/K16apache stop /etc/rc2.d/K28nfs.server stop |
「S」で始まるスクリプトを次のように実行する。
/etc/rc2.d/S01MOUNTFSYS start /etc/rc2.d/S5RMTMPFILES start /etc/rc2.d/S20sysetup start ... /etc/rc2.d/S99audit start /etc/rc2.d/S99dtlogin start |
これらのスクリプトは,Linux の場合と同じように「start」や「stop」をコマンドライン引数として取るようになっている。「start」の時には起動処理を,「stop」の場合には終了処理を行うようになっている。 例えば,「S88sendmail」の場合は次のようになっていて,1つのスクリプトで起動と終了ができるようになっている。
例:「/sbin/sh」スクリプト
別ウィンドウで見る or 06a2.txt
run level 3の場合でも,run level 2と同じく,/etc/rc3.d の中のスクリプトが「K」スクリプト,「S」スクリプトの順番に起動される。
% ls /etc/rc3.d README S15nfs.server S50apache S76snmpdx S77dmi % |
上記の場合では,「K」スクリプトがないため「S」スクリプトが順番に次のように実行される。
/etc/rc3.d/S15nfs.server start /etc/rc3.d/S50apache start /etc/rc3.d/S76snmpdx start /etc/rc3.d/S77dmi start |
実際に独自の処理を追加する方法を解説しよう。rc スクリプトで処理を追加する場合,「start」や「stop」をコマンドライン引数として理解できるスクリプトを作成する必要がある。テンプレート(雛型)としては,次のようになるだろう。この中に記述されている「start」や「stop」に該当する処理を記述するのだ。
#!/sbin/sh case "$1" in start) echo "start" ;; stop) echo "stop" ;; *) echo "Usage: $0 {start|stop}" exit 1 ;; esac exit 0 |
例えば,Apacheを/usr/local/apacheにインストールした場合,次のようになる。これでApacheを起動,終了することのできるスクリプトができたことになる(Apacheの場合は制御するapachectlと呼ばれるプログラムが用意されている)。
#!/sbin/sh killproc() { pid=`/usr/bin/ps -e | /usr/bin/grep -w $1 | /usr/bin/sed -e 's/^ *//' -e 's/ .*//'` [ "$pid" != "" ] && kill $pid } case "$1" in start) /usr/local/apache/bin/httpd echo "start" ;; stop) killproc httpd echo "stop" ;; *) echo "Usage: $0 {start|stop}" exit 1 ;; esac exit 0 |
ここで定義されている「killproc」という関数は,プログラム名で指定してプロセスを終了するためのものだ。プロセスIDが分かっていないような場合に利用することができる。あとは,この完成したスクリプトを,起動または終了させたいrun level用のrcディレクトリに,「S??apache」または「K??apache」のような名前でコピーするだけである。「??」の部分は,該当するrun levelの中で処理される順番になる。前後のスクリプト番号から判断する必要がある。例えば,run level 3で50番目に起動させたい場合には次のようになる。
# cp apache.sh /etc/rc3.d/S50apache # chmod 755 /etc/rc3.d/S50apache |