Date: Tue, 20 Feb 2007 16:34:19 +0300 From: Yar Tikhiy <yar@comp.chem.msu.su> To: freebsd-stable@freebsd.org Subject: How I updated 4.11 to 6.2 in a single reboot Message-ID: <20070220133419.GB31403@comp.chem.msu.su>
next in thread | raw e-mail | index | archive | help
Hi all, I hope the following story will divert a few potential subscribers from freebsd-eol and save some effort aimed to keep the 4.11 zombie dancing. DISCLAIMER: I take no responsibility for inconvenience or damage that can happen if one uses my story as a how-to guide, especially without full knowledge of what and why he is actually doing. YMMV. I had an old machine with its CD-ROM and floppy drives long-dead and PXE missing from its boot options. It was running 4.11-STABLE. Facing the virtual EOL of the entire 4-STABLE branch, I wanted to update the machine's OS to 6.2-RELEASE and forget about it for a while, bar running freebsd-update occasionally. You'll say I should have connected a working CD-ROM drive to the machine and used the opportunity to dust its inside. Alas, I felt too lazy even to walk to the console. So I chose the path of least effort: to replace the binaries in the live system through SSH. This might sound like installing a heart implant without narcosis, but the surgeon was sufficiently heartless himself. First, I downloaded the following 6.2 distribution parts from an FTP server to the machine: base, dict, games, info, kernels, manpages. Had I wanted a minimal set, it would have consisted of base, kernels, manpages. (I had been taught well in the past not to save on manpages irrespective of the system's role.) Second, I added the system users and groups that had been born between 4.11 and 6.2. The new users were proxy, _pflogd, _dhcp; the new groups were proxy, authpf, _pflogd, _dhcp, audit. I just grabbed the appropriate revisions of src/etc/master.passwd and src/etc/group from CVSWeb, extracted the new records from them, and added those records to /etc/master.passwd (using vipw) and /etc/group. The new master.passwd and group files could also have been extracted from the base 6.2 distro. Note that the next step, full extraction of distros, could have resulted in wrong file ownership without this step. After that, I set DESTDIR to /usr/tmp: # mkdir /usr/tmp # export DESTDIR=/usr/tmp and ran install.sh in each distro subdirectory: # for d in base dict games info manpages > do > ( cd $d && sh install.sh ) > done # cd kernels && sh install.sh GENERIC So I got the new system's tree under /usr/tmp. At that stage, the old 4.11 tar(1) slightly mishandled the new archive format of the 6.2 distros by creating bogus PaxHeader directories instead of setting the schg flag on some files from the base distro. Fortunately, each PaxHeader directory hinted at which files should have had the schg flag set. Due to that I was able to save the list of files needing the flag. # find /usr/tmp -path "*/PaxHeader/*" | sed -e s,/PaxHeader,, -e s,/usr/tmp,, > /root/schg.lst I didn't set the flag on the files immediately because the files to be transferred to / would lose it anyway. (See below.) Then it was safe to remove the bogus directories: # find /usr/tmp -name PaxHeader | xargs rm -rf Having done with that, I created a scratch directory in / and transferred the respective files to it to make sure they fit in /: # mkdir /newroot # cd /usr/tmp # tar cf - COPYRIGHT bin boot dev etc lib libexec rescue sbin | ( cd /newroot && tar xpf - ) Note my having used tar(1), not cp(1) there. Alas, cp(1) would mishandle hard links by copying each link as a separate file. OTOH, tar(1) would lose file flags -- that's why I had saved the schg candidate list. Then I fixed the default kernel: # cd /newroot/boot # cp -pR GENERIC/* kernel/ ... updated the boot blocks: # disklabel -B -b /newroot/boot/boot1 -s /newroot/boot/boot2 ad0s1 ... created the new system directories in /var (the others could wait): # cp -pR /usr/tmp/var/named /var/ # mtree -deU -f /newroot/etc/mtree/BSD.var.dist -p /var The mtree command was the second to require that the new system users and groups be created in advance. Then I transferred the most essential settings from /etc to /newroot/etc for the machine to be up and accessible over the network after a reboot. The following files could simply be copied: fstab, resolv.conf, ssh/*key*. A few files in /newroot/etc called for manual work: - rc.conf (see below); - master.passwd (added myself and the rest of local users); - group (the most important thing was to assign myself to the wheel group); - mail/aliases (set the root alias.) I also made sure I didn't have a shell from /usr/local. In addition, I disabled all extra services in the new rc.conf. The hostname, network interface configuration, defaultrouter, and sshd_enable="YES" were basically needed in my case; stock services using the default configuration could also be enabled from the outset. After the preliminary merging of /etc, I built spwd.db and pwd.db in /newroot/etc: # pwd_mkdb -p -d /newroot/etc /newroot/etc/master.passwd To get the correct time zone after the reboot, I also copied /newroot/etc/localtime from /usr/tmp/usr/share/zoneinfo/Europe/Moscow. I should have created /newroot/etc/wall_cmos_clock if the machine hadn't had its hardware clock set in UTC. I also should have paid attention to /newroot/boot/loader.conf, had the system needed any modules pre-loaded or tunables pre-set. Then came the tricky part: replacing the binaries. I started it by killing off most daemons, especially those running external programs: # killall cron inetd sendmail syslogd At the same time, I killed neither sshd nor dhclient, or else I would lose my connection to the host. To prevent other users from logging into the system under update, I opened a couple of spare SSH sessions for myself just in case, then touched /var/run/nologin. There were no other users logged in at that moment. Actual replacing began from /usr: # cd /usr/tmp/usr # for d in bin games include lib libdata libexec sbin share src > do > mv /usr/$d /usr/$d.old && mv $d /usr/ > done And now -- /! # cd /newroot # mv COPYRIGHT lib libexec rescue / # for d in boot dev etc sbin > do > mv /$d /$d.old && mv $d / > done # mv /bin /bin.old # /bin.old/mv bin / At last, I crossed my fingers and typed: # /sbin.old/reboot It worked! In a couple of minutes I could log into the 6.2 system. It was time to finish the update. First, I applied the rest of /etc/mtree files except BSD.x11*: # cd /etc/mtree # mtree -deU -f BSD.root.dist -p / # mtree -deU -f BSD.usr.dist -p /usr # mtree -deU -f BSD.sendmail.dist -p / # mtree -deU -f BSD.include.dist -p /usr/include # mtree -deU -f BSD.local.dist -p /usr/local Then the schg candidate list in /root/schg.lst came handy: # xargs chflags schg < /root/schg.lst After that, I copied /etc/exports from /etc.old and manually merged local bits in rc.conf, inetd.conf, syslog.conf, newsyslog.conf, and shells. It would have had more sense to unpack the system sources and run mergemaster(8) against the /etc.old contents if I had had more local changes there. The commands I would have issued are as follows: # mv /etc /etc.new # cp -pR /etc.old /etc # mtree -deU -f /etc.new/BSD.root.dist -p / # mergemaster -i # cp /etc.new/localtime /etc Mergemaster would also have taken care of the dot-files in / and /root. I just overwrote them with the new versions as I hadn't had customized them. Further polishing included pkg_add'ing compat[45]x, enabling in rc.conf and starting important services from the base system and /usr/local (it's easy due to rc.d!) Now I'm going to update old ports gradually. Some day I'll remove the *.old stuff and say the last farewell to the good old 4.11. It did an excellent job for me, and I'll miss it. That's all, folks! P.S. To refresh my memory, I reproduced my scenario later in a virtual machine using 4.11-RELEASE. I was also interested in estimates for disc space usage during the process, as I was going to update even older and weaker machines in this manner. Here are some df(1) readings for the curious: Original 4.11 w/o catman, docs or src: Filesystem 1K-blocks Used Avail Capacity Mounted on /dev/ad0s1a 201518 36114 149284 19% / /dev/ad0s1f 1610806 109076 1372866 7% /usr /dev/ad0s1e 50350 318 46004 1% /var procfs 4 4 0 100% /proc After unpacking 6.2 to /usr/tmp from an external partition: Filesystem 1K-blocks Used Avail Capacity Mounted on /dev/ad0s1a 201518 36116 149282 19% / /dev/ad0s1f 1610806 270066 1211876 18% /usr /dev/ad0s1e 50350 318 46004 1% /var procfs 4 4 0 100% /proc After copying the respective files to /newroot: Filesystem 1K-blocks Used Avail Capacity Mounted on /dev/ad0s1a 201518 72884 112514 39% / /dev/ad0s1f 1610806 270066 1211876 18% /usr /dev/ad0s1e 50350 318 46004 1% /var procfs 4 4 0 100% /proc After copying GENERIC/* to kernel/: Filesystem 1K-blocks Used Avail Capacity Mounted on /dev/ad0s1a 201518 95896 89502 52% / /dev/ad0s1f 1610806 270066 1211876 18% /usr /dev/ad0s1e 50350 318 46004 1% /var procfs 4 4 0 100% /proc So, if you have a tiny / partition, you can mv instead of cp the kernel files from GENERIC/ to kernel/ and save some / space. See below. After the reboot: Filesystem 1K-blocks Used Avail Capacity Mounted on /dev/ad0s1a 201518 95926 89472 52% / devfs 1 1 0 100% /dev /dev/ad0s1f 1610806 270068 1211874 18% /usr /dev/ad0s1e 50350 316 46006 1% /var procfs 4 4 0 100% /proc After removing all old and tmp cruft: Filesystem 1K-blocks Used Avail Capacity Mounted on /dev/ad0s1a 201518 66916 118482 36% / devfs 1 1 0 100% /dev /dev/ad0s1f 1610806 124096 1357846 8% /usr /dev/ad0s1e 50350 318 46004 1% /var procfs 4 4 0 100% /proc After removing /boot/GENERIC, which was a duplicate of /boot/kernel: Filesystem 1K-blocks Used Avail Capacity Mounted on /dev/ad0s1a 201518 43924 141474 24% / devfs 1 1 0 100% /dev /dev/ad0s1f 1610806 124096 1357846 8% /usr /dev/ad0s1e 50350 320 46002 1% /var procfs 4 4 0 100% /proc It is clear from the first and last readings that disc space usage by 6.2 hasn't grown much as against 4.11, although there are a lot of important new features in 6.2. FreeBSD isn't like Some Other OS Types(tm), which double their disc space requirements on each major release. Great job, folks! -- Yar
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20070220133419.GB31403>