PXE是Preboot Execution Environment的简称,个人一般用它来实现系统的网络引导安装。简要的说,PXE引导的过程是这样的:
当然,由于机器本地没有安装介质,后续还是要通过NFS/HTTP/FTP等服务器获得安装源文件,但这不属于PXE服务器的范畴,就不讲述了。
综上,搭建一个PXE服务器,包括三个部分的工作:
前两个都是标准的服务,但不同系统引导所需的文件是不相同的,各有各的特点。
本文先在slackware环境下搭建PXE服务器环境,之后介绍个人涉及的几个Linux发行版的引导程序文件,最后配置一个综合的PXE服务器。
下面的具体操作基于slackware64 13.37,详细的说明可参阅slackware官方文档README_PXE.TXT。
slackware下的tftp服务器通过inetd启动。编辑/etc/inetd.conf,修改tftp所在行:
tftp dgram udp wait root /usr/sbin/in.tftpd in.tftpd -s /repo/ftp/tftpboot -r blksize
这里将服务器的文件目录设置为/repo/ftp/tftpboot,缺省是/tftpboot。
如果之前inetd服务没启用,则启用之:
chmod a+x /etc/rc.d/rc.inetd /etc/rc.d/rc.inetd start
首先进入tftp服务器文件根目录:
cd /repo/ftp/tftpboot
为了方便后续与其他Linux发行版的整合,这里不将文件直接放在根目录下,而是新建子目录:
mkdir -p slackware/64-13.37 cd slackware/64-13.37
拷贝相关文件(假设安装源文件在~/ftp/slackware/slackware64-13.37/目录下):
mkdir pxelinux.cfg cp /usr/share/syslinux/pxelinux.0 . cp ~/ftp/slackware/slackware64-13.37/isolinux/message.txt . cp ~/ftp/slackware/slackware64-13.37/isolinux/f2.txt . cp ~/ftp/slackware/slackware64-13.37/isolinux/initrd.img . cp ~/ftp/slackware/slackware64-13.37/usb-and-pxe-installers/pxelinux.cfg_default pxelinux.cfg/default cp -a ~/ftp/slackware/slackware64-13.37/kernels .
编辑配置文件/etc/dhcpd.conf,下面是一个最简单的配置模式:
# dhcpd.conf # # Configuration file for ISC dhcpd # # If this DHCP server is the official DHCP server for the local # network, the authoritative directive should be uncommented. authoritative; ddns-update-style none; # Allow bootp requests allow bootp; # Point to the TFTP server: next-server 172.18.0.1; # Default lease is 1 week (604800 sec.) default-lease-time 604800; # Max lease is 4 weeks (2419200 sec.) max-lease-time 2419200; subnet 172.18.0.0 netmask 255.255.255.0 { option domain-name "copyleft.net"; option broadcast-address 172.18.0.255; option subnet-mask 255.255.255.0; option domain-name-servers 192.168.176.1; option routers 172.18.0.99; range dynamic-bootp 172.18.0.201 172.18.0.210; use-host-decl-names on; if substring (option vendor-class-identifier, 0, 9) = "PXEClient" { filename "/slackware/64-13.37/pxelinux.0"; } }
这里的几个关键配置分别是第11、14、30行。
新建启动脚本/etc/rc.d/rc.dhcpd:
#!/bin/sh # # /etc/rc.d/rc.dhcpd # This shell script takes care of starting and stopping # the ISC DHCPD service # # Put the command line options here that you want to pass to dhcpd: DHCPD_OPTIONS="-q eth0" [ -x /usr/sbin/dhcpd ] || exit 0 [ -f /etc/dhcpd.conf ] || exit 0 start() { # Start daemons. echo -n "Starting dhcpd: /usr/sbin/dhcpd $DHCPD_OPTIONS " /usr/sbin/dhcpd $DHCPD_OPTIONS echo } stop() { # Stop daemons. echo -n "Shutting down dhcpd: " killall -TERM dhcpd echo } status() { PIDS=$(pidof dhcpd) if [ "$PIDS" == "" ]; then echo "dhcpd is not running!" else echo "dhcpd is running at pid(s) ${PIDS}." fi } restart() { stop start } # See how we were called. case "$1" in start) start ;; stop) stop ;; restart) stop start ;; status) status ;; *) echo "Usage: $0 {start|stop|status|restart}" ;; esac exit 0
其中的第9行指定dhcpd服务的网络接口。
最后,启动dhcpd服务,就可以测试PXE网络安装了:
chmod +x /etc/rc.d/rc.dhcpd touch /var/state/dhcp/dhcpd.leases /etc/rc.d/rc.dhcpd start
CentOS 5本身有一个工具Network Booting Services,可以自动配置引导文件。如果之前没有安装,可以执行如下命令安装:
yum install system-config-netboot
运行:
system-config-netboot
点击:Configure → Network Installation → Add,按照提示进行配置,完毕所有输出文件存放在/tftpboot/linux-install/目录下。生成的文件列表如下(这里以64位的CentOS 5.8为例):
./msgs ./msgs/rescue.msg ./msgs/boot.msg ./msgs/general.msg ./msgs/param.msg ./msgs/snake.msg ./msgs/expert.msg ./pxelinux.0 ./CentOS_5_x86_64 ./CentOS_5_x86_64/vmlinuz ./CentOS_5_x86_64/ks.cfg ./CentOS_5_x86_64/initrd.img ./pxelinux.cfg ./pxelinux.cfg/default ./pxelinux.cfg/pxeos.xml
同样的,我们将所有文件复制到特定目录下:
cp -a /tftpboot/linux-install/* /repo/ftp/tftpboot/centos/5/x86_64/
要测试,只需修改dhcpd.conf的如下部分:
if substring (option vendor-class-identifier, 0, 9) = "PXEClient" { filename "/centos/5/x86_64/pxelinux.0"; }
之所以CentOS要分两个版本来说明,是因为在6版本中已经没有Network Booting Services了。不过没关系,在了解了引导文件的大概架构后,可以手工来实现。
这里以64位的CentOS 6.3为例,并假设安装源文件在~/ftp/centos/6/os/x86_64/目录下。同时需要事先安装syslinux软件包,如果未安装,则执行:
yum install syslinux
拷贝相关文件:
mkdir -p /repo/ftp/tftpboot/centos/6/x86_64 cd /repo/ftp/tftpboot/centos/6/x86_64/ cp /usr/share/syslinux/menu.c32 . cp /usr/share/syslinux/pxelinux.0 . mkdir CentOS_6_x86_64 cp ~/ftp/centos/6/os/x86_64/images/pxeboot/vmlinuz CentOS_6_x86_64/ cp ~/ftp/centos/6/os/x86_64/images/pxeboot/initrd.img CentOS_6_x86_64/ mkdir pxelinux.cfg
接下来新建文件pxelinux.cfg/default:
timeout 100 default menu.c32 menu title ########## PXE Boot Menu ########## label 1 menu label ^1) Install CentOS 6 x86_64 kernel CentOS_6_x86_64/vmlinuz append initrd=CentOS_6_x86_64/initrd.img label 2 menu label ^2) Boot from local drive localboot
这是一个最简单的配置模式。
修改dhcpd.conf的如下部分,以便测试:
if substring (option vendor-class-identifier, 0, 9) = "PXEClient" { filename "/centos/6/x86_64/pxelinux.0"; }
这里以64位的Debian 6(squeeze)为例,相关文件官方已经打包做好,直接下载就行了,所在位置:debian-mirror-site/dists/squeeze/main/installer-amd64/current/images/netboot/netboot.tar.gz。
解开netboot.tar.gz文件:
mkdir -p /repo/ftp/tftpboot/debian/6/amd64 cd /repo/ftp/tftpboot/debian/6/amd64/ tar xzvf netboot.tar.gz
修改dhcpd.conf的如下部分,以便测试:
if substring (option vendor-class-identifier, 0, 9) = "PXEClient" { filename "/debian/6/amd64/pxelinux.0"; }
Ubuntu和Debian的方法是一样的。这里以64位的Ubuntu 12.04为例,下载位置:ubuntu-mirror-site/dists/precise/main/installer-amd64/current/images/netboot/netboot.tar.gz。
解开netboot.tar.gz文件:
mkdir -p /repo/ftp/tftpboot/ubuntu/12.04/amd64 cd /repo/ftp/tftpboot/ubuntu/12.04/amd64/ tar xzvf netboot.tar.gz
修改dhcpd.conf的如下部分,以便测试:
if substring (option vendor-class-identifier, 0, 9) = "PXEClient" { filename "/ubuntu/12.04/amd64/pxelinux.0"; }
经过上述操作,很自然就会想到,何不做一个综合各个Linux发行版的PXE服务器呢?而不用每次手工修改dhcp配置文件,想装哪个系统就装哪个。好吧,接下来就做。
上面的实现中,Debian和Ubuntu的形式是多层次菜单驱动的。经过短暂对Debian架构的了解,决定基于Debian来构建。架构不算太复杂,就不过多说明了,下面直接列出具体操作。
复制Debian的pxelinu.0:
cd /repo/ftp/tftpboot/ cp debian/6/amd64/pxelinux.0 .
建立pxelinux.cfg目录:
mkdir pxelinux.cfg
参照Debian在pxelinux.cfg目录下新建default文件:
include config/menu.cfg default config/vesamenu.c32 prompt 0 timeout 0
建立config目录,后续操作在config目录下进行:
mkdir config cd config/
复制Debian的splash.png和vesamenu.c32:
cp ../debian/6/amd64/debian-installer/amd64/boot-screens/splash.png . cp ../debian/6/amd64/debian-installer/amd64/boot-screens/vesamenu.c32 .
复制Debian的stdmenu.cfg并做相应修改:
cp ../debian/6/amd64/debian-installer/amd64/boot-screens/stdmenu.cfg .
这里只修改了文件路径:
diff stdmenu.cfg ../debian/6/amd64/debian-installer/amd64/boot-screens/stdmenu.cfg 1c1 < menu background config/splash.png --- > menu background debian-installer/amd64/boot-screens/splash.png
参照Debian新建menu.cfg文件:
menu hshift 15 menu width 49 menu title Installer boot menu include config/stdmenu.cfg menu begin slackware64-13.37 menu title Slackware64-13.37 label mainmenu menu label ^Back.. menu exit include config/slackware64-13.37.cfg menu end menu begin centos64-5 menu title CentOS/x86_64 5 label mainmenu menu label ^Back.. menu exit include config/centos64-5.cfg menu end menu begin centos64-6 menu title CentOS/x86_64 6 label mainmenu menu label ^Back.. menu exit include config/centos64-6.cfg menu end menu begin debian64-6 menu title Debian/amd64 6 label mainmenu menu label ^Back.. menu exit include config/debian64-6.cfg menu end menu begin ubuntu64-12.04 menu title Ubuntu/amd64 12.04 label mainmenu menu label ^Back.. menu exit include config/ubuntu64-12.04.cfg menu end
每个发行版占用一个菜单项,对应一个单独的配置文件,文件里的每个安装选项又对应一个子菜单项。
下面是各个发行版配置文件的具体内容,除了基本的安装选项外,也融合了Expert、Rescue等选项,方便使用。
default huge.s label huge.s menu label ^huge.s menu default kernel slackware/64-13.37/kernels/huge.s/bzImage append initrd=slackware/64-13.37/initrd.img load_ramdisk=1 prompt_ramdisk=0 rw printk.time=0 SLACK_KERNEL=huge.s label speakup.s menu label ^speakup.s kernel slackware/64-13.37/kernels/huge.s/bzImage append initrd=slackware/64-13.37/initrd.img load_ramdisk=1 prompt_ramdisk=0 rw printk.time=0 SLACK_KERNEL=huge.s label memtest menu label ^memset kernel slackware/64-13.37/kernels/memtest/memtest
default install label install menu label ^Install menu default kernel centos/5/x86_64/CentOS_5_x86_64/vmlinuz append initrd=centos/5/x86_64/CentOS_5_x86_64/initrd.img label expert menu label ^Install (Expert mode) kernel centos/5/x86_64/CentOS_5_x86_64/vmlinuz append initrd=centos/5/x86_64/CentOS_5_x86_64/initrd.img expert label rescue menu label ^Rescue mode kernel centos/5/x86_64/CentOS_5_x86_64/vmlinuz append initrd=centos/5/x86_64/CentOS_5_x86_64/initrd.img rescue
default install label install menu label ^Install menu default kernel centos/6/x86_64/CentOS_6_x86_64/vmlinuz append initrd=centos/6/x86_64/CentOS_6_x86_64/initrd.img label basic menu label ^Install (basic video) kernel centos/6/x86_64/CentOS_6_x86_64/vmlinuz append initrd=centos/6/x86_64/CentOS_6_x86_64/initrd.img xdriver=vesa nomodeset label rescue menu label ^Rescue mode kernel centos/6/x86_64/CentOS_6_x86_64/vmlinuz append initrd=centos/6/x86_64/CentOS_6_x86_64/initrd.img rescue
default install label install menu label ^Install menu default kernel debian/6/amd64/debian-installer/amd64/linux append vga=788 initrd=debian/6/amd64/debian-installer/amd64/initrd.gz -- quiet label expert menu label ^Expert install kernel debian/6/amd64/debian-installer/amd64/linux append priority=low vga=788 initrd=debian/6/amd64/debian-installer/amd64/initrd.gz -- label rescue menu label ^Rescue mode kernel debian/6/amd64/debian-installer/amd64/linux append vga=788 initrd=debian/6/amd64/debian-installer/amd64/initrd.gz rescue/enable=true -- quiet label auto menu label ^Automated install kernel debian/5.0/amd64/debian-installer/amd64/linux append auto=true priority=critical vga=788 initrd=debian/6/amd64/debian-installer/amd64/initrd.gz -- quiet
default install label install menu label ^Install menu default kernel ubuntu/12.04/amd64/ubuntu-installer/amd64/linux append vga=788 initrd=ubuntu/12.04/amd64/ubuntu-installer/amd64/initrd.gz -- quiet label cli menu label ^Command-line install kernel ubuntu/12.04/amd64/ubuntu-installer/amd64/linux append tasks=standard pkgsel/language-pack-patterns= pkgsel/install-language-support=false vga=788 initrd=ubuntu/12.04/amd64/ubuntu-installer/amd64/initrd.gz -- quiet label expert menu label ^Expert install kernel ubuntu/12.04/amd64/ubuntu-installer/amd64/linux append priority=low vga=788 initrd=ubuntu/12.04/amd64/ubuntu-installer/amd64/initrd.gz -- label cli-expert menu label Command-^line expert install kernel ubuntu/12.04/amd64/ubuntu-installer/amd64/linux append tasks=standard pkgsel/language-pack-patterns= pkgsel/install-language-support=false priority=low vga=788 initrd=ubuntu/12.04/amd64/ubuntu-installer/amd64/initrd.gz -- label rescue menu label ^Rescue mode kernel ubuntu/12.04/amd64/ubuntu-installer/amd64/linux append vga=788 initrd=ubuntu/12.04/amd64/ubuntu-installer/amd64/initrd.gz rescue/enable=true -- quiet
最后,修改dhcpd.conf的如下部分:
if substring (option vendor-class-identifier, 0, 9) = "PXEClient" { filename "/pxelinux.0"; }
配置完毕。