UbuntuでカスタムライブDVDを作る

このページ、2009/02/05に大幅改定した。
2009/02/10にプログラムを更新。

起動後に直ぐサーバ(SSH/NFS/SMB/WEB 等)が使えるUbuntuの自作ライブDVDを作成した。

Ubuntu Desktop版では、インストールCD=ライブCD となっていて、“コンピュータに変更を加えないでUbuntuをつかてみる”でデモではなく実際のUbuntuの環境が(HDDにインストールすることなく)直ぐに利用できる。このライブCDは便利なので良く利用する。保守やトラブル対応に便利だ。時々、1〜2日電源を入れたままでWindowsのPCをUbuntuのPCとして使う事もある。

しかし、オリジナルのライブCDでは利用できるユーティリティが制限されているし、何よりCDからブートした状態だと、ネットワークからSSHでログインしたり、vino(リモートデスクトップ)でネットワークから操作できない。これを行うにはライブCDを立ち上げた後、パッケージをインストールしたり設定を変更しなければならない。

私の“おうちサーバ”はリビングにおいて別の部屋からネットワークを通して使う。従って、運用管理やトラブル時もネットワーク通して行うことになる。(リビングのテレビに接続して使えないこともないが、接続ケーブルの切替とかがめんどくさい。)そこで、Ubuntu Desktop CDをカスタマイズして、いちいちSSHサーバのインストールしたりvinoの環境を設定しなくても、CDから立ち上げれば直ぐにネットワークからのアクセスを受け付けるようにした。つまり、自分専用のライブCDを作成した。

更に、UbuntuはライブCDは容量が約700MBを超えないように作られているが、自作のカスタムであればライブDVDでもいい。必要な(というか不必要なもの含めて)テンコ盛りのライブDVDを作った。DVDから起動すると、SSHサーバだけでなく、nfsサーバ、sambaサーバ、DNSサーバ、Webサーバ等などが動いている状態になる。

ライブCDの中身は?

色々と試している内に分かって来たのは、Ubuntu Desktopの場合、HDDへのOSのインストールは一々debパッケージから解凍・設定するのではなく、ライブCDのOSイメージをそのままコピーして、その後で必要に応じて設定を変更したり、不必要なパッケージを削除したりしているようだ。逆に言えば、HDDの内容を読み出し専用のCDイメージとして書込み、これを使ってあたかも読み書きできるように見せかけてライブシステムを実現している。これを実現しているのがcasper*1というシステムであり、その中核にはaufs(another unionfs)というファイルシステムを使っている。(このcasperを使えば、ディスククライアントも簡単に構成できる。“ライブUbuntuをネットワークブートする − ディスクレスサーバ構築”参照。)

ライブCDのUbuntu環境で使っているパッケージとHDDにインストール直後のパッケージの状態を比べると、ライブCDから次のパッケージが削除されていることが分かる。(Ubuntu Desktop 8.10 amd64

casper, gimp-help-common, gimp-help-en, gparted, grub, hunspell-en-us, jfsutils,
language-pack-en, language-pack-en-base, language-pack-es,
language-pack-es-base, language-pack-gnome-en, language-pack-gnome-en-base,
language-pack-gnome-es, language-pack-gnome-es-base, language-pack-gnome-xh,
language-pack-gnome-xh-base, language-pack-xh, language-pack-xh-base,
language-support-en, language-support-translations-en,
language-support-writing-en, libdebconfclient0, libdebian-installer4, libntfs10,
localechooser-data, lupin-casper, myspell-en-au, myspell-en-gb, myspell-en-za,
ntfsprogs, openoffice.org-help-en-gb, openoffice.org-help-en-us,
openoffice.org-hyphenation, openoffice.org-hyphenation-en-us,
openoffice.org-l10n-common, openoffice.org-l10n-en-gb,
openoffice.org-l10n-en-za, openoffice.org-thesaurus-en-au,
openoffice.org-thesaurus-en-us, os-prober, rdate, thunderbird-locale-en-gb,
ubiquity, ubiquity-casper, ubiquity-frontend-gtk, ubiquity-ubuntu-artwork,
user-setup, wamerican, wbritish, xfsprogs

逆言えば、インストール直後のOSにこのパッケージを“再”インストールすればライブCDと同じ環境ができる。

そしてライブCDでは“/casper/filesystem.squashfs”というファイルに“rootファイルシステム”の本体が格納されていて、このイメージファイルを / にマウントすることでライブ環境を実現している。(squashFSLZMAという圧縮方式を使った読出し専用圧縮ファイルシステムで、結構高速で動くらしい。)従って、カスタムDVD用に作成したファイルシステムsquashFSでこのファイルと置き換えれば良いことになる。

一方、Ubuntu Server版は全く異なるCDの構造をしている。CDの“/pool/”というディレクトリの下に“main”と“restricted”に分かれてdebパッケージの形でソフトウェアが格納されていて、これをインストール時に展開する。Ubuntu Desktop版では/pool/の下に格納されているソフトウェアはごく僅かで、殆どがデバイス依存しているドライバ類とコンパイラ類の様だ。環境に合わせてインストールが必要なためだろうか。

ここでライブDVDのrootファイルシステム(/casper/filesystem.squashfs)を作成する方法に大きく2つの方法がある。一つはオリジナルCDの中にある“/casper/filesystem.squashfs”を適当なディレクトリにマウントしてコピーをとり、そのコピーにchrootして変更を加える方法。これはオリジナルのCDに一番近いカスタムDVDを作成できるが、作業が基本的にコマンドラインだけであり、GUIのカスタマズが(不可能ではないが)大変手間がかかる。

もう一つは、普通にHDDにLinuxをインストールして、それをベースに/casper/filesystem.squashfsを作成する方法。GUI環境でのカスタマイズもできるが、casper関連の設定がマニュアルが無いので手さぐりになってしまう(どこかに落ちているとは思うのだが)。しかし、今回はこの方法で作成しみた。

大まかな手順

大まかな手順は以下の通りとなる。

1.ライブDVDで使うファイルシステムの元となるLinuxをHDDにクリーン・インストールする
2.インストールしたLinuxを使いやすい様にカスタマイズする
3.Ubuntu Desktop CDとLinuxファイルシステムから新しいDVDを作成する準備をする
4.Ubuntu Desktop CDとLinuxファイルシステムから新しいDVDを作成する
最後の第4ステップはシェルスクリプトによるプログラムを実行するだけである。カスタムDVDを作成するシェルスクリプトを“mkudvdプログラムリスト”に載せておいた。

各ステップの具体的な説明の前に、作業環境について触れておく。私は今回、VMware仮想マシン環境を作業場所とした。この仮想マシンには2つの仮想ディスクを付けていて、次のような構成である。
1. DVD作成用マシンのOS(Ubuntu Desktop 8.10)の仮想HDD(作業領域が必要なので12GB以上)
2. ライブDVDのための雛型Linuxがインストールされている仮想HDD
以降の説明は基本的にこの環境を使った場合について話すが、勿論、実マシンでも作業は出来る。最低2パーティションが必要で、マシンを動かすためのOSのパーティションと、もう1つは雛型Linuxのためである。(これらの2つのパーティションは同じHDDにあっても異なるHDD上にあっても構わない。)

以降では、分かりやすいように1ディスク1パーティションとして話を進める。(パーティションは論理パーティションではなく物理(プライマリ)パーティションとする。)

*1:Run a "live" preinstalled system from read-only media:読出し専用メディアに予めインストールされた“ライブ”システムを実行する

ライブDVD用の雛型Linuxをクリーンインストールする

まず、2台目のHDDにライブDVDための雛型Linuxをインストールする(1台目のHDDは作業用のOSをインストールするために残しておく。)
インストールにおけるポイントは、以下のとおり。

  • 出来る限りデフォルト(標準値)でインストールする。標準構成で余計な設定を避けるのは、ライブDVDをインストールDVDとして利用する際、ここでのOSの構成や設定がHDDにインストールされたOSにも引き継がれるため。例えば、パスワード無しでsudoができるように設定してしまうと、HDDにインストールしたOSでもパスワード無しでsudoできる様になってしまう。もっとも、これを利用してHDDにインストール時に設定済みのインストールCDを作成することができる。ただ、今回はHDDにインストールした時に標準の設定になっているようにする。(サーバ機能付きライブDVDとして使う場合は、起動した時点で幾つかの設定が済んでいなければならないが、その設定は雛型Linuxに対して行うのではなく、“casper”というシステムに手を加えることで実現する。)
  • ユーザ名は何でも構わないが、ライブCDとの整合性を考えて“ubuntu”にした。なお、インストール中に作成するユーザのuidは“1000”となるが、ライブCDでのubuntuのuidは“999”なので、インストール後に999に変更する。
    • 説明:Live session user
    • ユーザ名:ubuntu
    • パスワード:ubuntu
    • コンピュータ名:(任意、オリジナルCDに合わせる場合は”ubuntu”)
    • 自動的にログイン:チェックしない

この条件で通常にインストールする。

ubuntuのuid、gidの変更

まず、一回目のブートで ubuntu のuid 、gidを999に変更する。大まかな手順は次の通り。

% sudo -s
# vipw
# vipw -g
# ls -l /home
# chown -R 999:999 /home/ubuntu
# ls -l /home
# reboot

ここではsudoのパスワードを求められるのでインストール時に設定したパスワード(ubuntu)を入力する。

また、chownで /home/ubuntu/.gvfs と言うディレクトリの所有者を変更できないというエラーが発生する。ls -lで確認するとディレクトリの属性がおかしな表示になっている。多分、Ubuntu(もしくはGNOME)のバグと思われる。2回目のブート時にはuid 1000としてアクセスできる様になるので、再度2回目のブートでchownする必要がある。

パッケージを更新、追加する

2回目のブートでは、(最初に /home/ubuntu を再度chownを実行しておくのを忘れずに)uid、gidを確認の上、インストールしてあるパッケージを最新版に更新する。

% sudo -s
# chown -R ubuntu:ubuntu /home/ubuntu

パッケージの更新は“dist-upgrade”として実行することで、最新版のカーネルを持った雛型Linuxを構築できる。

# apt-get update
# apt-get dist-upgrade
(console-setup等幾つかのパッケージで質問がでるがデフォルトで(単に“ENTER”を押すだけ)。)

ここでリブートするように促されるので素直にリブート。

パッケージの追加と設定

3回目のブートでパッケージの追加と各種設定を行う。

先ずはオリジナルのライブCDからHDDへインストールした際に削られたパッケージ群を“再”インストールしておく。これらのパッケージを追加することで、作成するカスタムDVDでもOSインストールなどの作業が可能となる。パッケージの依存関係から、次の9つのパッケージを追加すれば良い。(但し、Ubuntuのバージョン等に依存するので Uuntu8.10 Desktop 以外では確認が必要。)

% sudo -s
# apt-get install ubiquity 
# apt-get install lupin-casper
# apt-get install language-pack-es
# apt-get install language-pack-gnome-es
# apt-get install language-pack-gnome-xh
# apt-get install language-pack-xh
# apt-get install gparted
# apt-get install jfsutils
# apt-get install xfsprogs

後は、保守作業や個人の趣味で必要なパッケージを追加すればいい。今回は次のようなパッケージを追加してみた。これでほぼ Ubuntu Desktop + Ubuntu Server の機能を持ったライブDVDを作ることができる。(保守用“ライブ環境”での使用なのでデータベース関係とメイル関係は省いた。)

% sudo -s
# apt-get install apache2
# apt-get install bind9 bind9-doc
# apt-get install build-essential
# apt-get install ethtool
# apt-get install fdutils
# apt-get install installation-report
# apt-get install kpartx
# apt-get install landscape-common
# apt-get install lvm2
# apt-get install mdadm
# apt-get install mii-diag
# apt-get install netcat-openbsd
# apt-get install nfs-kernel-server
# apt-get install ntp
# apt-get install openssh-server
# apt-get install php5
# apt-get install samba samba-doc
# apt-get install smartmontools
# apt-get install smbfs
# apt-get install squashfs-tools
# apt-get install sysvutils
# apt-get install tomcat6 tomcat6-admin
# apt-get install ttf-dejavu
# apt-get install ubuntu-minimal
# apt-get install util-linux-locales
# apt-get install winbind

これで従来のライブCDでは扱えなかった論理ボリューム(lvm)やRAIDのHDDも利用できる様になる。また、opensshサーバ等の各種サーバも動かすことができる。ただし、サーバ類の設定(例えば、NFSサーバに対してどのディレクトリを開放するか等)は後で casperの変更のところで行い、ここでは標準設定(インストールしたての状態)として残しておく。

最後に不要なファイルをクリーンアップして、シャットダウンする。

# apt-get autoremove
# apt-get clean
# mandb

なお、この後、ubuntuアカウントのカスタマイズを好みに応じて行う。例えば端末をメニューバーに登録してクリック1つで起動てきるようにしたり、vino(GNOME版のvncサーバ)でリモートからアクセスできる様にする、などである。ただし、システム全体に渡る設定は避けた方がいいだろう。あくまでも/home/ubuntuディレクトリの範囲内での環境設定にとどめる。

カスタムDVDのISOファイルを作成する前準備

次に、上で作った雛型LinuxファイルシステムUbuntuのオリジナルライブCDのISOイメージからカスタムDVDのISOファイルを作成する。先ずはその準備。

ここでの前提は、2台目のHDDに上でインストールした雛型のrootファイルシステムが入っている。1台目のHDDは空のままで、ここに作業用のLinuxをインストールする。通常のインストールと同じで、ただし、雛型Linuxが入っている1台目のHDDはインストール時には“どこにも接続しない”状態にしておく。1台目のHDDのLinuxは作業用なので、自分の好みに合わせてインストール、設定して構わない。

用意が整ったら作業用のLinuxを(1台目のHDDから)起動して、作業ディレクトリを作る。ここでは /livedvd というディレクトリを想定する。以降の作業はスーパーユーザ権限が必要ものが多いので、最初に sudo -s しておく。

% sudo -s
# mkdir /livedvd
# cd /livedvd

ここを作業領域として以下の準備をする。
1. オリジナルライブCDのISOイメージをコピーする
2. 雛型Linuxのディスク(2台目のHDD)をマウントする
3. 雛型Linuxのファイルをコピーする
4. squashfs-toolsパッケージのインストール
5. ライブ起動時に起動前設定を行う各種ファイルやプログラムを置く

まず、ライブCDのイメージファイルを作業用ディレクトリ(/livedvd)へコピー(もしくはUbuntuのホームページからダウンロード)する。>|

# dd if=/dev/sr0 of=/livedvd/ubuntu-8.10-desktop-amd64.iso bs=100M

次に、filesystem.org というディレクトリを作り、そこに雛型Linuxの入っている2台目のディスクを読み出し専用でマウントする。

# mkdir filesystem.org
# mount -o ro /dev/sdb1 filesystem.org

2台目に入っている雛型Linuxはそのまま残しておいて、その内容に手を加えるため、filesystemというディレクトリを作成してファイルシステムを丸ごとコピーする。

# mkdir filesystem
# rsync -ax filesystem.org/ filesystem/

ライブDVDを作る過程で、雛型のファイルシステムsquashFSという読出し専用圧縮ファイルイメージとして保存する。そのsquashFSイメージファイルを作成するための mksquashfs というコマンドを使えるようにsquashfs-toolsというパッケージをインストールしておく。

# apt-get install squashfs-tools

ライブ起動時にinitrdの状態で起動前設定を行うためのシェルスクリプトやファイルを作成して、miscというディレクトリに集める。

# mkdir misc
	:
	:
# ls misc
11adduserhome  18hostname  60setupnfs  61setupsmb  62setupntp  63setupbind  ubuntu_home.cpio.gz

ここで“ubuntu_home.cpio.gz”はubuntuのホームディレクトリをcpio形式でアーカイブしたものである。ライブDVDを作成する際に、雛型Linuxから一旦 ubuntuアカントを抹消する。ライブ環境で立ち上げる時はcasperがubuntuアカウントを作成するが、新規に作られるため雛型Linuxでカスタマイズした設定は失われている。これを起動前設定の段階(initrdの段階)で復旧するためのデータである。このアーカイブは手動で作成も出来るが、後で出てくるISO作成用シェルスクリプトの中で自動的に作成することもできる。
そしてそのアーカイブを/home/ubuntuへ展開ためのシェルスクリプトが“11adduserhome”になる。

#!/bin/sh
PREREQ=""
DESCRIPTION="Adding live session user home directory..."

. /scripts/casper-functions

prereqs()
{
       echo "$PREREQ"
}

case $1 in
# get pre-requisites
prereqs)
       prereqs
       exit 0
       ;;
esac

log_begin_msg "$DESCRIPTION"

if [ -f /var/backups/ubuntu_home.cpio.gz ]; then
    if [ -d /root/home/ubuntu ]; then
        ( cd /root/home/ubuntu ; gzip -dc /var/backups/ubuntu_home.cpio.gz | cpio -i)
    fi
fi

log_end_msg

このシェルスクリプトはcasperから呼び出されるので、それに合わせた形式で書かれている。

次の“18hostname”はオリジナルCDにもあるのだが、ライブCD(もしくはDVD)のISOファイルを使ってディスクレスクライアントを動かす場合、DHCPサーバからホスト名を取得するように改造したもの。“ライブUbuntuをネットワークブートする − ディスクレスサーバ構築”を参照。

#! /bin/sh

PREREQ=""
DESCRIPTION="Setting hostname..."

. /scripts/casper-functions

prereqs()
{
       echo "$PREREQ"
}

case $1 in
# get pre-requisites
prereqs)
       prereqs
       exit 0
       ;;
esac

log_begin_msg "$DESCRIPTION"

NETCONFIG=/netboot.config
ADDR=127.0.1.1
DOMAIN=

if [ -f $NETCONFIG ]; then

	NET_HOST=$(grep '^ host   :' $NETCONFIG | cut -f6 -d ' ' )
	if [ ! -z "$NET_HOST" ]; then HOST=$NET_HOST; fi
	export HOST

	NET_DOMN=$(grep '^ domain :' $NETCONFIG | cut -f4 -d ' ' )
	if [ ! -z "$NET_DOMN" ]; then DOMAIN=$NET_DOMN; fi

	NET_ADDR=$(grep '^ address:' $NETCONFIG | cut -f3 -d ' ' )
	if [ ! -z "$NET_ADDR" ]; then ADDR=$NET_ADDR; fi
fi

echo "$HOST" > /root/etc/hostname
cat > /root/etc/hosts <<EOF
127.0.0.1 localhost
$ADDR $HOST $HOST.$DOMAIN

# The following lines are desirable for IPv6 capable hosts
::1     ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
ff02::3 ip6-allhosts

EOF
hostname "$HOST"

log_end_msg


以下“60setupnfs”はNFSの設定プログラム、“ 61setupsmb”はSMB設定用プログラム、“ 62setupntp”はNTP設定用、“ 63setupbind”はBIND設定用のプログラムとなっていて、これらはオリジナルCDには無い。ここでは参考のために1つだけ書いてく。(その他のプログラムリストは終わりの方にまとめて書いておく。)

60setupnfs:/etc/exportsに変更を加え/tmpをネットワークからマウントできるようにしている。

#!/bin/sh

PREREQ=""
DESCRIPTION="Setting up NFS configuration..."

. /scripts/casper-functions

prereqs()
{
       echo "$PREREQ"
}

case $1 in
# get pre-requisites
prereqs)
       prereqs
       exit 0
       ;;
esac

log_begin_msg "$DESCRIPTION"

if [ -f /root/etc/exports ]; then
        echo '/tmp      *(rw,all_squash,no_subtree_check,fsid=0)' >> /root/etc/exports
fi

log_end_msg

カスタムDVDのISOファイルを作成する

ここからの作業はシェルスクリプト(mkudvd:Make Ubuntu DVD)にまとめておいた。*1 このシェルスクリプトを動かせばDVDのISOイメージが作成できる。このプログラム(“mkudvdプログラムリスト”にリストをおいてある)をコピー&ペーストしてファイルに落として実行すればいい。

# bash mkudvd

問題なく終了すれば作業用ディレクトリに ubuntu-8.10-desktop-amd64-custom.iso というISOファイルが出来上がる。

では、シェルスクリプト mkudvd の中ではどのようなことをしているのかを説明する。

パラメータ設定

今回はコマンドに引数などを持たせず、各種パラメータはハードコードにしてしまった。環境が違えばここを直せばいい。

################################################################################
# Parameter Settings

WORKING_DIR=/livedvd
ORIGINAL_CD_ISO="${WORKING_DIR}/ubuntu-8.10-desktop-i386.iso"
EXTENSION=custom

CUSTOM_DVD_ISO="${WORKING_DIR}/"`basename "${ORIGINAL_CD_ISO}" .iso`-${EXTENSION}.iso
TEMPLATE_ROOT="${WORKING_DIR}/filesystem"
MISC_FILES="${WORKING_DIR}/misc"
DVD_FILES="${WORKING_DIR}/live_dvd_files"
FS_TYPE=squashfs
REMOVE_999_ACCOUNT=1
  • WORKING_DIR

作業用ディレクトリへのパス。

  • ORIGINAL_CD_ISO

オリジナルCDのISOファイル。 ここでは“ubuntu-8.10-desktop-amd64.iso”で、これは先ほどの準備でコピーしておいたファイルとなる。

  • EXTENSION

これから作成するカスタムDVDのISOファイル名のための拡張文字列。

  • CUSTOM_DVD_ISO

これから作成するカスタムDVDのISOファイル。EXTENSIONが“custom”であれば“ubuntu-8.10-desktop-amd64-custom.iso”という名前のファイルが生成される。

  • TEMPLATE_ROOT

雛型ルートファイルシステムの格納されているディレクトリ。./filesystem (/livedvd/filesystem)とした。先程の準備で作成したディレクトリである。

  • MISC_FILES

casperによる起動前設定のためのプログラムとデータを格納しておく。./misc

  • DVD_FILES

オリジナルCDのファイルを展開する一時ディレクトリ。./live_dvd_files とした。

  • REMOVE_999_ACCOUNT

これは後程説明するが、雛型ルートファイルシステムを作成した際に作った“ubuntu”という名前のアカウント(uid=999)を残してライブDVDを作成するか、残さずにライブDVDを作成するかのフラグ。オリジナルのCDでは一般ユーザアカウントが一切含まれてない雛型を使っていて、ライブCDからLinuxを立ち上げる時に casper というソフトウェアが“ライブユーザ”つまり ubuntuのアカウントを自動的に生成する。その後、このプログラムで生成したDVDでは、ubuntuのホームディレクトリを復元する。従って、基本的には削除する(“1”を設定)にして使う。

    • “REMOVE_999_ACCOUNT=1”雛型を残さない場合
    • “REMOVE_999_ACCOUNT=” 雛型を残す場合

なお、DEBUGという変数もあるが、これもREMOVE_999_ACCOUNTと同様、有効する場合は“=1”、無効にする場合は“=”(何も値を代入しない)にする。

環境の確認

カスタムDVDを作成するのに必要な環境が揃っているかの確認。

################################################################################
# Check base files

	:
################################################################################
# Check utilities
	:

オリジナルCDをlive_dvd_filesディレクトリへ展開

################################################################################
echo "Copying original CD files"

	:
rsync -ax "${WORKING_DIR}/mnt/" "${DVD_FILES}/"

コピーにはrsyncを使っているので、再度コマンドを実行した場合は、修正があったファイルのみがコピーされ以前の状態に戻される。

ブートパラメータの調整

################################################################################
echo "Modifying boot menu parameter"

sed -i \
	-e 's/^timeout .*$/timeout 50/' \
	"${DVD_FILES}/isolinux/isolinux.cfg"

今回はブートして最初に現れる言語選択のメニューの表示時間を5秒にしてある(オリジナルでは30秒)。

雛型Linuxを整理する

いよいよ本格的な作業に入っていくが、まず、雛型LinuxをDVD作成へ向けて調整する。
先ずはrootとパスワードをチェックして必要であれば変更する。

################################################################################
echo "Triming base filesystem"

### Changing root password character

sed -i -e 's/^root:!:/root:*:/' "${TEMPLATE_ROOT}/etc/shadow"

Ubuntudebian?)の“/usr/lib/user-setup/functions.sh”にバグがある。このスクリプトの中のroot_passwordという関数の中でrootのパスワードをshadowファイルから拾う部分がある。

	if [ -e $ROOT/etc/shadow ] && \
	   [ "`grep ^root: $ROOT/etc/shadow | cut -d : -f 2`" ] && \
	   [ "`grep ^root: $ROOT/etc/shadow | cut -d : -f 2`" != '*' ]; then
		return 0
	fi

もしrootのパスワードフィールドが“!”となっていると、この式の評価結果は

	if [ ! != * ]; then

となってしまい、testコマンドの引数として不整合を起こしスクリプトが失敗する。
rootのパスワードフィールが“!”以外(例えば“*”とか)であれば良いのだが。何故かUbuntuクリーンインストール直後の状態はrootだけ“!”になっている。これはわざとか?

次にライブブートの妨げとなるファイルを削除しておく。

### Removing trouble-making files
		:
	rm -rf "${TEMPLATE_ROOT}/etc/blkid.tab"*
		:
	rm -rf "${TEMPLATE_ROOT}/etc/resolv.conf"
		:
echo "# UNCONFIGURED FSTAB FOR BASE SYSTEM" \
	> "${TEMPLATE_ROOT}/etc/fstab"
		:
rm -rf "${TEMPLATE_ROOT}/etc/mtab"
		:
ln -s "/var/lib/initscripts/nologin" "${TEMPLATE_ROOT}/etc/nologin"

これらのファイルが残っているとファイルシステムを正常にマウント出来ないなどの問題が起きる可能性がある。(一見正常に動作しているように見えるのだがDVDではなく/dev/sda1をマウントしていたりする。)nologinに関しては必要ないと思うが、オリジナルCDの内容と合わせるために再設定している。

次に、/tmp や /var の下のゴミファイルをクリアしておく。

### Removing garbage files

rm -rf "${TEMPLATE_ROOT}/tmp/"*
rm -rf "${TEMPLATE_ROOT}/tmp/".??*
		:
		:
if [ -d "${TEMPLATE_ROOT}/root" ]; then
        echo "Cleaning root directory up...."
        ( cd "${TEMPLATE_ROOT}/root"; rm -rf ${REMOVE_LIST} )
fi

DVDに焼くことを前提すれば、これらのゴミが入っていても容量的には余裕だが、DVDを作るまでにどのようなことをしたのか等の情報まで永久に焼き込まれ事になる。もっとも、よく使うコマンドをhistoryとして残しておきライブ環境で使うと言う方法もあるが。

ubuntuのホームの保存と削除

ライブDVDには一般ユーザの情報が /etc/passwdなどに入っていない状態で作成される。そこでubuntuのアカントとホームディレクトリを削除するが、その前に(もし、ホームディレクトリのアーカイブファイルが存在しなければ)ホームディレクトリをアーカイブして保存してから削除する。

if [ -d "${TEMPLATE_ROOT}/home/ubuntu" ]; then
        (
        echo "Cleaning ubuntu directory up...."
        cd "${TEMPLATE_ROOT}/home/ubuntu"
        rm -rf ${REMOVE_LIST}
        if [ ! -f "${MISC_FILES}/ubuntu_home.cpio.gz" ]; then
                echo "Backing ubuntu home up...."
                find . | cpio -o -H newc | gzip > "${MISC_FILES}/ubuntu_home.cpio.gz"
        fi
        )

fi

###
# remove pre-configured user account, ubuntu

if [ ${REMOVE_999_ACCOUNT} ]; then
        echo "Removing ubuntu account and home...."
        (chroot "${TEMPLATE_ROOT}" userdel -f -r ubuntu ) &> /dev/null
        rm -rf "${TEMPLATE_ROOT}/home/ubuntu/"
        (chroot "${TEMPLATE_ROOT}" groupdel ubuntu ) &> /dev/null
        if [ -f "${TEMPLATE_ROOT}/etc/gdm/gdm.conf" ]; then
                sed -i \
                        -e "s/^AutomaticLoginEnable=.*\$/AutomaticLoginEnable=false/" \
                        -e "s/^AutomaticLogin=.*\$/AutomaticLogin=/" \
                        -e "s/^TimedLoginEnable=.*\$/TimedLoginEnable=false/" \
                        -e "s/^TimedLogin=.*\$/TimedLogin=/" \
                        -e "s/^TimedLoginDelay=.*\$/TimedLoginDelay=/" \
                        "${TEMPLATE_ROOT}/etc/gdm/gdm.conf"
        fi
fi

ユーザの介入なくシステムをシャットダウンするようにする

オリジナルCDではライブ環境をシャットダウンする際、CDをトレイから出したことを確認するために、最後に“Enter”キーを押す必要があるが、リモート環境にあるキーボードが接続されていないマシンではいつまでもシャットダウンできなくなってしまう。そこで、その部分をキーボードの入力無しに電源オフまでたどり着くように変更する。

################################################################################
# Triming casper for maitainance works

if [ -f "${TEMPLATE_ROOT}/etc/init.d/casper" ]; then
        echo "Modifying /etc/init.d/casper ...."
        sed -i \
                -e 's/TIMEOUT 86400/TIMEOUT 5/' \
                -e '/^[ ]*read x /s/^ /#/' \
                "${TEMPLATE_ROOT}/etc/init.d/casper"
fi

雛型からカーネルとinitrdイメージをコピーする

ライブDVDで使うカーネル(vmlinuz)とinitrdイメージを雛型からコピーしておく。
その際に initrd.imgの中にあるcasper関連のファイルを変更したり、追加うる。理由は以下の通り。

  • オリジナルCDのkernel/initrdにはロジカルボリュームを扱うパッケージ(lvm)が入っていない。従ってライブLinuxを立ち上げようとするシステムに既にロジカルボリュームがあっても別に問題はなかった。しかし、カスタムDVDを作成する過程で lvm2パッケージをインストールした場合、ライブ環境でもロジカルボリュームを認識できるようになってしまう。これは保守作業には嬉しいのだが、casperはロジカルボリュームがあると正しく動作しなくなってしまう。casperがlive media(ライブ環境のデバイス、ここではCDやDVD)を探すロジックがいま一つのようだ。仕方ないので、casperがlive mediaを探し出す対象としてロジカルボリュームデバイス(dm-0等)を除外するようにスクリプトをちょっとだけ変更する。
  • ライブ環境で立ち上げる時casperは“ubuntu”というユーザアカウントを作りだすが、当然、システム標準の環境である。それに保存しておいたubuntuのホームディレクトリを展開しておいて、カスタマイズされたGUI環境を利用出来るようにする。
  • SSHNFSなどの各種サーバがシステム起動完了時に使える(外部からネットワークを通してアクセスできる)ように環境を整える。
################################################################################
echo "Modifying initrd and copy initrd and kernel"

INITRD_ROOT="${WORKING_DIR}/initrd"

rm -rf "${WORKING_DIR}/initrd.img"
rm -rf "${INITRD_ROOT}"; mkdir "${INITRD_ROOT}"
(
        cd "${INITRD_ROOT}"
        gzip -dc "${TEMPLATE_ROOT}/initrd.img" | cpio -i --quiet

        # Casper can not handle lvm device properly, then modify casper script
        # But modifying just initrd script, not usr/share/initramfs-tools/scripts/casper
        sed -i -e 's/(loop|ram|fd)/(loop|ram|fd|dm-)/' \
                "${INITRD_ROOT}/scripts/casper"

        # Change ubuntu default password to "ubuntu", from "\n"
        sed -i -e 's/U6aMy0wojraho/kBzYzm5JjWKPA/' \
                "${INITRD_ROOT}/scripts/casper-bottom/10adduser"

        # Copy add_ubuntu_home_directory script
        if [ -f "${MISC_FILES}/11adduserhome" ]; then
                cp "${MISC_FILES}/11adduserhome" \
                        "${INITRD_ROOT}/scripts/casper-bottom/"
        fi

        # Copy server setup scripts
        cp -f "${MISC_FILES}/"6[0-9]* "${INITRD_ROOT}/scripts/casper-bottom/"

        # Copy ubuntu home directory archive, if exist
        if [ -f "${MISC_FILES}/ubuntu_home.cpio.gz" ]; then
                mkdir -p "${INITRD_ROOT}/var/backups"
                cp -f "${MISC_FILES}/ubuntu_home.cpio.gz" \
                        "${INITRD_ROOT}/var/backups/"
        fi

        find . | cpio -o --quiet -H newc | gzip > "${WORKING_DIR}/initrd.img"
)
cp -f "${WORKING_DIR}/initrd.img" "${DVD_FILES}/casper/initrd.gz"

rm -rf "${WORKING_DIR}/initrd.img"
rm -rf "${INITRD_ROOT}"

cp -f "${TEMPLATE_ROOT}/vmlinuz" "${DVD_FILES}/casper/vmlinuz"

最新版のカーネルとinitrdをコピーすることで、オリジナルCDよりも最新版のライブDVD(インストールDVD)を作成できる。

雛型からsquashFSを作成する

雛型のルートファイルシステムの調整が終わったので、これを元にsquashFSのイメージファイルを作成する。これはmksquashfsというコマンドがやってくれるが数分時間がかかる。また、CDやDVD用のISOではなく、ネットワークブートするディスクレスクライアント用のISOを作成する際にsquashfsではなくext2としてイメージファイルを作成することのできるようになっている。(“mkext2fs”というコマンドもあるようだが、ここでは標準で使えるddやmkfsを使ってイメージファイルを作成している。)

SQUASH_FILE="${DVD_FILES}/casper/filesystem.squashfs"
EXT2_FILE="${DVD_FILES}/casper/filesystem.ext2"
rm -rf "${SQUASH_FILE}" "${EXT2_FILE}"

case "${FS_TYPE}" in
squashfs|squash)
	FS_FILE="${SQUASH_FILE}"
	mksquashfs "${TEMPLATE_ROOT}" "${SQUASH_FILE}"
	;;
ext2|ext)
	FS_FILE="${EXT2_FILE}"
	FS_SIZE=`du -s "${TEMPLATE_ROOT}/" | awk '{print $1}'`
	FS_SIZE=`expr "${FS_SIZE}" + "${FS_SIZE}" / 10`
	dd if=/dev/zero of="${EXT2_FILE}" bs="${FS_SIZE}" count=1024 2>/dev/null
	mkfs -F -q -t ext2 "${EXT2_FILE}"
	rm -rf mnt ; mkdir mnt
	mount -o loop "${EXT2_FILE}" mnt
	rsync -ax "${TEMPLATE_ROOT}/" mnt/
	umount mnt
	rm -rf mnt
	;;
*)
	echo "Filesystem Type is incorrect."
	echo "exit."
	exit 1
	;;
esac
chmod 444 "${FS_FILE}"

次に“manifest”というsquashFSの中にどんなdebパッケージが入っているかを表すリストを作成する必要がある。リストには2つあって一つはライブ環境で使うsquashFSの中の全てのパッケージリスト(filesystem.manifest)。もう一つはHDDにインストールするパッケージのリスト(filesystem.manifest-desktop)である。オリジナルのminifestから2つの差分を作っておく。

MANIFEST_1="${DVD_FILES}/casper/filesystem.manifest"
MANIFEST_2="${DVD_FILES}/casper/filesystem.manifest-desktop"

ORIGINAL_DIFFS=` \
        diff "${MANIFEST_1}" "${MANIFEST_2}" | \
        sed -e '/^[^<]/d' -e 's/^< //' -e 's/ .*//' \
        `

次に雛型ファイルシステムのパッケージリスト(filesystem.manifest)を作成し、これに上で求め差分を適用してHDDインストール用のmanifest(filesystem.manifest-desktop)を作りだす。

rm -rf "${MANIFEST_1}"
rm -rf "${MANIFEST_2}"

dpkg-query -W --showformat='${Package} ${Version}\n' \
         --admindir="${TEMPLATE_ROOT}/var/lib/dpkg/" \
        > "${MANIFEST_1}"

cp -f "${MANIFEST_1}" "${MANIFEST_2}"
for REMOVE_PKG in ${ORIGINAL_DIFFS}; do
        sed -i -e "/^${REMOVE_PKG} /d" "${MANIFEST_2}"
done

DVDコンテンツのMD5チェエクリストを作る

以上で大体DVDを作成する準備が出来た。最後に(live_dvd_filesディレクトリの下にある)DVDに収められる各ファイルのMD5リストを作成しておく。このリストが“CDの異常をチェック”で使われる。(CDをチェックする気が無ければ、無くても構わない。)オリジナルCDでは、なぜかisolinuxのディレクトリだけはチェック対象から外れていたので、ここでもisolinuxのディレクトリは除外した。(ブートにライブCDではisolinux、ライブUSBではsyslinuxを使うのでこの部分が入れ替わることがあるのが原因らしい。)

################################################################################
echo "Making md5 check file"

touch "${DVD_FILES}/CUSTOM"

(
        cd "${DVD_FILES}"
        rm -f md5sum.txt
        find . -xdev -path ./isolinux -prune -o -type f -print0 \
                | xargs -0 md5sum \
                | sort -k 2 > ../md5sum.txt
        mv ../md5sum.txt .
)

ISOファイルを生成する

準備終わったのでISOファイルを生成する。genisoimageで。

################################################################################
echo "Generating custom DVD iso image"

genisoimage -quiet -J -R -D -V "CUSTOM_LIVE_DVD" \
	-o "${CUSTOM_DVD_ISO}" -b isolinux/isolinux.bin -c isolinux/boot.cat \
	-no-emul-boot -boot-load-size 4 -boot-info-table \
	"${CD_FILES}" 2> /dev/null

################################################################################

あとはDVDソフトなどでDVDに焼いて使えばいい。

*1: なお、casperパッケージにはcasper-snapshotというシェルスクリプト作られたsquashfsext2でファイルイメージを作成するプログラムがあるが、ファイルイメージの作成までしかやってくれないのと、イメージの元になる雛型ファイルシステムに関してもほとんど何もやっていないので、はcasper-snapshotは使っていない。

mkudvdプログラムリスト

  • 2009/02/10 Ver 0.06
  • 2009/02/13 Ver 0.07
    • オリジナルCDからのファイルのコピーを最適化し、作業時間を短縮する。
#! /bin/bash

# Custom Ubuntu Live DVD maker
# mkudvd Ver 0.07 (2009/02/13)
# Copyright (C) 2009 Adsaria

# This program is free software; you can redistribute it and/or modify it.
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY.

DEBUG=

if [ ${DEBUG} ]; then set -x; fi

################################################################################
# Parameter Settings

WORKING_DIR=/livedvd
ORIGINAL_CD_ISO="${WORKING_DIR}/ubuntu-8.04.2-desktop-i386.iso"
EXTENSION=custom

CUSTOM_DVD_ISO="${WORKING_DIR}/"`basename "${ORIGINAL_CD_ISO}" .iso`-${EXTENSION}.iso
TEMPLATE_ROOT="${WORKING_DIR}/filesystem"
MISC_FILES="${WORKING_DIR}/misc"
DVD_FILES="${WORKING_DIR}/live_dvd_files"
FS_TYPE=squashfs
# FS_TYPE=ext2
REMOVE_999_ACCOUNT=1

################################################################################
# Check base files

if [ ! -e "${TEMPLATE_ROOT}/vmlinuz" ]; then
	echo "Template root file system is not found."
	exit 1
fi

if [ ! -f "${ORIGINAL_CD_ISO}" ]; then
	echo "Ubuntu original CD iso file is not found."
	exit 1
fi

################################################################################
# Check utilities

if [ ! -x /usr/bin/mksquashfs ]; then
	echo "It seems package \"squashfs-tools\" have not been installed."
	exit 1
fi
if [ ! -x /usr/bin/genisoimage ]; then
	echo "It seems package \"genisoimage\" have not been installed."
	exit 1
fi

################################################################################
echo "Copying original CD files"

if [ ! -d "${DVD_FILES}" ]; then
	rm -rf "${DVD_FILES}"
	mkdir -p "${DVD_FILES}"
fi

rm -rf "${WORKING_DIR}/mnt"; mkdir "${WORKING_DIR}/mnt"
mount -t iso9660 -o loop,ro "${ORIGINAL_CD_ISO}" "${WORKING_DIR}/mnt"

rsync -ax --delete --exclude='filesystem.squashfs' \
	"${WORKING_DIR}/mnt/" "${DVD_FILES}/"

umount "${WORKING_DIR}/mnt"; rm -rf "${WORKING_DIR}/mnt"

################################################################################
echo "Modifying boot menu parameter"

sed -i \
	-e 's/^timeout .*$/timeout 50/' \
	"${DVD_FILES}/isolinux/isolinux.cfg"

################################################################################
echo "Triming base filesystem"

### Changing root password character

sed -i -e 's/^root:!:/root:*:/' "${TEMPLATE_ROOT}/etc/shadow"

### Removing trouble-making files

if [ -e "${TEMPLATE_ROOT}/etc/blkid.tab" ]; then
	rm -rf "${TEMPLATE_ROOT}/etc/blkid.tab"*
fi

if [ -e "${TEMPLATE_ROOT}/etc/resolv.conf" ]; then
	rm -rf "${TEMPLATE_ROOT}/etc/resolv.conf"
fi

echo "# UNCONFIGURED FSTAB FOR BASE SYSTEM" \
	> "${TEMPLATE_ROOT}/etc/fstab"

rm -rf "${TEMPLATE_ROOT}/etc/nologin"
ln -s "/var/lib/initscripts/nologin" "${TEMPLATE_ROOT}/etc/nologin"

rm -rf "${TEMPLATE_ROOT}/etc/mtab"

### Removing garbage files

rm -rf "${TEMPLATE_ROOT}/tmp/".[^.]*
rm -rf "${TEMPLATE_ROOT}/tmp/".??*
rm -rf "${TEMPLATE_ROOT}/tmp/"*

rm -rf "${TEMPLATE_ROOT}/var/log/Xorg.0.log"
rm -rf "${TEMPLATE_ROOT}/var/log/gdm/:0.log"
rm -rf "${TEMPLATE_ROOT}/var/log/tomcat6/"*
if [ ${DEBUG} ]; then FIND_OPT="-print" ; fi
find "${TEMPLATE_ROOT}/var/log/" -type f -name \*.gz ${FIND_OPT} -exec rm -f '{}' \;
find "${TEMPLATE_ROOT}/var/log/" -type f -name \*.\[0-9\] ${FIND_OPT} -exec rm -f '{}' \;
find "${TEMPLATE_ROOT}/var/log/" -type f -name \*old ${FIND_OPT} -exec rm -f '{}' \;
find "${TEMPLATE_ROOT}/var/log/" -type f ${FIND_OPT} -exec cp -f /dev/null '{}' \;

REMOVE_LIST=" \
        .bash_history \
        .cache \
        .esd_auth \
        .fontconfig \
        .gtk-bookmarks \
        .gvfs \
        .ICEauthority \
        .local \
        .nautilus \
        .pulse \
        .pulse-cookie \
        .recently-used.xbel \
        .ssh \
        .sudo_as_admin_successful \
        .update-notifier \
        .Xauthority \
        .xsession-errors \
        "

if [ -d "${TEMPLATE_ROOT}/root" ]; then
	echo "Cleaning root directory up...."
	( cd "${TEMPLATE_ROOT}/root"; rm -rf ${REMOVE_LIST} )
fi

if [ -d "${TEMPLATE_ROOT}/home/ubuntu" ]; then
	(
	echo "Cleaning ubuntu directory up...."
	cd "${TEMPLATE_ROOT}/home/ubuntu"
	rm -rf ${REMOVE_LIST}
	if [ ! -f "${MISC_FILES}/ubuntu_home.cpio.gz" ]; then
		echo "Backing ubuntu home up...."
		touch .mark ; chown `stat -c "%u:%g" .` .mark
		find . | cpio -o -H newc --quiet | gzip > "${MISC_FILES}/ubuntu_home.cpio.gz"
	fi
	)

fi

###
# remove pre-configured user account, ubuntu

if [ ${REMOVE_999_ACCOUNT} ]; then
	echo "Removing ubuntu account and home...."
	(chroot "${TEMPLATE_ROOT}" userdel -f -r ubuntu ) &> /dev/null
	rm -rf "${TEMPLATE_ROOT}/home/ubuntu/"
	(chroot "${TEMPLATE_ROOT}" groupdel ubuntu ) &> /dev/null
	if [ -f "${TEMPLATE_ROOT}/etc/gdm/gdm.conf" ]; then
		sed -i \
			-e "s/^AutomaticLoginEnable=.*\$/AutomaticLoginEnable=false/" \
			-e "s/^AutomaticLogin=.*\$/AutomaticLogin=/" \
			-e "s/^TimedLoginEnable=.*\$/TimedLoginEnable=false/" \
			-e "s/^TimedLogin=.*\$/TimedLogin=/" \
			-e "s/^TimedLoginDelay=.*\$/TimedLoginDelay=/" \
			"${TEMPLATE_ROOT}/etc/gdm/gdm.conf"
	fi
fi

################################################################################
# Triming casper for maitainance works

if [ -f "${TEMPLATE_ROOT}/etc/init.d/casper" ]; then
	echo "Modifying /etc/init.d/casper ...."
	sed -i \
		-e 's/TIMEOUT 86400/TIMEOUT 5/' \
		-e '/^[ ]*read x /s/^ /#/' \
		"${TEMPLATE_ROOT}/etc/init.d/casper"
fi

################################################################################
echo "Modifying initrd and copy initrd and kernel"

INITRD_ROOT="${WORKING_DIR}/initrd"

rm -rf "${WORKING_DIR}/initrd.img"
rm -rf "${INITRD_ROOT}"; mkdir "${INITRD_ROOT}"
(
	cd "${INITRD_ROOT}"
	gzip -dc "${TEMPLATE_ROOT}/initrd.img" | cpio -i --quiet

	# Casper can not handle lvm device properly, then modify casper script
	# But modifying just initrd script, not usr/share/initramfs-tools/scripts/casper
	sed -i -e 's/(loop|ram|fd)/(loop|ram|fd|dm-)/' \
		"${INITRD_ROOT}/scripts/casper"

	# Change ubuntu default password to "ubuntu", from "\n"
	sed -i -e 's/U6aMy0wojraho/kBzYzm5JjWKPA/' \
		"${INITRD_ROOT}/scripts/casper-bottom/10adduser"

	# Replace set_hostname script
	if [ -f "${MISC_FILES}/18hostname" ]; then
		cp -f "${MISC_FILES}/18hostname" \
			"${INITRD_ROOT}/scripts/casper-bottom/"
	fi

	# Copy add_ubuntu_home_directory script
	if [ -f "${MISC_FILES}/11adduserhome" ]; then
		cp "${MISC_FILES}/11adduserhome" \
			"${INITRD_ROOT}/scripts/casper-bottom/"
	fi

	# Copy server setup scripts
	cp -f "${MISC_FILES}/"6[0-9]* "${INITRD_ROOT}/scripts/casper-bottom/"

	# Copy ubuntu home directory archive, if exist
	if [ -f "${MISC_FILES}/ubuntu_home.cpio.gz" ]; then
		mkdir -p "${INITRD_ROOT}/var/backups"
		cp -f "${MISC_FILES}/ubuntu_home.cpio.gz" \
			"${INITRD_ROOT}/var/backups/"
	fi

	find . | cpio -o --quiet -H newc | gzip > "${WORKING_DIR}/initrd.img"
)
cp -f "${WORKING_DIR}/initrd.img" "${DVD_FILES}/casper/initrd.gz"

rm -rf "${WORKING_DIR}/initrd.img"
rm -rf "${INITRD_ROOT}"

cp -f "${TEMPLATE_ROOT}/vmlinuz" "${DVD_FILES}/casper/vmlinuz"

################################################################################
echo "Creating filesystem image"

SQUASH_FILE="${DVD_FILES}/casper/filesystem.squashfs"
EXT2_FILE="${DVD_FILES}/casper/filesystem.ext2"
rm -rf "${SQUASH_FILE}" "${EXT2_FILE}"

case "${FS_TYPE}" in
squashfs|squash)
	FS_FILE="${SQUASH_FILE}"
	mksquashfs "${TEMPLATE_ROOT}" "${SQUASH_FILE}"
	;;
ext2|ext)
	FS_FILE="${EXT2_FILE}"
	FS_SIZE=`du -s "${TEMPLATE_ROOT}/" | awk '{print $1}'`
	FS_SIZE=`expr "${FS_SIZE}" + "${FS_SIZE}" / 20`
	dd if=/dev/zero of="${EXT2_FILE}" bs="${FS_SIZE}" count=1024 2>/dev/null
	mkfs -F -q -t ext2 "${EXT2_FILE}"
	rm -rf mnt ; mkdir mnt
	mount -o loop "${EXT2_FILE}" mnt
	rsync -ax "${TEMPLATE_ROOT}/" mnt/
	umount mnt
	rm -rf mnt
	;;
*)
	echo "Filesystem Type is incorrect."
	echo "exit."
	exit 1
	;;
esac
chmod 444 "${FS_FILE}"

MANIFEST_1="${DVD_FILES}/casper/filesystem.manifest"
MANIFEST_2="${DVD_FILES}/casper/filesystem.manifest-desktop"

ORIGINAL_DIFFS=` \
	diff "${MANIFEST_1}" "${MANIFEST_2}" | \
	sed -e '/^[^<]/d' -e 's/^< //' -e 's/ .*//' \
	`
rm -rf "${MANIFEST_1}"
rm -rf "${MANIFEST_2}"

dpkg-query -W --showformat='${Package} ${Version}\n' \
         --admindir="${TEMPLATE_ROOT}/var/lib/dpkg/" \
        > "${MANIFEST_1}"

cp -f "${MANIFEST_1}" "${MANIFEST_2}"
for REMOVE_PKG in ${ORIGINAL_DIFFS}; do
	sed -i -e "/^${REMOVE_PKG} /d" "${MANIFEST_2}"
done

chmod 444 "${MANIFEST_1}"
chmod 444 "${MANIFEST_2}"

################################################################################
echo "Making md5 check file"

touch "${DVD_FILES}/CUSTOM"

(
	cd "${DVD_FILES}"
	rm -f md5sum.txt
	find . -xdev -path ./isolinux -prune -o -type f -print0 \
		| xargs -0 md5sum \
		| sort -k 2 > ../md5sum.txt
	mv ../md5sum.txt .
)

################################################################################
echo "Generating custom DVD iso image"

rm -f "${CUSTOM_DVD_ISO}"
genisoimage -quiet -J -R -D -V "CUSTOM_LIVE_DVD" \
	-o "${CUSTOM_DVD_ISO}" -b isolinux/isolinux.bin -c isolinux/boot.cat \
	-no-emul-boot -boot-load-size 4 -boot-info-table \
	"${DVD_FILES}" 2> /dev/null

################################################################################
echo "Done."

exit 0
#!/bin/sh

PREREQ=""
DESCRIPTION="Adding live session user home directory..."

. /scripts/casper-functions

prereqs()
{
       echo "$PREREQ"
}

case $1 in
# get pre-requisites
prereqs)
       prereqs
       exit 0
       ;;
esac

log_begin_msg "$DESCRIPTION"

if [ -f /var/backups/ubuntu_home.cpio.gz ]; then
    if [ -d /root/home/ubuntu ]; then
	(
	    cd /root/home/ubuntu
	    rm -rf .home_template ; mkdir .home_template
	    cd .home_template
	    gzip -dc /var/backups/ubuntu_home.cpio.gz | cpio -i
	    cp -a ..?* .[^.]* * ..
	    cd ..
	    rm -rf .home_template
	)
    fi
fi

log_end_msg

initrd管用のcpioが“-u”オプションを使えないので、少々回りくどい処理をしている。

  • 18hostname:DHCPサーバからホスト名等を取得し設定する。
#! /bin/sh

PREREQ=""
DESCRIPTION="Setting hostname..."

. /scripts/casper-functions

prereqs()
{
       echo "$PREREQ"
}

case $1 in
# get pre-requisites
prereqs)
       prereqs
       exit 0
       ;;
esac

log_begin_msg "$DESCRIPTION"

NETCONFIG=/netboot.config
ADDR=127.0.1.1
DOMAIN=

if [ -f $NETCONFIG ]; then

	NET_HOST=$(grep '^ host   :' $NETCONFIG | cut -f6 -d ' ' )
	if [ ! -z "$NET_HOST" ]; then HOST=$NET_HOST; fi
	export HOST

	NET_DOMN=$(grep '^ domain :' $NETCONFIG | cut -f4 -d ' ' )
	if [ ! -z "$NET_DOMN" ]; then DOMAIN=$NET_DOMN; fi

	NET_ADDR=$(grep '^ address:' $NETCONFIG | cut -f3 -d ' ' )
	if [ ! -z "$NET_ADDR" ]; then ADDR=$NET_ADDR; fi
fi

echo "$HOST" > /root/etc/hostname
cat > /root/etc/hosts <<EOF
127.0.0.1 localhost
$ADDR $HOST $HOST.$DOMAIN

# The following lines are desirable for IPv6 capable hosts
::1     ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
ff02::3 ip6-allhosts

EOF
hostname "$HOST"

log_end_msg
  • 60setupnfs:/etc/exportsに変更を加え/tmpをネットワークからマウントできるようにしている。
#!/bin/sh

PREREQ=""
DESCRIPTION="Setting up NFS configuration..."

. /scripts/casper-functions

prereqs()
{
       echo "$PREREQ"
}

case $1 in
# get pre-requisites
prereqs)
       prereqs
       exit 0
       ;;
esac

log_begin_msg "$DESCRIPTION"

if [ -f /root/etc/exports ]; then
        echo '/tmp      *(rw,all_squash,no_subtree_check,fsid=0)' >> /root/etc/exports
fi

log_end_msg
  • 61setupsmb:/etc/samba/smb.confに変更を加えて/tmpを共有できる様にしている。
#!/bin/sh
PREREQ=""
DESCRIPTION="Setting up Samba configuration..."

. /scripts/casper-functions

prereqs()
{
       echo "$PREREQ"
}

case $1 in
# get pre-requisites
prereqs)
       prereqs
       exit 0
       ;;
esac

log_begin_msg "$DESCRIPTION"

if [ -f /root/etc/samba/smb.conf ]; then
        cat >> /root/etc/samba/smb.conf << EOF
[tmp]
        comment = /tmp
        path = /tmp
        browseable = no
        writable = yes
        guest ok = yes
EOF
fi

log_end_msg
  • 62setupntp:/etc/ntp.confを変更する。
#!/bin/sh

PREREQ=""
DESCRIPTION="Setting up NTP configuration..."

. /scripts/casper-functions

prereqs()
{
       echo "$PREREQ"
}

case $1 in
# get pre-requisites
prereqs)
       prereqs
       exit 0
       ;;
esac

log_begin_msg "$DESCRIPTION"

if [ -f /root/etc/ntp.conf ]; then
        sed -i -e 's/^server ntp.ubuntu.com/#server ntp.ubuntu.com\
server  255.255.255.255\
server  255.255.255.255/' /root/etc/ntp.conf

fi

log_end_msg

プログラム中の“255.255.255.255”の部分は自分が使っているプロバイダのNTPサーバ、もしくは国内の公共NTPサーバのIPアドレスにする。ただ、このスクリプトは特に必要ないかも。/etc/ntp.confに変更を加えなくても“ntp.ubuntu.com”というNTPサーバを使うような設定になっている。

  • 63setupbind:/etc/bind/named.conf.optionsに変更を加えてBINDをフォワーダーとして起動する。
#!/bin/sh

PREREQ=""
DESCRIPTION="Setting up BIND configuration..."

. /scripts/casper-functions

prereqs()
{
       echo "$PREREQ"
}

case $1 in
# get pre-requisites
prereqs)
       prereqs
       exit 0
       ;;
esac

log_begin_msg "$DESCRIPTION"

if [ -f /root/etc/bind/named.conf.options ]; then
        sed -i \
                -e '/^[\t ]*\/\/[\t ]*0\.0\.0\.0;/,/^[\t ]*\/\/[\t ]*};/d' \
                -e 's/^[\t ]*\/\/ forwarders {/ forwarders { 255.255.255.255; };/' \
                /root/etc/bind/named.conf.options
fi

log_end_msg

プログラム中の“255.255.255.255”の部分は自分が利用しいるプロバイダのDNSサーバのIPアドレスに変更する。詳しくは“最小限の設定でDNSを使う”を参照。

本当はUSBメモリを使いたかったのだけど

実は最初、USBメモリブートするISO Linuxを作ろうと思っていた。しかし、私のマシンのBIOSUSBメモリは“リムーバブルメディア”ではなく“HDD”として認識してしまう。従ってUSBを挿してもBIOSを設定し直さないとUSBメモリからブートしない。仕方なく、セットして電源を入れればそちらからブートするCD/DVDにした。おかげでCasperとか面白いシステムの勉強になった。

上の方法を応用してカスタムライブUSBも作成した。“UbuntuでカスタムライブUSBを作る”参照。