もくじ

起動時にファイルのコピーや設定変更をする方法(2010/6/27)

概要

生徒用機へのファイルのコピーや設定変更が、起動時のrc.localで自動的におこなわれるようにする。

歴史

生徒用機がWindowsだったころドメインログオンするときにサーバーの指定場所のバッチファイルが実行されることになっていた。これを利用してインストールし忘れたソフトのファイルやバージョンアップされたソフトのファイル、ショートカットなどをコピーするように指定できた。サーバーに仕掛けをすれば生徒がログオンするだけで、全機の設定が済むのはたいへん助かる。数百キロバイトのファイルなら速度的にも問題はなかった。

Linuxではそのような仕組みはないが、rc.localを使ってサーバー上のディレクトリをマウントし、そこに置いたスクリプトを実行させることで同様のことができる。

Linuxに移行した翌年の2008年から機種ごとに行っている。

生徒機のrc.localに加筆

rc.localとはLinuxが起動する過程で実行されるシェルスクリプトで、管理者権限で実行されている。この実行が終わると一般ユーザーがログインできる状態になる。実際にはX-Windowシステムが起動してGUIでのログインをすることになる。

Debianでは次のように使用する場合の注意書きだけあるファイルである。

#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.

exit 0

このexitの前に次のように加える。

# add adachi for execute script on server
test -d /mnt/sys || mkdir /mnt/sys
mount -t nfs jonah:/zhome/fish-rc /mnt/sys
pushd /mnt/sys
if [ -x ./rc.sh ] ; then
  ./rc.sh
  date >/tmp/rc-execute.txt
  echo 'true' >>/tmp/rc-execute.txt
  chmod 0666 /tmp/rc-execute.txt
else
  date >/tmp/rc-execute.txt
  echo 'false' >>/tmp/rc-execute.txt
  chmod 0666 /tmp/rc-execute.txt
fi
popd
umount /mnt/sys
rmdir /mnt/sys 

exit 0
test -d /mnt/sys || mkdir /mnt/sys
/mnt/sysというディレクトリがあるかどうかを調べてなければ作る。ディレクトリが作ってあり、そのままでもよければこんな面倒なことはいらないが、別な環境に移植したりしてうっかり忘れることもあるので、
mount -t nfs jonah:/zhome/fish-rc /mnt/sys
jonahというサーバーの/zhome/fish-rcを、/mnt/sysにnfsマウントをする。
pushd /mnt/sys
現在のカレントディレクトリを記憶して/mnt/sysに移る。(記憶してpopdで戻しているのだが、カレントディレクトリを戻す必要はないかもしれない。でも念のため)
./rc.shを/mnt/sys/rc.shにすればカレントディレクトリを移すことも不要だが、こうしておくことでrc.sh内の記述が移植の時に書き換えなくてもよくなるかもしれない。
if [ -x ./rc.sh ] ; then
rc.shが存在し、実行可能であるときだけ実行するためのもの。スクリプト作成過程で確認しながらつくるためにこのようにした。なにかトラブルがあったときにdate,ech,chmodの3行とともに役立つかもしれない。
./rc.sh
サーバーの/zhome/fish-rcディレクトリに入れておくスクリプト。名前は自分で決める。fish-rcのfishは機種をあらわしている。スクリプトの他にコピーするファイルなどを機種ごとに用意するのでディレクトリ名で分けるのが都合が良い。
date,ech,chmodの3行
時間と、実行したかどうかをファイルに記録する。作成過程のテストのため書いたものを残している。
else~fi
実行しなかったことの報告をファイルに記録する。
popd
pushdで記憶したディレクトリに戻る。これは必要ないかもしれないが念のため。
umount /mnt/sys
終わったらマウントを解除
rmdir /mnt/sys
ディレクトリも削除。(これもいらないかも。でもけじめ)

もう少し簡易にすれば、これだけ。でも動く

mount -t nfs jonah:/zhome/fish-rc /mnt/sys
pushd /mnt/sys
./rc.sh
popd
umount /mnt/sys
exit 0

サーバーに/zhome/fish-rcの提供を加える

マウントができる様にサーバーの/etc/exportsに加筆

root@jonah:/zhome/vine-rc# cat /etc/exports
# /etc/exports: the access control list for filesystems which may be exported
#               to NFS clients.  See exports(5).
/zhome/vine-rc  10.0.0.0/255.0.0.0(rw,sync,no_root_squash)
/zhome/fish-rc  10.0.0.0/255.0.0.0(rw,sync,no_root_squash)

もちろんIPアドレスはネットワークの設定に合わせて吟味する。

サーバーに置くrc.sh の内容

何を書くかはそれぞれ。

機械にセットする内容の場合、クラスの人数が異なったり、欠席があったりするので、何クラスかの授業で実行することになる。繰り返したくないときは工夫が必要。

ユーザーへのセットする内容もできるが、欠席などを考えると、サーバー上で全員のユーザーホームに書き換えをする方が簡単かもしれない。

事例 1. hexerというプログラムとマニュアルをコピーする

1台にインストールして、どこにファイルが格納されたかを調べて、それを記述。これは端末からCUIで起動するプログラムなので、本体さえあれば使える。メニューは考慮する必要がない。

#!/bin/bash
cp hexer /usr/bin/
cp hexer.1.gz /usr/share/man/man1/

vine-rcディレクトリに必要なファイルを置く

root@jonah:/zhome/vine-rc# ll
-rwxr-xr-x 1 root root 177560 2009-05-18 12:57 hexer
-rw-r--r-- 1 root root   8429 2009-05-18 12:57 hexer.1.gz
-rwxr--r-- 1 root root    221 2009-05-18 12:58 rc.sh

事例 2. windows.iniファイルの一部書き換え

windows.iniはWindowsMeのファイル。vineという機種のメモリを512MBから1GBに増設した。デュアルインストールしてあるLinuxは問題なかったがWindowsMeはメモリが多すぎで起動できなくなった。調査の結果windows.iniにメモリの制限を書き加えればよいことがわかったが、なにせ起動しない。Linuxで起動して、Windowsパーティションをマウントして書き換えるというかなりの手数。そこで、rc.local

windows.iniにはログインしたことのあるユーザー名のリストが入っているので単純にファイル全体をコピーしてはいけない。

そこでpatchを使って一部だけ書き換える。

diffとpatch

diffで差分ファイルを作ってpatchで先方が更新するという手順になる。

diff

diff -u /mnt/windows/system.ini /mnt/windows/system.inito >diffsystem1g
           変更前のファイル        変更後のファイル        差分ファイル

普段気楽に使っているdiffを使ってリダイレクト。オプションの-c,-uでファイル名が入ってpatch向けになる。

どちらも使えるが-uがよりコンピュータ向き。冗長な部分をなくしている。-cが人間向き。目視で違いを把握しやすい。

できたファイルの内容

$ cat diffsystem1g
--- /mnt/windows/system.ini	2009-05-23 18:30:10.000000000 +0900
+++ /mnt/windows/system.inito	2009-05-23 20:14:24.000000000 +0900
@@ -44,6 +44,8 @@
 woafont=dosapp.fon
 device=*enable
 display=*vdd,*vflatd
+;REM for1GB adachi 090523
+MaxPhysPage=40000
 
 [drivers32]
 msacm.lhacm=lhacm.acm
@@ -94,6 +96,8 @@
 MPEGVideo2=mciqtz.drv
 
 [vcache]
+;REM for1GB adachi 090523
+MaxFileCache=524288
 
 [MSNP32]

patch

変更したいファイルのあるディレクトリに移動して差分ファイルをリダイレクトで読み込ませる。

-b はバックアップを作る指定。

patch -b </home/c1g05/diffsystem1g 

お試し結果

diffではsystem.ini(旧)→system.inito(新)

patchではsystem.ini(旧)→system.ini.orig 、system.ini+diffsystem1g→system.ini(新)

-rwxr-xr-x 1 root root      78 2002-03-28 18:16 system.cb
-r-xr-xr-x 1 root root 1556512 2008-03-06 19:09 system.dat
-rwxr-xr-x 1 root root    3227 2009-05-23 20:27 system.ini
-rwxr-xr-x 1 root root    3133 2009-05-23 20:27 system.ini.orig
-rwxr-xr-x 1 root root    3227 2009-05-23 20:14 system.inito

起動時rc.local

#!/bin/bash
sys=$PWD
mkdir /mnt/win
mount /dev/hda1 /mnt/win
pushd /mnt/win/windows
hst=`hostname`
if [ -s system.ini.orig ]; then
   ls -l system.i* >>$sys/done/$hst
   echo 'already done, do nothing'>>$sys/done/$hst
elif [ -f system.ini.rej ]; then
   ls -l system.i* >>$sys/done/$hst
   echo 'found rej file, do nothing'>>$sys/done/$hst
else
   patch -b < /mnt/sys/diffsystem1g
   ls -l system.i* >>$sys/done/$hst
   echo 'patched' >> $sys/done/$hst
fi
popd
umount /mnt/win
rmdir /mnt/win

Linuxクライアント/サーバ運用
聖愛中学高等学校
安達 順一
http://www.seiai.ed.jp/
2010-06-29