Be Careful With SHELL=/usr/local/bin/bash

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 the gettext sources thinks that configure-time checks can use your current SHELL
  • 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:

  1. 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 when WITH_STATIC_BASH is set at build-time.
  2. Use /bin/csh or shells/mksh as a temporary shell to reinstall the broken packages, e.g. gettext and any other package that depends on it.
  3. Set CONFIG_SHELL to a shell that works even without gettext (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 on libc.so.X on FreeBSD, so it should work fine too).
About these ads
This entry was posted in Computers, Free software, FreeBSD, Software and tagged , , , , . Bookmark the permalink.

5 Responses to Be Careful With SHELL=/usr/local/bin/bash

  1. adamo says:

    I am now reminded of our discussion with @mperedim on how it is inadvisable to not change the root shell.

  2. Stathis says:

    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

  3. keramida says:

    @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:

    keramida@kobe:~$ df -ht zfs
    Filesystem            Size    Used   Avail Capacity  Mounted on
    kobe                   98G    1.2G     97G     1%    /
    kobe/local            101G    3.9G     97G     4%    /usr/local
    kobe/ports             97G    622M     97G     1%    /usr/ports
    kobe/distfiles         99G    2.5G     97G     2%    /usr/ports/distfiles
    kobe/packages          98G    1.7G     97G     2%    /usr/ports/packages
    kobe/home/keramida    108G     11G     97G    11%    /home/keramida
    ...
    keramida@kobe:~$
  4. Ben Grimm says:

    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?

  5. 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.

Comments are closed.