From Mark F. Johnson on Wed, 27 Jan 1999
Greetings Once Again Honorable Guru,
My newly acquired, but soon to be short-lived, reputation as a Linux sage is in danger. I have been helping my friend set up Linux on his PC at home. He was the one who waged the Winmodem battle I told you about. He is attempting to duplicate my success at dual-booting Windows98 and Linux (RedHat 5.2). When he uses the workstation install mode, everything works fine. But when we attempt a custom install, which I have done successfully numerous times, the install goes fine until the first reboot. Then the boot sequence stops after checking his partitions, with a message that reads "Unable to open a console". We have done everything identically to the method I used on my PC, which is a near duplicate of his PC. We have removed all the partitions and OS's, including Windows, repartitioned and reformatted the drive, verified that the available space equalled the size of the drive, and reinstalled Windows and then Linux. Still, no joy. Same message. During the custom install, we created a 300MB root directory, a 127MB swap file (he has 128MB RAM), and three 600MB (growable) directories (/usr, /home, and /opt). As I said, everything formatted and installed without a hitch until reboot.
I have searched the past Linux Gazettes for an answer to this problem, but I came up dry. Any help would be appreciated.
Unable to open console after reboot suggests a problem in your /dev directory tree. If the tty1 and other "virtual terminal" device nodes are inaccessible (you tried to put /dev as a symlink to some mounted filesystem or something like that) then I'd expect this error message.
You can get similar problems (error messages regarding utmp or wtmp files) if your /var/log doesn't get mounted --- or doesn't exist.
So, it could be some problem with the way you're structuring your filesystems. Boot from a rescue floppy and look around. Make sure that the /dev directory is on your root filesystem and that the /dev/tty[0-2]* devices nodes are there, and that the are proper character devices. An 'ls -al' should look a bit like:
crw-rw---- 1 jimd users 4, 0 Jul 26 1998 /dev/tty0 crw--w---- 1 jimd tty 4, 1 Jan 26 22:23 /dev/tty1 crw------- 1 root root 4, 10 Jan 7 17:41 /dev/tty10 crw--w---- 1 root tty 4, 11 Jan 24 18:18 /dev/tty11 crw--w---- 1 root tty 4, 12 Jan 25 05:42 /dev/tty12 crw-rw---- 1 jimd users 4, 13 Jul 26 1998 /dev/tty13 crw-rw---- 1 jimd users 4, 14 Oct 3 02:28 /dev/tty14 crw-rw---- 1 root tty 4, 15 Jul 26 1998 /dev/tty15 crw-rw---- 1 root tty 4, 16 Jul 26 1998 /dev/tty16 crw-rw---- 1 root tty 4, 17 Jul 26 1998 /dev/tty17 crw-rw---- 1 root tty 4, 18 Jul 26 1998 /dev/tty18 crw-rw---- 1 root tty 4, 19 Jul 26 1998 /dev/tty19 crw--w---- 1 jimd tty 4, 2 Jan 24 16:16 /dev/tty2 crw-rw---- 1 root tty 4, 20 Jul 26 1998 /dev/tty20 crw-rw---- 1 root tty 4, 21 Jul 26 1998 /dev/tty21 crw-rw---- 1 root tty 4, 22 Jul 26 1998 /dev/tty22 crw-rw---- 1 root tty 4, 23 Jul 26 1998 /dev/tty23 crw-rw---- 1 root tty 4, 24 Jan 26 22:44 /dev/tty24 crw--w---- 1 jimd tty 4, 3 Jan 23 09:09 /dev/tty3 crw------- 1 root root 4, 4 Jan 7 17:41 /dev/tty4 crw------- 1 root root 4, 5 Jan 7 17:41 /dev/tty5 crw------- 1 root root 4, 6 Jan 7 17:41 /dev/tty6 crw------- 1 root root 4, 7 Jan 7 17:41 /dev/tty7 crw------- 1 root root 4, 8 Jan 7 17:41 /dev/tty8 crw------- 1 root root 4, 9 Jan 7 17:41 /dev/tty9
... note that I define 24 of these ttys --- that's because I use twelve of them for logins and my X sessions (sometimes up to three of them) are on the next few, a copy of all 'syslogd' messages is on number 24, and I use the others with the 'open' command, or as target for redirecting 'tail -f' output and other logging operations. So I use alot more ttys than most people.
Now, the odd thing is that this is happening right after a fresh install. I almost always used custom (one of these days I'll learn to use Red Hat's "KickStart" package --- though every installation I do is different so it probably wouldn't help much).
So, I'd have to guess that somewhere you're forcing Red Hat to skip the installation of some vital package. It's hard to imagine how you're doing that. The only time I've come close to that problem is when I was experimenting with installing over FTP from a public Internet FTP site (that was very unreliable in Red Hat 5.2).
The obvious workaround is to install using their "workstation" profile and then to use the 'rpm' command to add and remove the packages to your taste after the intallation is complete and you've successfully rebooted.
One way to get a full list of packages that you hvae installed on a Red Hat (or other RPM based) system is to use the command:
... which you can redirect to a file, of course.
If just the package names aren't enough, you can use a command like:
... to get a full list of packages with short (one screen full) describtion and some info about each.
So, you could create a package list using:
rpm -aq > /tmp/plist
... then edit that to delete the names of all the packages you want to keep. You can refer to individual rpm -qi screens for packages that you don't recognize by name by simply issuing commands like:
rpm -qi zircon-1.17-16
... (where zircon was a package name I picked at random).
(If you wanted to be clever you'd make a macro in your favorite editor to pull in the description of any package on which your cursor was sitting when you invoked it. In 'vi' that would be something like:
:map S mcyypI:r!rpm -qi ^[o^[k"cD@c^M^[`c
... (where S is just any key that you don't use much in 'vi' command mode. This macro sets mark 'c' and fills paste register 'c'. All of the ^[ are literal escapes and the one ^M is a literal carriage return; those are entered in 'vi' by preceding them with a ^v [Ctrl-V]).
So, using this macro you'd move your cursor over any package that you were wondering about, hit [S] (from command mode) and this macro would extract the "info" by "querying" the RPM database and insert the results into your editing buffer.
Once you've removed all the package names that you want to keep you could use a command like:
cat /tmp/delete.list | xargs rpm -e
... to try "erasing" (un-installing) everything on the list. Here I'm assuming you make a copy of your package list file to "delete.list" and edited that. Obviously you can use any filenames you like.
This might result in a list of error messages about how some packages could not be removed due to dependencies with other packages. There should be no harm done --- so this command isn't as dangerous as it might look.
After you've removed all the packages you don't want you can select various packages that you do want to add and simply use the 'rpm -i' command to install each of them.
This would be most easily done in a shell (rather than through an editor list). To save on typing I'd probably create a couple of shell aliases like 'q' and 'i' to query and install packages. Those would look like:
alias q='rpm -qp '
alias i='rpm -i '
Of course looking through a list of almost 600 packages one could get boring. You could narrow the list a bit by generating a list of the package names on the CD and comparing that to the packages listed in your database.
To do that can use something a bit like:
rpm -qp > /tmp/pkg.list rpm -aq >> /tmp/pkg.list sort /tmp/pkg.list | uniq
... since any package that is installed will be listed twice (once from the -qp listing and once from the -aq listing) the 'sort | uniq' step will leave you with a list of packages that are NOT installed. Note: This trick only works since you have just installed all the RPMs from this CD. If you had fetched and installed some RPMs from a different CD or from an FTP site then you'd have to use a different approach to weed out the "extras"
rpm -qa | sort > /tmp/pkg.inst rpm -qp | sort > /tmp/pkg.dir comm -23 /tmp/pkg.dir /tmp/pkg.inst > /tmp/pkg.not
... this is a better technique overall. The 'comm' command finds lines "in common" between two files. It normally prints three columns of output --- but we just want the first column (the names of packages in the "dir" that are not in the list of "inst"-alled packages).
Incidentally using the command
comm -13 /tmp/pkg.dir /tmp/pkg.inst > /tmp/pkg.not
... or swapping the names of the files should give us a list of all "3rd party" packages that we've installed. That is that it results in a list of files that are installed and for which there is no ".rpm" file in the directory listing. Obviously the fact that Red Hat stores all of its package files in a single directory on its CDs is pretty convenient here. However, even when we're using S.u.S.E. CDs (with several CDs to a set and RPMs scattered in number groupings) we can easily generate a single listing of all the packages from as many directories as we like.
(You can then print a list of those, or you could be even more clever, make a /tmp/pkglist/ directory and create a series of symlinks for each of the "not installed" package). Here's a command that will do that:
cat /tmp/not.installed.txt | while read i; do ln -s /mnt/cdrom/RedHat/RPMS/$i . done
... (execute this command from your tmp/pkglist directory!).
No you can focus on these packages --- issuing your 'q' and 'i' commands. Or you could just use the 'q' alias to read more about each package --- and remove the symlinks for each that you don't want to install. Then, when you're done you could just issue a command like:
rpm -i *.rpm
... to install every package that's still listed in your temporary link farm.
Of course I've mentioned a number of other 'rpm' command tricks in previous issues. However, to save you the time searching through the back issues of LG I'll recap a couple of them here:
"Verify" all the installed packages:
... this produces a list of any file from any package that is "missing" or has changed (checking MD5 checksums, time stamps, ownership and permissions, etc). Unfortunately the output doesn't list the names of the packages from which these files came. You can get that by using:
rpm -qf $FILENAME
(for any of the files that were listed as modified or "missing" --- or for any file that was installed by any RPM on your system, for that matter).
The -qf option associates a file with the package that "owns" it.
This "Verify" compares your files to the installed RPM database. It's possible to keep back copies of your RPM database on removable media (though they will typically be too large to fit on a floppy, even compressed in most of my cases). You can use the '--dbpath' option to force the 'rpm' command to use a database in some other location (such as /mnt/ls120/backup or /mnt/zipdisk/rpmdb.bak/).
Another trick is to verify a package installation against the contents of a package file. To do this you use the command:
rpm -Vp $PACKAGE_FILENAME
... in a previous column I gave a script that would verify any of your installed packages against any RPM in the current directory. However, it occurs to me that this script was probably unnecessarily complex --- I could use the 'comm' command to simplify it somewhat.
In this case we'd generate our to lists of packages as before. We also build an "index" of the packages (matching the package names to the filenames) using a command like:
ls *.rpm | while read f; do echo $(rpm -qp $f) $f done > /tmp/pkg.index
Then we'd use a command like:
comm -12 /tmp/pkg.dir /tmp/pkg.inst \
| join - /tmp/pkg.index | cut -f 2 -d" " | xargs rpm -Vp
... this may not look simpler --- but it is much more elegant than the last version of this script that I posted. (I often forget about 'comm' and 'join' --- and I shouldn't). The 'comm' command in this case is just listing the packages in common (between our installed list and our directory listing). The 'join' command finds those lines in our index file that correspond to any of the package names we've listed (remember, package names and package FILE names don't have to match). The 'cut' command then simply "cuts" the filename from each line (that's "field" number two with a "delimiter" of a space; I could have used -e and "\t" on my echo command when I was building the "index" file to build it with 'cut's default delimiter --- though it makes no difference). Finally we pass the list of package file names to 'xargs' which builds a series of one or more 'rpm -Vp' commands by translating the arguments from its standard input into lists of arguments on the command lines it executes.
If we consolidate the code samples into a full script it would total about a dozen lines or less. (I think that's half of what it took in my previous example).
I've used a number of techniques like these to manage the large numbers of packages that I have installed on some of my systems. I use 'sh' (actually 'bash') enough and on enough different systems that I don't even keep most of these scripts --- it's usually easier to just type them on the fly then it is to remember where I have them and go fetch them.
I think I'll put this one together and forward it to the Red Hat team, to the maintainer of the Linux-Tips HOWTO, and maybe post it on my website.
(It would be nice if someone generated a list of comparable 'dpkg' commands --- since I don't have the experience with Debian, and I'd like to learn more about it).
More importantly I hope I've given some nice examples of shell scripting --- ways to use commands like 'uniq', 'comm', 'join', 'cut', 'xargs' and those ubiquitous 'while read' loops that show up in so many of my scripts.
(Actually I should note that my use of /tmp for all of this is atrocious --- since anyone using this in a script on a multi-user system would be vulnerable to horrible symlink attacks. Usually I use ~/tmp for all of these sorts of things).
It turns out that I've been asked to teach shell programming at a local community college. I've never done any professional teaching before --- and only recently did my first public lecture. It's kind of exciting for a guy with no college degree himself.
I'm working from my text terminal in the living room tonight --- so I couldn't view this site's content (it doesn't come across in 'lynx'). I often use one of the terminals in the living room while I'm watching TV, or when I have friends over. One of my friends decided to drop by and do some programming on his laptop, and Heather is working on something on her laptop. My office (with my X station) is too small and cluttered for all of us to hang out in there.
Maybe I'll remember to look at it some other time.
Mark F. Johnson Systems Administrator Maxwell Library Bridgewater State College