One of the things I often do on FreeBSD machines is to install shells/mksh or shells/bash and work most of the time with a bourne-compatible shell.
The default /bin/csh shell is mostly ok for short interactive sessions, but I can’t stand its command-syntax for semi-complex looping, iteration or other combined commands. So install bash or mksh and I launch one of them from my login prompt, using something like:
csh# env SHELL=/usr/local/bin/bash /usr/local/bin/bash -l bash#
There’s a minor catch with SHELL being set to /usr/local/bin/bash though. The default binary of bash is dynamically linked, and it depends on libintl.so.XXX from the devel/gettext package. This means that if you happen to run a package update command that rebuilds gettext from source, there is a small period between the time the old gettext is uninstalled and the new version is installed that the following are all true:
- Your current
SHELLpoints to bash - The bash binary needs
libintl.so.XXXto run, so it (temporarily) fails with a runtime linker error - The “
configure” script of thegettextsources thinks that configure-time checks can use your currentSHELL - Boom!…
So you cannot upgrade gettext, and your current shell needs it to run. Any other packages that depend on gettext cannot be upgraded either. Not a very nice corner to paint yourself into…
There are, however, at least three options to recover from a mess like this:
- Run a shell that is statically linked version of bash. The
shells/bashport of FreeBSD can build a statically linked version of the shell whenWITH_STATIC_BASHis set at build-time. - Use
/bin/cshorshells/mkshas a temporary shell to reinstall the broken packages, e.g.gettextand any other package that depends on it. - Set
CONFIG_SHELLto a shell that works even withoutgettext(the/bin/shshell of FreeBSD should work fine for this), or to one that has minimal library dependencies (the/usr/local/bin/mkshshell only depends onlibc.so.Xon FreeBSD, so it should work fine too).
I am now reminded of our discussion with @mperedim on how it is inadvisable to not change the root shell.
On a more general note, I like the way Solaris handles system updates. Creating a clone of the root filesystem and updating the clone, with the ability to rollback to your last good working snapshot. This solves or rather it avoids a whole class of problems.
I hope BSDs and Linux will eventually provide something similar (no, chroots aren’t good enough :P). FreeBSD has zfs so it should be doable in principle.
Cheers
@adamo: That’s I don’t actually change the shell of root in /etc/master.passwd but I exec the bash/ksh version. I was just amused by the interaction of exec bash and gettext upgrades. Now that I have understood what’s going on, I’m going to be careful when rebuilding ports from source.
@stathis: One of the things I want to experiment with is zfs snapshots before major upgrades. That’s why my laptop now runs with a ZFS root filesystem and the root fs is a zfs dataset of its own:
I have upgraded gettext several times (even recurisvely, when /usr/ports/UPDATING mandated it) and I can’t say that I have ever come across this problem. The difference may be that I have bash as a shell in /etc/passwd (on the toor account, not the root account, of course), so it’s not launched from .cshrc, but invoked directly on logon. Could it be that the way you invoke bash exposes it to this specific problem?
Basically, that is why you NEVER change the csh shell of the root account and do all your updates WITHOUT sudo (Ubuntu haters) when you do such trivial tasks as updates! An su will also save you some time because:
1. it is 2 characters smaller :-P
2. You don’t have to type it again and again when performing portsnap updates and portupgrades e.t.c.