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
SHELL
points to bash - The bash binary needs
libintl.so.XXX
to run, so it (temporarily) fails with a runtime linker error - The “
configure
” script of thegettext
sources 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/bash
port of FreeBSD can build a statically linked version of the shell whenWITH_STATIC_BASH
is set at build-time. - Use
/bin/csh
orshells/mksh
as a temporary shell to reinstall the broken packages, e.g.gettext
and any other package that depends on it. - Set
CONFIG_SHELL
to a shell that works even withoutgettext
(the/bin/sh
shell of FreeBSD should work fine for this), or to one that has minimal library dependencies (the/usr/local/bin/mksh
shell only depends onlibc.so.X
on 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.