Sometimes you may want to do a custom installation of Slackware Linux, for example to get better understanding of how GNU/Linux systems work, or to prepare an automatic installation script. This chapter outlines the steps that are required to install Slackware Linux manually. A sample installation script is also provided in Section 6.5.
If you have performed a normal installation, you should not have any problems partitioning a disk. You can use the fdisk(8) and cfdisk(8) commands to partition disks. If you are scripting the installation of Slackware Linux it is useful to know that you can pipe fdisk commands to the fdisk binary. For example:
# fdisk /dev/hda << EOF n p 1 +10000M n p 2 +512M t 2 82 w EOF
These commands create a primary Linux partition of 10000MB, and a primary Linux swap partition of 512MB. You could store the fdisk commands in different disk profiles, and use one of the profiles based on the specific deployment (e.g. the disk size). For example:
# cat /usr/share/fdisk-profiles/smalldisk | fdisk
After making at least a swap and a Linux partition, you can initialize the filesystem and swap space and make use of this storage. On systems that are short on memory, you should initialize, and use swap first. We will use the partition layout used in the partitioning example listed above in the following examples. To set up and use swap, execute:
# mkswap /dev/hda2 # swapon /dev/hda2
The meaning of these commands is quite obvious. mkswap(8) initializes the swap space, and swapon(8) puts it to use. You will only have to execute mkswap once, but swapon has to be executed during every system boot. This can be done automatically by adding an entry for the swap partition to /etc/fstab, which we will do during a later step.
For now, it is important to initialize the target partitions. This can be done with the mkfs(8) command. You can specify which filesystem should be used by adding the -t parameter. mkfs will automatically invoke a mkfs.filesystem command based on the filesystem that you have chosen. Be aware that the filesystems that can be used depends on the installation kernel that you have booted. If you have booted the bare.i kernel, you can use the ext2, ext3 and reiserfs filesystems.
To initialize an ext3 filesystem, and mount it, you should execute the following commands:
# mkfs -t ext3 /dev/hda1 # mount /dev/hda1 /mnt
If you have made separate partitions for certain directories in the root filesystem, e.g. /home, you can also initialize them and mount them at this point. For example:
# mkfs -t ext3 /dev/hda2 # mkdir /mnt/home # mount /dev/hda2 /mnt/home
Finally, you will have to mount your source medium. If you use a CD-ROM, this is easy. Suppose that /dev/hdc is the CD-ROM device file, you can mount the CD-ROM with:
# mount /dev/hdc /var/log/mount
Using NFS as the installation medium requires some more steps. First of all, you will have to load the network disk. You can do this by running the network command and inserting a network disk. You can also load this disk from another medium, for example from an USB memory stick. Suppose that you have mounted a USB memory stick on /var/log/mount, you can load the network disk with: network /var/log/mount/network.dsk. After loading the network disk, you will have to configure the network interface. If the NFS server is on the same network, you will only have to assign an IP address to the network interface. For example, to use the address 192.168.2.201, you could execute the following command:
# ifconfig eth0 192.168.2.201
You can then load the portmapper, which is necessary for the NFS client to function correctly:
# /sbin/rpc.portmap
If the portmapper started correctly, you can mount the NFS volume. But, first make sure that you unmount any filesystem that you have previously mounted at /var/log/mount. If no other filesystems are mounted at /var/log/mount, you can proceed with mounting the NFS volume. Suppose, that you want to mount 192.168.2.1:/home/pub/slackware-current, you should issue the following command:
# mount -r -t nfs -o nolock 192.168.2.1:/home/pub/slackware-current /var/log/mount
If no errors where printed when the volume was mounted, it should be accessible through /var/log/mount
Everything is now set up to start installing packages from the installation medium. Since installpkg(8) is available from the installation system, you can use it to install Slackware Linux packages. To install packages to the target partition(s) mounted on /mnt, add the -root. The following command installs all packages from the source medium:
# installpkg -root /mnt /var/log/mount/slackware/*/*.tgz
If you have created tagfiles to define which packages should be installed, then you can use them now (tagfiles are described in Section 18.4). Suppose that you have stored a tagfile for each disk set in /usr/share/tagfiles/small-desktop, you can install packages based on the tagfiles in the following manner:
# for p in [a-z]*; do installpkg -root /mnt -tagfile /usr/share/tagfiles/small-desktop/$p/tagfile /var/log/mount/slackware/$p/*.tgz done
The next sections describe the bare minimum of configuration that is necessary to get a running system.
One of the necessary configuration steps is to create a fstab(5) file, so that the system can look up what partitions or volumes have to be mounted. The format of the /etc/fstab file is described in Section 8.6.4. As a bare minimum you will have to add entries for the / filesystem, the /proc pseudo-filesystem, the devpts pseudo-filesystem, and the swap partition.
With the sample partitioning used earlier in this chapter, you could create a /etc/fstab like this:
# cat > /mnt/etc/fstab << EOF /dev/hda2 swap swap defaults 0 0 /dev/hda1 / ext3 defaults 1 1 devpts /dev/pts devpts gid=5,mode=620 0 0 proc /proc proc defaults 0 0
To make the system bootable you will have to configure and install the Linux Loader (LILO). The configuration of LILO is covered in Section 20.1. For this section we will just show a sample LILO configuration, that can be used with the partition layout described in this chapter. The first step is to create the /etc/lilo.conf file:
# cat > /mnt/etc/lilo.conf << EOF boot = /dev/hda vga = normal timeout = 50 image = /boot/vmlinuz root = /dev/hda1 label = Slackware read-only EOF
You can then install LILO with /mnt as the LILO root. With /mnt set as the root, LILO will use /etc/lilo.conf from the target partition:
# lilo -r /mnt
The configuration of networking in Slackware Linux is covered in Chapter 23. This section will cover one example of a host that will use DHCP to get an IP address.
The /etc/networks file contains information about known Internet networks. Because we will get network information via DHCP, we will just use 127.0.0.1 as the local network.
# cat > /mnt/etc/networks << EOF loopback 127.0.0.0 localnet 127.0.0.0 EOF
Although we will get a hostname via DHCP, we will still set up a temporary hostname:
# cat > /mnt/etc/HOSTNAME << EOF sugaree.example.net EOF
Now that the hostname is configured, the hostname and localhost should also be made resolvable, by creating a /etc/hosts database:
# cat > /mnt/etc/hosts << EOF 127.0.0.1 localhost 127.0.0.1 sugaree.example.net sugaree EOF
We do not have to create a /etc/resolv.conf, since it will be created automatically by dhcpcd, the DHCP client. So, finally, we can set up the interface in /etc/rc.d/rc.inet1.conf:
# cat > /mnt/etc/rc.d/rc.inet1.conf << EOF IPADDR[0]="" NETMASK[0]="" USE_DHCP[0]="yes" DHCP_HOSTNAME[0]="" EOF
Depending on the purpose of the system that is being installed, it should be decided which initialization scripts should be started. The number of services that are available depends on what packages you have installed. You can get get a list of available scripts with ls(1):
# ls -l /mnt/etc/rc.d/rc.*
If the executable bits are set on a script, it will be started, otherwise it will not. Obviously you should keep essential scripts executable, including the runlevel-specific scripts. You can set the executable bit on a script with:
# chmod +x /etc/rc.d/rc.scriptname
Or remove it with:
# chmod -x /etc/rc.d/rc.scriptname
GNU/Linux uses a cache for loading dynamic libraries. Besides that many programs rely on generic version numbers of libraries (e.g. /usr/lib/libgtk-x11-2.0.so, rather than /usr/lib/libgtk-x11-2.0.so.0.600.8). The cache and library symlinks can be updated in one ldconfig(8) run:
# chroot /mnt /sbin/ldconfig
You may not know the chroot(1) command; it is a command that executes a command with a different root than the active root. In this example the root directory is changed to /mnt, and from there chroot(1) runs /sbin/ldconfig binary. After the command has finished the system will return to the shell, which uses the original root. To use chroot(1) with other commands this ldconfig(8) command has to be executed once first, because without initializing the dynamic linker run-time bindings most commands will not execute, due to unresolvable library dependencies.
Now that the dynamic library cache and links are set up, you can execute commands on the installed system. We will make use of this to set the root password. The passwd(1) can be used to set the password for an existing user (the root user is part of the initial /etc/passwd file). We will use the chroot(1) again to execute the command on the target partition:
# chroot /mnt /usr/bin/passwd root
On UNIX-like systems it is important to set the timezone correctly, because it is used by various parts of the system. For instance, the timezone is used by NTP to synchronize the system time correctly, or by different networking programs to compute the time difference between a client and a server. On Slackware Linux the timezone can be set by linking /etc/localtime to a timezone file. You can find the timezone for your region by browsing the /mnt/usr/share/zoneinfo directory. Most timezones can be found in the subdirectories of their respective regions. For example to use Europe/Amsterdam as the timezone, you can execute the following commands:
# cd /mnt # rm -rf etc/localtime # ln -sf /usr/share/zoneinfo/Europe/Amsterdam etc/localtime
After setting the time zone, programs still do not know whether the hardware clock is set to the local time, or to the Coordinated Universal Time (UTC) standard. If you use another operating system on the same machine that does not use UTC it is best to set the hardware clock to the local time. On UNIX-like systems it is a custom to set the system time to UTC. You can set what time the system clock uses, by creating the file /etc/hardwareclock, and putting the word localtime in it if your clock is set to the local time, or UTC when it is set to UTC For example, to use UTC, you can create /etc/hardwareclock in the following manner:
# echo "UTC" > /mnt/etc/hardwareclock
If you are going to use X11, you will have to initialize the font cache for TrueType and Type1 fonts. This can be done with the fc-cache(1) command:
# chroot /mnt /usr/X11R6/bin/fc-cache
It is easy to combine the steps of a custom installation into one script, which performs the custom steps automatically. This is ideal for making default server installs or conducting mass roll-outs of Linux clients. This sections contains a sample script that was written by William Park. It is easy to add an installation script to the Slackware Linux medium, especially if you use an installation CD-ROM or boot the installation system from an USB flash drive.
The installation system is stored in one compressed image file, that is available on the distribution medium as isolinux/initrd.img. You can make a copy of this image to your hard disk, and decompress it with gunzip(1):
# mv initrd.img initrd.img.gz # gunzip initrd.img.gz
After decompressing the image, you can mount the file as a disk, using the loopback device:
# mount -o loop initrd.img /mnt/hd
You can now add a script to the initrd file by adding it to the directory structure that is available under the mount point. After making the necessary changes, you can unmount the filesystem and compress it:
# umount /mnt/hd # gzip initd.img # mv initrd.img.gz initrd.img
You can then put the new initrd.img file on the installation medium, and test the script.
#! /bin/sh # Copyright (c) 2003-2005 by William Park <[email protected]>. # All rights reserved. # # Usage: slackware-install.sh rm_ln () # Usage: rm_ln from to { rm -rf $2; ln -sf $1 $2 } ############################################################################### echo "Partitioning harddisk..." ( echo -ne "n\np\n1\n\n+1000M\n" # /dev/hda1 --> 1GB swap echo -ne "n\np\n2\n\n+6000M\n" # /dev/hda2 --> 6GB / echo -ne "t\n1\n82\nw\n" ) | fdisk /dev/hda mkswap /dev/hda1 # swap swapon /dev/hda1 mke2fs -c /dev/hda2 # / mount /dev/hda2 /mnt ############################################################################### echo "Installing packages..." mount -t iso9660 /dev/hdc /cdrom # actually, /var/log/mount cd /cdrom/slackware for p in [a-z]*; do # a, ap, ..., y installpkg -root /mnt -priority ADD $p/*.tgz done cd /mnt ############################################################################### echo "Configuring /dev/* stuffs..." rm_ln psaux dev/mouse # or, 'input/mice' for usb mouse rm_ln ttyS0 dev/modem rm_ln hdc dev/cdrom rm_ln hdc dev/dvd ############################################################################### echo "Configuring /etc/* stuffs..." cat > etc/fstab << EOF /dev/hda1 swap swap defaults 0 0 /dev/hda2 / ext2 defaults 1 1 devpts /dev/pts devpts gid=5,mode=620 0 0 proc /proc proc defaults 0 0 # /dev/cdrom /mnt/cdrom iso9660 noauto,owner,ro 0 0 /dev/fd0 /mnt/floppy auto noauto,owner 0 0 tmpfs /dev/shm tmpfs noauto 0 0 EOF cat > etc/networks << EOF loopback 127.0.0.0 localnet 192.168.1.0 EOF cat > etc/hosts << EOF 127.0.0.1 localhost 192.168.1.1 node1.example.net node1 EOF cat > etc/resolv.conf << EOF search example.net nameserver 127.0.0.1 EOF cat > etc/HOSTNAME << EOF node1.example.net EOF ## setup.05.fontconfig chroot . /sbin/ldconfig # must be run before other program chroot . /usr/X11R6/bin/fc-cache chroot . /usr/bin/passwd root ## setup.06.scrollkeeper chroot . /usr/bin/scrollkeeper-update ## setup.timeconfig rm_ln /usr/share/zoneinfo/Canada/Eastern etc/localtime cat > etc/hardwareclock << EOF localtime EOF ## setup.liloconfig cat > etc/lilo.conf << EOF boot=/dev/hda delay=100 vga=normal # 80x25 char # VESA framebuffer console: # pixel char 8bit 15bit 16bit 24bit # ----- ---- ---- ----- ----- ----- # 1600x1200 796 797 798 799 # 1280x1024 160x64 775 793 794 795 # 1024x768 128x48 773 790 791 792 # 800x600 100x37 771 787 788 789 # 640x480 80x30 769 784 785 786 image=/boot/vmlinuz # Linux root=/dev/hda2 label=bare.i read-only # other=/dev/hda1 # Windows # label=win # table=/dev/hda EOF lilo -r . ## setup.xwmconfig rm_ln xinitrc.fvwm95 etc/X11/xinit/xinitrc ############################################################################### echo "Configuring /etc/rc.d/rc.* stuffs..." cat > etc/rc.d/rc.keymap << EOF #! /bin/sh [ -x /usr/bin/loadkeys ] && /usr/bin/loadkeys us.map EOF chmod -x etc/rc.d/rc.keymap ## setup.mouse cat > etc/rc.d/rc.gpm << 'EOF' #! /bin/sh case $1 in stop) echo "Stopping gpm..." /usr/sbin/gpm -k ;; restart) echo "Restarting gpm..." /usr/sbin/gpm -k sleep 1 /usr/sbin/gpm -m /dev/mouse -t ps2 ;; start) echo "Starting gpm..." /usr/sbin/gpm -m /dev/mouse -t ps2 ;; *) echo "Usage $0 {start|stop|restart}" ;; esac EOF chmod +x etc/rc.d/rc.gpm ## setup.netconfig cat > etc/rc.d/rc.inet1.conf << EOF IPADDR=(192.168.1.1) # array variables NETMASK=(255.255.255.0) USE_DHCP=() # "yes" or "" DHCP_HOSTNAME=() GATEWAY="" DEBUG_ETH_UP="no" EOF cat > etc/rc.d/rc.netdevice << EOF /sbin/modprobe 3c59x EOF chmod +x etc/rc.d/rc.netdevice ## setup.setconsolefont mv etc/rc.d/rc.font{.sample,} chmod -x etc/rc.d/rc.font ## setup.services chmod +x etc/rc.d/rc.bind chmod +x etc/rc.d/rc.hotplug chmod +x etc/rc.d/rc.inetd chmod +x etc/rc.d/rc.portmap chmod +x etc/rc.d/rc.sendmail # chmod -x etc/rc.d/rc.atalk chmod -x etc/rc.d/rc.cups chmod -x etc/rc.d/rc.httpd chmod -x etc/rc.d/rc.ip_forward chmod -x etc/rc.d/rc.lprng chmod -x etc/rc.d/rc.mysqld chmod -x etc/rc.d/rc.pcmcia chmod -x etc/rc.d/rc.samba chmod -x etc/rc.d/rc.sshd