2002-09-09
Revision History | ||
---|---|---|
Revision 0.3 | 2002-09-24 | Revised by: gct |
Review suggestions incorporated | ||
Revision 0.2 | 2002-09-23 | Revised by: jyg |
Minor revisions | ||
Revision 0.1 | 2002-09-09 | Revised by: gct |
First draft. |
Copyright (c) 2002 Guilherme Tupynambá
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License (GFDL), Version 1.1 or any later version published by the Free Software Foundation; with no Invariant Sections, with no Front-Cover Texts, and with no Back-Cover Texts. The clone script is licensed in the terms of the GNU General Public License (GPL).
Install DHCP, if not installed, from the rpm package, normally found in Linux distributions:
# rpm -ihv dhcp-*.rpm |
#/etc/dhcpd.conf server-identifier dhcp.clonedomain.com; default-lease-time 172800; max-lease-time 604800; option domain-name "clonedomain.com"; subnet 10.0.0.0 netmask 255.255.255.0 { range dynamic-bootp 10.0.0.2 10.0.0.254; } |
Setting up TFTP is almost as easy as DHCP.
First install from the rpm package:
# rpm -ihv tftp-server-*.rpm |
Create a directory for the files:
# mkdir /tftpboot # chown nobody:nobody /tftpboot |
Edit the file /etc/xinetd.d/tftp to look like the following:
service tftp { socket_type = dgram protocol = udp wait = yes user = root server = /usr/sbin/in.tftpd server_args = -c -s /tftpboot disable = no per_source = 11 cps = 100 2 } |
Identify the compressed kernel file:
# cd /boot # ls vmlinuz-$(uname -r) vmlinuz-2.4.18-3 |
# tftp 10.0.0.1 tftp> binary tftp> put vmlinuz-2.4.18-3 vmlinuz Sent 1030147 bytes in 2.3 seconds tftp> quit |
Next, make the root file system image for the client. The full listing of the files is in Appendix A.
These files have been taken from a working system as a minimum configuration for having powerful shell (bash), client network utilities (dhcpcd and tftp), and copying and compressing utilities (dd, gzip). Administrative commands (mknod, mount, fdisk and insmod) are also present.
In the working directory create a file named initrd.lst and put these file names on it. To check the existence of these files in your system, run the following command:
# ls -d $(<initrd.lst) > /dev/null |
You should get an error output like this:
ls: /bin/clone: No such file or directory ls: /bin/tftp: No such file or directory ls: /lib/3c59x.o: No such file or directory |
The first error is a script to be created in the working directory. The second error is the program tftp found in the directory /usr/bin instead of /bin. The third is the network interface card module (probably not yours) found in the directory /lib/modules/$(uname -r)/kernel/drivers/net.
These three files will be discussed in upcoming sections separately soon. If there are other missing files, check for lack of installation or differences in version, distribution or hardware. Adjust the list to match your system.
# dd if=/dev/zero of=initrd bs=1024 count=4096 4096+0 records in 4096+0 records out # yes | mkfs initrd mke2fs 1.27 (8-Mar-2002) initrd is not a block special device. Proceed anyway? (y,n) Filesystem label= blah blah blah... # mkdir mnt # mount -o loop initrd mnt/ # egrep -v "clone|3c59x|tftp" initrd.lst | cpio -pdm mnt 4876 blocks |
# cp -p /usr/bin/tftp mnt/bin/ |
![]() | Whenever you see a reference to 3c59x, use the name of the module suited for your case. |
# cp -p /lib/modules/$(uname -r)/kernel/drivers/net/3c59x.o mnt/lib/ |
Edit the clone script found in Appendix B, changing the variables as explained in Section 6. Make it executable and copy it to the image directory:
# chmod +x clone # cp -p clone mnt/bin/ |
Unmount, compress, and send the initrd image.
# umount mnt/ # gzip initrd # tftp 10.0.0.1 tftp> binary tftp> put initrd.gz Sent 1155530 bytes in 2.8 seconds tftp> quit |
In the working directory create a file named grub.conf with the following content:
default=0 timeout=1 title Clone bootp root (nd) kernel /vmlinuz rw root=/dev/ram ramdisk_size=4096 init=/bin/clone initrd /initrd.gz |
In the last four lines are the Grub commands to boot from network:
To compile Grub, first download the source tarball from the Grub web site and unpack it. Run configure specifying the menu file you just created and the network interface card model. Run make as usual.
# tar xzf grub-0.92.tar.gz # cd grub-0.92 # ./configure --enable-preset-menu=../grub.conf --enable-3c90x # make |
Again, where you see 3c90x put the model of your network interface card. First check if it is supported by Grub.
The clone script, shown in Appendix B, is not essential. You can make init=/bin/bash as a kernel parameter and end up with a shell from where you can run the available commands and programs.
The script is presented here to show the commands in a formal way and to propose a way to reduce the possibility of damages resulting from mistyping. You have to change the variables tftp_server, nic_module, major_a, family_a and image_a according to your environment and application.
Please note that the arrays major_a and family_a are corresponding. Wrong major number for a given family name will mislead the user. You can locate the major and minor numbers of the devices of interest (whole disks and partitions) by listing the /dev directory. The major and minor number are where the size of a regular file is, in the output of the command ls -l, separated by a comma.
# ls -l /dev/fd0 /dev/hda /dev/hda1 /dev/hdc brw-rw---- 1 root disk 2, 0 Apr 11 11:25 /dev/fd0 brw-rw---- 1 root disk 3, 0 Apr 11 11:25 /dev/hda brw-rw---- 1 root disk 3, 1 Apr 11 11:25 /dev/hda1 brw-rw---- 1 root disk 22, 0 Apr 11 11:25 /dev/hdc |
The command set -e instructs the shell to abort the script should any command return non-zero code. The message"Kernel panic: Attempted to kill init!" will follow, as in case of normal end. Don't panic! This is normal, given the circumstances. Just turn off the computer. Press Ctrl-Alt-Del to have a smooth reboot before exiting the script to avoid this ugly message.
The command insmod will load the network interface module and the command dhcpcd will start DHCP client. Note that the fact that Grub used DHCP during its boot has nothing to do with Linux doing the same.
The script makes a big loop and, for each iteration, it asks for one of three operations: Copy from network to device, Copy from device to network or Run fdisk. Then the script asks which block device to use. The array major_a holds the major number for the block devices allowed to be used and the array family_a the respective names for the device families. Next, the script asks the minor number of the block device to be used.
# mkdir /mnt # mount ${device_name} /mnt # mknod ${image} p # tftp ${tftp_server} <<-EOT & binary put ${image} EOT tar czf ${image} |
# tftp ${tftp_server} <<-EOT & binary get ${image} EOT tar xzf ${image} |
You have to put the mkdir and tar programs in the initrd image so that the script can use them.
/bin/ /bin/bash /bin/clone /bin/dd /bin/gzip /bin/mknod /bin/mount /bin/tftp /dev/ /dev/console /dev/null /etc/ /etc/dhcpc/ /etc/hosts /etc/nsswitch.conf /etc/protocols /etc/services /lib/ /lib/3c59x.o /lib/i686/ /lib/i686/libc-2.2.5.so /lib/i686/libc.so.6 /lib/ld-2.2.5.so /lib/ld-linux.so.2 /lib/libdl-2.2.5.so /lib/libdl.so.2 /lib/libnss_files-2.2.5.so /lib/libnss_files.so.2 /lib/libtermcap.so.2 /lib/libtermcap.so.2.0.8 /proc/ /sbin/ /sbin/dhcpcd /sbin/fdisk /sbin/insmod /tmp/ /var/ /var/run/ |
#!/bin/bash set -e export PATH=/sbin:/bin tftp_server=10.0.0.1 nic_module=3c59x.o major_a=(2 3 22) family_a=(fd hda hdc) image_a=(img0001 img0002 img0003 img0004) operation_a=( "Copy from network to device" \ "Copy from device to network" \ "Run fdisk") mount -t proc proc /proc insmod /lib/${nic_module} /sbin/dhcpcd while true; do \ [ ! -z "${image}" ] && unset image echo echo "Clone Menu" echo echo "Operation" echo PS3="Choose operation (1-${#operation_a[*]}): " select operation in "${operation_a[@]}"; do \ [ -z "${operation}" ] && continue echo echo $REPLY - $operation echo break done echo "Device Family" echo PS3="Choose device family (1-${#family_a[*]}): " select family in "${family_a[@]}"; do \ [ -z "${family}" ] && continue echo echo $REPLY - $family echo break done major_i=$[REPLY-1] major=${major_a[$major_i]} echo "Minor Number" echo PS3="Choose minor number (0-255): " echo -n "$PS3" >&2 read minor minor=$[minor%256] echo echo $minor echo if [ "${operation}" != "${operation_a[2]}" ]; then \ echo "Image" echo PS3="Choose image (1-${#image_a[*]}): " select image in "${image_a[@]}"; do \ [ -z "${image}" ] && continue echo echo $REPLY - $image echo break done image_i=$[REPLY-1] image=${image_a[${image_i}]} fi echo echo -e "Operation:\t$operation" device_name=/dev/${family_a[${major_i}]}${minor} echo -e "Device:\t\t${device_name} ($major, $minor)" [ ! -z "${image}" ] && echo -e "Image:\t\t${image}" echo echo "Confirmation" echo PS3="Ok/Cancel (1-2): " select ok in Ok Cancel; do \ [ -z "${ok}" ] && continue echo echo $REPLY - $ok echo break done if [ "${ok}" = "Ok" ]; then \ if [ ! -b ${device_name} ]; then \ echo "Creating ${device_name}" mknod ${device_name} b ${major} ${minor} fi if [ ! -z "${image}" ]; then \ if [ ! -p ${image} ]; then \ echo "Creating pipe" mknod ${image} p fi fi if [ "${operation}" = "${operation_a[0]}" ]; then \ tftp ${tftp_server} <<-EOT & binary get ${image} EOT gzip -c -d < ${image} | dd of=${device_name} elif [ "${operation}" = "${operation_a[1]}" ]; then \ tftp ${tftp_server} <<-EOT & binary put ${image} EOT dd if=${device_name} | gzip -c > ${image} elif [ "${operation}" = "${operation_a[2]}" ]; then \ fdisk ${device_name} fi echo fi echo "Continuation" echo PS3="Continue/Exit (1-2): " select new in Continue Exit; do \ [ -z "${new}" ] && continue echo echo $REPLY - $new echo break done [ "${new}" = "Exit" ] && break done exit 0 |