免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 994 | 回复: 0
打印 上一主题 下一主题

OpenBSD LiveCD制作过程 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2006-01-18 20:01 |只看该作者 |倒序浏览
作者:OpenBSD LiveCD制作过程
2005-3-31更新
OpenBSD LiveCD制作过程
   刚开始接触OpenBSD时,我就很想使用OpenBSD LiveCD,但没找到。今年1月那时起就想自己做一个LiveCD,一个新年一过, 就将它放下了,现在又重新开始制作,今天写这篇文章只是我思路的一个开始,制作的LiveCD,还不完善,我会后续为其改进。
   制作过程:
一、 准备工作:
1、 一个能运行OpenBSD系统的所需要的必备文件,这里我就没像一些mini LiveCD那样对系统进行剔牛肉进行精减了,只是将一个能运行的系统的所有文件进行备份。而且如果备份的文件不大, 那制作出的LiveCD就很小, 我们就可以将这个备份的系统文件也一起放进CD中, 到时就可以用这个LiveCD安装系统,方法就是我今年1月3日写的《OpenBSD  另类安装法》。
2、 OpenBSD系统的源程序,我们在制作过程中需要编译光盘镜像。
二、 将备份的系统文件解开到一个目录下,我将以这个目录作为LiveCD的根目录制作CD,如/usr/live/。
三、 将OpenBSD源程序解开到/usr/src下,然后:
1、 安装必须的程序:
# cd /usr/src/distrib/crunch/crunchgen
#make; make install
#cd /usr/src/distrib/crunch/crunchide
#make; make install
2、 定制内核
内核文件是/usr/src/sys/arch/i386/conf/RAMDISK_CD,我们需要对这个文件进行修改,其中有三行最重要,一定不能少:
option  MFS
option  UNION
config  bsd root on cd0a
LiveCD运行于MFS上,而且它的根目录在CD上。
还有其它一些选项如:
option SMALL_KERNEL
option NO_PROPLICE
option TIMEZONE=0
option DST=0
option RAMDISK_HOOKS
option MINIROOTSIZE=3560
需要将一些多余的东西删除,因此这个内核大小控制在2.88M以内, 太大时会编译失败。我的RAMDISK_CD是将/usr/src/sys/arch/i386/conf/GENERIC 和/usr/src/sys/conf/GENERIC这两个文章合并然后去掉一些内容整理出来的。
3、 编译内核
# cd /usr/src/distrib/i386/ramdisk_cd
#make
成功后会在目录下生成cdrom36.fs这个文件,我们将这个文件复制到制作LiveCD的目录下/usr/live/。
四、 修改/usr/live/etc中的各类文件
1、fstab
代码:
/dev/cd0a / cd9660 ro,noatime 0 0
swap   /dev   mfs   rw,noatime,union,-s=16384   0 0
swap   /tmp   mfs   rw,nodev,noexec,nosuid,noatime,-s=32768   0 0
swap   /etc   mfs   rw,noatime,-s=16384   0 0
swap   /var   mfs   rw,noatime,-s=16384   0 0
swap   /home mfs   rw,noatime,-s=16384   0 0
以前我没发现fstab的功能居然如此强大, 以为它只能mount已分好的挂载点, 原来它在光盘系统中还可以在启动时自动挂载写入fstab中的mfs.
2、rc
  OpenBSD启动时首先读取这个文件, 如果找不到它就会读取根目录下的/.profile文件进行初始配置。
  修改/etc/rc文件, 三个地方修改
代码:
   
#   $OpenBSD: rc,v 1.251 2004/08/21 08:17:28 hshoexer Exp $
# System startup script run by init on autoboot
# or after single-user.
# Output and error are redirected to console by init,
# and the console is the controlling terminal.
# Subroutines (have to come first).
# Strip comments (and leading/trailing whitespace if IFS is set)
# from a file and spew to stdout
stripcom() {
   local _file="$1"
   local _line
   {
      while read _line ; do
         _line=${_line%%#*}      # strip comments
         test -z "$_line" && continue
         echo $_line
      done
   } /dev/null 2>&1
   chmod 600 /var/db/host.random >/dev/null 2>&1
   if [ $? -eq 0 -a -f /etc/rc.shutdown ]; then
      echo /etc/rc.shutdown in progress...
      . /etc/rc.shutdown
      echo /etc/rc.shutdown complete.
      # bring carp interfaces down gracefully
      for hn in /etc/hostname.carp[0-9]*; do
         # Strip off /etc/hostname. prefix
         if=${hn#/etc/hostname.}
         test "$if" = "carp[0-9]*" && continue
         ifconfig $if > /dev/null 2>&1
         if [ "$?" != "0" ]; then
            ifconfig $if down
         fi
      done
      if [ "X${powerdown}" = X"YES" ]; then
         exit 2
      fi
   else
      echo single user: not running /etc/rc.shutdown
   fi
   exit 0
fi
# Configure ccd devices.
if [ -f /etc/ccd.conf ]; then
   ccdconfig -C
fi
# Configure raid devices.
for dev in 0 1 2 3; do
   if [ -f /etc/raid$dev.conf ]; then
      raidctl -c /etc/raid$dev.conf raid$dev
   fi
done
# Check parity on raid devices.
raidctl -P all
swapctl -A -t blk
if [ -e /fastboot ]; then
   echo "Fast boot: skipping disk checks."
elif [ $1x = autobootx ]; then
   echo "Automatic boot in progress: starting file system checks."
#   fsck –p      这一行要注释掉
   case $? in
   0)
      ;;
   2)
      exit 1
      ;;
   4)
      echo "Rebooting..."
      reboot
      echo "Reboot failed; help!"
      exit 1
      ;;
   8)
      echo "Automatic file system check failed; help!"
      exit 1
      ;;
   12)
      echo "Boot interrupted."
      exit 1
      ;;
   130)
      # interrupt before catcher installed
      exit 1
      ;;
   *)
      echo "Unknown error; help!"
      exit 1
      ;;
   esac
fi
trap "echo 'Boot interrupted.'; exit 1" 3
umount -a >/dev/null 2>&1
mount -a -t nonfs
mount -uw /      # root on nfs requires this, others aren't hurt
rm -f /fastboot      # XXX (root now writeable)
这里需要在/dev下建立三个设备点, 不然后一步tar出错, 系统启动时会问题多多
mknod /dev/stdout c 22 1
mknod /dev/stdin c 22 0
mknod /dev/stderr c 22 2
if [ -f /mfs/mfs.tgz ]; then
   tar zxpf /mfs/mfs.tgz -C /
   echo 'Fixed up mfs from /mfs/mfs.tgz'
fi
chmod 755 /dev /etc /var
chmod a+rwx,a+t /tmp
# set flags on ttys.  (do early, in case they use tty for SLIP in netstart)
echo 'setting tty flags'
ttyflags -a
if [ "X${pf}" != X"NO" ]; then
   RULES="block all"
   RULES="$RULES\npass on lo0"
   RULES="$RULES\npass in proto tcp from any to any port 22 keep state"
   RULES="$RULES\npass out proto { tcp, udp } from any to any port 53 keep state"
   RULES="$RULES\npass out inet proto icmp all icmp-type echoreq keep state"
   RULES="$RULES\npass out inet6 proto icmp6 all icmp6-type routersol"
   RULES="$RULES\npass in inet6 proto icmp6 all icmp6-type routeradv"
   RULES="$RULES\npass proto { pfsync, carp }"
   case `sysctl vfs.mounts.nfs 2>/dev/null` in
   *[1-9]*)
      # don't kill NFS
      RULES="scrub in all no-df\n$RULES"
      RULES="$RULES\npass in proto udp from any port { 111, 2049 } to any"
      RULES="$RULES\npass out proto udp from any to any port { 111, 2049 }"
      ;;
   esac
   echo $RULES | pfctl -f - -e
fi
if [ -f /etc/sysctl.conf ]; then
(
   # delete comments and blank lines
   set -- `stripcom /etc/sysctl.conf`
   while [ $# -ge 1 ] ; do
      sysctl $1
      shift
   done
)
fi
# set hostname, turn on network
echo "Setting Network......"     修改这里, 加入我写的setnetwork脚本,
. /etc/setnetwork                     这样网络设置在每台机上都可以重新设置而不是更改文件.
3、上一步最后有一个setnetwork脚本,这一步写出。我的脚本编写不会, 只好从其它地方抄过来,有一些错误,需要请高手改写。这个文件有点大, 贴在最后吧!
4、将一些网络配置的文件删除如:hosts, mygate等。上一步的network在启动时会生成这些配置文件。
五、 备份几个目录,在4.3 rc脚本中的MFS部分那个文件。
在/usr/live/ LiveCD根目录下建立文件夹:mfs 然后:
# tar cvzfp mfs/mfs.tgz dev etc home var
  
六、 制作ISO镜像:
# cd /usr/live
# mkhybrid –b cdrom36.fs –c boot.catalog –R –v –o /usr/OpenBSD-LiveCD.iso /usr/live
现在制作完成, 你可以用虚拟机测试这个生成的ISO镜像。
参考了网上许多文章, 这里就不一一列出来了, 感谢那些大哥写出那么好的教程.
我现在还有几个问题需要解决,主要是MFS这方面的,另外shell脚本的错误也需要大家来解决。
设置网络用的setnetwork脚本:
setnetwork:
代码:
#!/bin/sh
get_dkdevs() {
   bsort `sed -ne "${MDDISKDEVS:-/^[sw]d[0-9][0-9]* /s/ .*//p}" /var/run/dmesg.boot`
}
get_cddevs() {
   bsort `sed -ne "${MDCDDEVS:-/^cd[0-9][0-9]* /s/ .*//p}" /var/run/dmesg.boot`
}
get_ifdevs() {
   ifconfig -a \
       | egrep -v '^[[:space:]]|(bridge|enc|gif|gre|lo|pflog|pfsync|ppp|sl|tun|vlan)[[:digit:]]+:' \
       | sed -ne 's/^\(.*\):.*/\1/p'
}
askpass() {
   set -o noglob
   stty -echo
   read resp?"$1 "
   stty echo
   set +o noglob
   echo
}
ask() {
   local _question=$1 _default=$2
   set -o noglob
   while : ; do
      echo -n "$_question "
      [[ -z $_default ]] || echo -n "[$_default] "
      read resp
      case $resp in
      !)   echo "Type 'exit' to return to install."
         sh
         ;;
      !*)   eval ${resp#?}
         ;;
      *)   : ${resp:=$_default}
         break
         ;;
      esac
   done
   set +o noglob
}
ask_until() {
   resp=
   while [[ -z $resp ]] ; do
      ask "$1" "$2"
   done
}
ask_yn() {
   local _q=$1 _a=${2:-no} _resp
   typeset -l _resp
   while : ; do
      ask "$_q" "$_a"
      _resp=$resp
      case $_resp in
      y|yes)   resp=y ; return ;;
      n|no)   resp=n ; return ;;
      esac
   done
}
ask_which() {
   local _name=$1 _query=$2 _devs=$3 _defdev=$4 _err=$5
   set -- $_devs
   if [[ $# -lt 1 ]]; then
      echo "${_err:=No ${_name}s found}."
      resp=done
      return
   fi
   : ${_defdev:=$1}
   _devs="$*"
   while : ; do
      ask "Available ${_name}s are: ${_devs}.\nWhich one ${_query}? (or 'done')" "$_defdev"
      [[ $resp == done ]] && break
      if isin "$resp" $_devs; then
         makedev $resp && break
      else
         echo "'$resp' is not a valid choice."
      fi
   done
}
isin() {
   local   _a=$1 _b
   shift
   for _b; do
      [ "$_a" = "$_b" ] && return 0
   done
   return 1
}
addel() {
   local   _a=$1
   shift
   echo -n "$*"
   isin "$_a" $* || echo -n " $_a"
}
rmel() {
   local   _a=$1 _b
   shift
   for _b; do
      [ "$_a" != "$_b" ] && echo -n "$_b "
   done
}
edit_tmp_file() {
   local _file=$1
   ask_yn "Edit $_file with $EDITOR?"
   [[ $resp == y ]] && $EDITOR /tmp/$_file
}
manual_net_cfg() {
   ask_yn "Do you want to do any manual network configuration?"
   [[ $resp == y ]] && { echo "Type 'exit' to return to $MODE." ; sh ; }
}
makedev() {
   local _dev=$1 _node=/dev/r${1}c
   if isin $_dev $IFDEVS || [[ -c $_node || -z ${_dev##+([0-9])} ]] ; then
      return 0
   fi
   if [[ ! -r /dev/MAKEDEV ]] ; then
      echo "No /dev/MAKEDEV. Can't create device nodes for ${_dev}."
      return 1
   fi
   (cd /dev; sh MAKEDEV $_dev)
   [[ -c $_node ]] || return 1
   DEVSMADE=`addel $_dev $DEVSMADE`
}
addhostent() {
   sed "/ $2\$/d" /etc/hosts > /etc/hosts.new
   mv /etc/hosts.new /etc/hosts
   echo "$1 $2" >> /etc/hosts
}
configure_ifs() {
   local _IFDEVS=$IFDEVS _ifs _name _media _hn
   while : ; do
      ask_which "interface" "do you wish to initialize" "$_IFDEVS" \
         "" "No more interfaces to initialize"
      [[ $resp == done ]] && break
      _ifs=$resp
      _hn=/etc/hostname.$_ifs
      ask "Symbolic (host) name for $_ifs?" "$(hostname -s)"
      _name=$resp
      _media=$(ifconfig -m $_ifs | grep "media ")
      if [[ -n $_media ]]; then
         cat  /etc/dhclient.conf
   if [[ -n $_hostname ]]; then
      echo "send host-name \"$_hostname\";" >> /etc/dhclient.conf
      echo "Issuing hostname-associated DHCP request for $_ifs."
   else
      echo "Issuing free-roaming DHCP request for $_ifs."
   fi
   cat >> /etc/dhclient.conf > /etc/resolv.conf.tail  $_hn
      fi
      ;;
   *)   _addr=$resp
      ask_until "Netmask?" "${_mask:=255.255.255.0}"
      if ifconfig $_ifs inet $_addr netmask $resp up ; then
         addhostent "$_addr" "$_name"
         echo "inet $_addr $resp NONE $_media" > $_hn
      fi
      ;;
   esac
}
v4_defroute() {
   local _dr _prompt=" or 'none'"
   [[ -x /sbin/dhclient ]] && _prompt=", 'dhcp'$_prompt"
   _prompt="Default IPv4 route? (IPv4 address$_prompt)"
   _dr=$(route -n show -inet | sed -ne '/^default */{s///; s/ .*//; p;}')
   [[ -f /tmp/dhclient.conf ]] && _dr=dhcp
   while : ; do
      ask_until "$_prompt" "$_dr"
      case $resp in
      none|dhcp) break ;;
      esac
      route delete -inet default > /dev/null 2>&1
      route -n add -inet -host default "$resp" && { echo "$resp" >/etc/mygate ; break ; }
      route -n add -inet -host default $_dr >/dev/null 2>&1
   done
}
isalphanumeric() {
   local _n=$1
   while [[ ${#_n} -ne 0 ]]; do
      case $_n in
      [A-Za-z0-9]*)   ;;
      *)      return 1;;
      esac
      _n=${_n#?}
   done
   return 0
}
enable_network() {
   local _netfile
#   for _netfile in hosts dhclient.conf resolv.conf resolv.conf.tail protocols services; do
#      if [ -f /mnt/etc/${_netfile} ]; then
#         cp /mnt/etc/${_netfile} /etc/${_netfile}
#      fi
#   done
   ifconfig lo0 inet 127.0.0.1
   for hn in /etc/hostname.*; do
      if=${hn#/etc/hostname.}
      if ! isalphanumeric "$if"; then
         continue
      fi
      ifconfig $if > /dev/null 2>&1
      if [ $? -ne 0 ]; then
         continue
      fi
      while :; do
         if [ "$cmd2" ]; then
            set -- $cmd2
            af=$1 name=$2 mask=$3 bcaddr=$4 ext1=$5 cmd2=
            i=1; while [ i -lt 6 -a -n "$1" ]; do shift; let i=i+1; done
            ext2="$@"
         else
            read af name mask bcaddr ext1 ext2 || break
         fi
         case $af in
         "#"*|"!"*|"bridge"|""|"rtsol")
            continue
            ;;
         "dhcp")   [ "$name" = "NONE" ] && name=
            [ "$mask" = "NONE" ] && mask=
            [ "$bcaddr" = "NONE" ] && bcaddr=
            ifconfig $if $name $mask $bcaddr $ext1 $ext2 down
            cmd="dhclient $if"
            ;;
         "up")
            cmd="ifconfig $if $name $mask $bcaddr $ext1 $ext2 up"
            ;;
         *)   read dt dtaddr
            if [ "$name" = "alias" ]; then
               alias=$name
               name=$mask
               mask=$bcaddr
               bcaddr=$ext1
               ext1=$ext2
               ext2=
            else
               alias=
            fi
            cmd="ifconfig $if $af $alias $name "
            case $dt in
            dest)   cmd="$cmd $dtaddr"
               ;;
            [a-z!]*)
               cmd2="$dt $dtaddr"
               ;;
            esac
            if [ ! -n "$name" ]; then
               echo "/etc/hostname.$if: invalid network configuration file"
               return
            fi
            case $af in
            inet)   [ "$mask" ] && cmd="$cmd netmask $mask"
               if [ "$bcaddr" -a "$bcaddr" != "NONE" ]; then
                  cmd="$cmd broadcast $bcaddr"
               fi
               [ "$alias" ] && rtcmd="; route -qn add -host $name 127.0.0.1"
               ;;
            inet6)
               continue
               ;;
            *)   cmd="$cmd $mask $bcaddr"
            esac
            cmd="$cmd $ext1 $ext2$rtcmd" rtcmd=
            ;;
         esac
         eval "$cmd"
      done /dev/null 2>&1
      route -qn add -host default $(/dev/null
   route -qn add -net 127 127.0.0.1 -reject >/dev/null
   echo "Network interface configuration:"
   ifconfig -am
   route -n show
   if [ -f /etc/resolv.conf ]; then
      echo "\nResolver enabled."
   else
      echo "\nResolver not enabled."
   fi
}
get_fqdn() {
   local _dn
   _dn=$(hostname)
   _dn=${_dn#$(hostname -s)}
   _dn=${_dn#.}
   echo "${_dn:=my.domain}"
}
donetconfig() {
   local _dn _ns
   configure_ifs
   if [ -f /etc/resolv.conf.shadow ]; then
      mv /etc/resolv.conf.shadow /etc/resolv.conf
      _ns=$(sed -ne '/^nameserver /s///p' /etc/resolv.conf)
      _dn=$(sed -n \
         -e '/^domain[[:space:]][[:space:]]*/{s///;s/\([^[:space:]]*\).*$/\1/;h;}' \
         -e '/^search[[:space:]][[:space:]]*/{s///;s/\([^[:space:]]*\).*$/\1/;h;}' \
         -e '${g;p;}' /tmp/resolv.conf)
   fi
   ask "DNS domain name? (e.g. 'bar.com')" "${_dn:=$(get_fqdn)}"
   hostname "$(hostname -s).$resp"
   ask "DNS nameserver? (IP address or 'none')" "${_ns:=none}"
   if [[ $resp != none ]]; then
      echo "lookup file bind" > /etc/resolv.conf
      for _ns in $resp; do
         echo "nameserver $_ns" >> /etc/resolv.conf
      done
      ask_yn "Use the nameserver now?" yes
      [[ $resp == y ]] && cp /etc/resolv.conf /etc/resolv.conf.shadow
   fi
   [[ -n $(ifconfig -a | sed -ne '/[    ]inet .* broadcast /p') ]] && v4_defroute
#   edit_tmp_file hosts
#   manual_net_cfg
}
IFDEVS=$(get_ifdevs)
MODE=OpenBSD-LiveCD
EDITOR=mg
ask_until "\nSystem hostname? (short form, e.g. 'foo')" "$(hostname -s)"
[[ ${resp%%.*} != $(hostname -s) ]] && hostname $resp
( cd /etc; rm -f host* my* resolv.* dhclient.* )
cat > /etc/hosts  myname
_dn=$(get_fqdn)
while read _addr _hn _aliases; do
   if [[ -n $_aliases || $_hn != ${_hn%%.*} || -z $_dn ]]; then
      echo "$_addr $_hn $_aliases"
   else
      echo "$_addr $_hn.$_dn $_hn"
   fi
done  hosts.new
mv hosts.new hosts
)
ask "HTTP/FTP proxy URL? (e.g. 'http://proxy:8080', or 'none')" \
       "${ftp_proxy:-none}"
unset ftp_proxy http_proxy
[[ $resp == none ]] || export ftp_proxy=$resp http_proxy=$resp
我将制作的一个livecd放在:
ftp://ftp.linuxeden.com/rianren/
各位可以下载来试试!


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/13188/showart_68912.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP