【zz】debian基本系统构建(build Linux system from scratch based on deb packages)


my

1.mkdir -p /opt/root_filesystem/var/cache/apt/archive/partial

2.从/var/lib/dpkg/status文件中获取essential,required,important软件包列表

3.将所有软件包以及它们所依赖包拷贝到/opt/root_filesystem/var/cache/apt/archive/

4.将所有essential,required包用 dpkg -x pkg.deb /opt/root_filesystem/ 解压

5.root@jfo-laptop:/# chroot /opt/root_filesystem/ /bin/bash 
root@jfo-laptop:/# export LC_ALL=C
root@jfo-laptop:/# touch /var/lib/dpkg/{status,available,diversions}

6.开始用dpkg安装essential,required包 
对所有essential,required包运行 dpkg –force-depends –unpack pkg.deb 
–force-depends 告诉 dpkg 忽略依赖关系 
 root@jfo-laptop:/# dpkg –configure -a –force-configure-any –force-depends 
 –force-depends 在这里可以解决包相互依赖的问题,例如 debconf与debconf-i18n 就相互依赖,用 dpkg单独对其中任何一个进行–configure都会失败,因此需要加上–force-depends  
-a 或 –pending 表示重新配置所有 
–force-configure-any : Configure also any unpacked but unconfigured packages on which the current package depends. 

7.安装配置apt
 root@jfo-laptop:/# dpkg -i apt.deb 
为方便后继安装,可以将ubunut DVD光盘作为源
 root@jfo-laptop:/# mount -o loop ubuntu-8.04.1-dvd-i386.iso /mnt/ 
 root@jfo-laptop:/# echo "deb file:/mnt/ hardy main restricted" > /etc/apt/sources.list 
下面一步解决cdrom作为源时的authentication warning问题 
 root@jfo-laptop:/# echo ‘APT::Authentication::TrustCDROM "true";’ > /etc/apt/apt.conf.d/00trustcdrom  
 root@jfo-laptop:/# apt-get update 
 root@jfo-laptop:/# apt-key update 

8.用apt-get安装important包,自动解决依赖关系 
 root@jfo-laptop:/# apt-get -y install pkg 
安装ubuntu最小化环境:
root@jfo-laptop:/# apt-get -y install ubuntu-minimal ubuntu-standard ubuntu-restricted-extras  

9.安装xorg、gdm或kde,以及其他软件包;或者安装ubuntu-desktop,桌面相关包全部自动安装
 root@jfo-laptop:/# apt-get -y install language-pack-{en,zh} 
 root@jfo-laptop:/# apt-get -y install xorg gdm gnome-session gnome-terminal gnome-panel ubuntu-gdm-themes metacity 
metacity是gnome的默认窗口管理器,不装这个窗口显示没有标题栏,并且窗口位于桌面左上角,遮住系统菜单

10.退出chroot,配置系统文件  
 root@jfo-laptop:/# touch /opt/root_filesystem/etc/{fstab,mtab} 
 root@jfo-laptop:/# cp /etc/hostname /opt/root_filesystem/etc/ 
 root@jfo-laptop:/# cp /etc/hosts /opt/root_filesystem/etc/ 

这样,一个根文件系统就制作完成了,消耗磁盘空间600M多!

my



http://comcat.blog.openrays.org/blog-htm-do-showone-tid-214.html

0. 缘起

基本系统,是一个最小化的debian系统,可以在其上使用debian的apt-get 机制,进一
步的安装你所需要的软件包。多用于开发测试用,比如在现有系统下交叉编译一个64位
的系统为了不影响当前系统的环境,可以在某个工作目录下安装一个基本系统,然后在
这个子系统里构建交叉编译环境。

安装程序也用到。在将目标磁盘分区完后,安装程序会将要安装整个系统的分区挂载在
某个目录下然后调用debootstrap 脚本在该目录下安装一个基本系统,完了进入这个基
本系统,使用 apt-get 进一步的安装 X-Windows、Gnome、KDE 等。



1. deb 包格式

deb 包实际上是一个二进制归档文件(使用 ar 创建),一般包含3个文件:
debian-binary, control.tar.gz, data.tar.gz


其中:

debian-binary 是deb包格式的版本号,我的系统里 $cat debian-binary 显示 2.0

control.tar.gz 包含deb包的控制信息和一些辅助脚本

如一个典型的control.tar.gz 解开为:

control.tar.gz
|
|--- control 控制信息文件,就是源码目录中的debian/control<br />|--- md5sum 软件包中所有文件的 md5 值,文本文件<br />|--- conffiles 软件包的配置文件列表,在升级包的过程中不会被覆盖(可有可无)<br />|--- preinst 辅助脚本,在包解压前执行 (可有可无)<br />|--- postinst 辅助脚本,在包解压后执行 (可有可无)<br />|--- prerm 辅助脚本,在包删除之前执行 (可有可无)<br />— postrm 辅助脚本,在包删除之后执行 (可有可无)


data.tar.gz 即是真实的安装数据所在,一个真实的data.tar.gz解开后的目录树为:

data.tar.gz
|
|– etc
| -- rarfiles.lst<br />– usr
|– bin
| -- rar<br />|-- lib<br />|– default.sfx
-- share<br />|-- doc<br />|– rar
| |– changelog.Debian.gz
| |– copyright
| |– order.htm
| |– rar.txt.gz
| |– rar_faq.txt.gz
| |– readme.txt
| |– technote.txt.gz
| -- whatsnew.txt<br />|-- lintian<br />|– overrides
| -- rar<br />– man
-- man1<br />– rar.1.gz


可以通过如下命令解包: ar x rar_3.20-2_i386.deb

以下命令查看包的内容: ar t rar_3.20-2_mipsel.deb


明白了这一层,我们就可以自己提供 debian-binary,control.tar.gz,data.tar.gz
随心所欲地制作deb 包 ^-^


如下命令制作deb包: ar r rar.deb debian-binary control.tar.gz data.tar.gz

dpkg -c rar.deb 就会显示包的内容了, 注意 debian-binary 要放在第一位,

否则 dpkg 会报: 文件“rar.deb”不是 debian 的二进制包文件


亦可直接解包获取我们所需的数据文件,绕开 dpkg 的控制,如:

ar -p ./rar.deb data.tar.gz | zcat | tar -xf -




2. 基本系统软件包的下载

debian 对核心的基本系统包进行了分类,一类用Essential: yes; Priority: required 标识,
一类用Priority: important 标识。 加上一些额外常用的包,可以形成两个列表:

required = "base-files base-passwd bash bsdutils coreutils libacl1 libattr1 debianutils diff dpkg dselect libblkid1 e2fsprogs e2fslibs libcomerr2 libss2 libuuid1 findutils grep gzip hostname libcap1 libdb1-compat libdb3 libncurses5 libnewt0.51 libpam-modules libpam-runtime libpam0g login makedev mawk mount ncurses-base ncurses-bin passwd perl-base procps sed slang1a-utf8 initscripts sysvinit sysv-rc tar util-linux libgcc1 gcc-3.3-base libstdc++5 zlib1g libc6"

base = "adduser apt apt-utils libdb4.2 base-config aptitude libsigc++-1.2-5c102 bsdmainutils console-common console-tools libconsole console-data cpio cron dhcp-client ed libgnutls11 libgcrypt11 libgpg-error0 libncursesw5 libopencdk8 libtasn1-2 fdutils gettext-base groff-base ifupdown info klogd libssl0.9.7 liblzo1 liblockfile1 libpcre3 libwrap0 logrotate man-db libgdbm3 manpages nano net-tools netbase netkit-inetd iputils-ping nvi ppp pppconfig pppoe pppoeconf libpcap0.7 sysklogd tasksel libtextwrap1 tcpd telnet wget libpopt0 modutils whiptail "

有了基本软件包的列表,就可以使用 apt 的机制来下载这些包到指定的目录。

假定我们的工作目录在$TARGET_DIR,下面建立工作目录:

mkdir -p "$TARGET_DIR/var/lib/dpkg"
mkdir -p "$TARGET_DIR/var/lib/apt/lists/partial"
mkdir -p "$TARGET_DIR/var/cache/apt/archives/partial"
: >"$TARGET_DIR/var/cache/apt/archives/lock"
: >"$TARGET_DIR/var/lib/dpkg/status"
: >"$TARGET_DIR/var/lib/dpkg/status"
: >"$TARGET_DIR/var/lib/dpkg/lock"
: >"$TARGET_DIR/var/lib/dpkg/available"
: >"$TARGET_DIR/var/lib/apt/lists/lock"
mkdir -p "$TARGET_DIR/etc/apt"
cp /etc/apt/sources.list $TARGET_DIR/etc/apt/


下面解析包依赖关系,使用 apt-get -d install 下载之:

all_debs="$required $base"

options=" -q
-o Dir::State::status=$TARGET_DIR/var/lib/dpkg/status
-o Dir::State=$TARGET_DIR/var/lib/apt
-o Dir::Cache=$TARGET_DIR/var/cache/apt
-o Dir::Etc=$TARGET_DIR/etc/apt
-o APT::Cache::AllVersions=0 "

# 更新源索引于 $TARGET_DIR/var/lib/apt/list/ 下
apt-get $options update -f>/dev/null 2>&1

# 解析依赖关系,并扩展所有基本系统软件包列表
apt-get install -s $all_debs $options
expand_list=$(apt-get install -s $all_debs $options | awk ‘{if ($0 ~ /^Inst/) print $2}’)

# 下载软件包于 $TARGET_DIR/var/cache/apt/archives/ 下
for f in $expand_list;do
apt-get install -d -y –force-yes $f $options
done

有关这里所用的 apt-get 的高级选项,参见我的另一篇 blog 文章:《深入 APT 系统》

注意: 传给apt-get 的options,其中的 $TARGET_DIR 必须为绝对路径。



3. 强制解压核心包

核心包即上面 required 列表所示的包,由于目标目录目前仅有一些 dpkg 所必须的工作目录及刚
下载的基本系统软件包,并无一些基本程序、基本文件的实体,这些通过强制解压所有核心包于目
标目录来是实现:

ar -p ./$pkg_full_path data.tar.gz | zcat | tar -xf -


然后向 dpkg 的控制信息文件写入 dpkg 自己的控制信息:


# 获取 dpkg 的版本号
ver="$(
ar -p "$TARGETDIR/var/cache/apt/archives/dpkg
.deb" control.tar.gz | zcat |
tar -O -xf - control ./control 2>/dev/null |
sed -ne ‘s/^Version: //Ip’ | head -n 1
)"

mkdir -p "$TARGET_DIR/var/lib/dpkg/info"

echo
"Package: dpkg
Version: $ver
Status: install ok installed" >> "$TARGET_DIR/var/lib/dpkg/status"

touch "$TARGET_DIR/var/lib/dpkg/info/${pkg}.list"


告诉 dpkg 自己已经安装了 ^-^



4. 使用dpkg 安装基本系统软件包

要保证我们的基本系统能使用apt-get 安装后序的开发包,则所有的基本系统包还是要纳入
dpkg 的管理机制的。故而所有包都要重新用 dpkg 安装。


经第3步强制解压后,目标目录已经有了最基本的文件,可以chroot 过去,使用dpkg 依序安装了:

ln -s mawk $TARGET_DIR/usr/bin/awk

pkg_path=var/cache/apt/archives # 所有基本系统deb包所在目录

chroot $TARGET_DIR # 将当前进程的根目录设为目标目录

dpkg –force-depends –install $pkgpath/base-files
.deb
dpkg –force-depends –install $pkgpath/base-passwd.deb
dpkg –force-depends –install $pkgpath/dpkg
.deb

if [ ! -e "$TARGET_DIR/etc/localtime" ]; then
ln -sf /usr/share/zoneinfo/UTC "$TARGET_DIR/etc/localtime" # 设置子系统时区
fi

dpkg –force-depends –install $pkgpath/libc6.deb
dpkg –force-depends –install $pkgpath/perl-base
.deb

rm $TARGET_DIR/usr/bin/awk

dpkg –force-depends –install $pkgpath/mawk.deb
dpkg –force-depends –install $pkgpath/debconf
.deb


收拾了最基本的,就可以批量处理了,使用如下命令安装 required 列表的所有软件包:

dpkg –force-depends –unpack $pkgpath/pkgname.deb

–force-depends 告诉 dpkg 忽略依赖关系
–unpack: 解压软件包,但不配置之。 –install 的话包括 –unpack 和 –configure


# 设置 dselect 使用 apt
echo "apt apt" > "$TARGET_DIR/var/lib/dpkg/cmethopt"
chmod 644 "$TARGET_DIR/var/lib/dpkg/cmethopt"

# 配置刚刚忽略依赖关系 unpack 的所有软件包
dpkg –configure –pending –force-configure-any –force-depends

–configure: 重新配置一个 unpack 的软件包,加 -a 或 –pending 则重新配置所有
–force-configure-any: Configure also any unpacked but unconfigured packages on which the current package depends.


搞定了 required 列表的,现在来收拾 base 列表的软件包:

dpkg –force-auto-select –force-overwrite –force-confold –skip-same-version
–unpack $pkgpath/pkgname
.deb

–force-overwrite:如有新的文件,则用新的
–force-confold:若原有配置文件被修改,则保留之。
–skip-same-version: 如果已经安装了相同版本号的包,就不再安装


# 配置刚刚忽略依赖关系 unpack 的所有软件包,-a 等价于 –pending
dpkg –force-confold –skip-same-version –configure -a



至此基本系统就安装在目标目录了,chroot $TARGET_DIR 就可以这个子系统里想干嘛就干嘛了 ^-^










end