18 December 2007

The bash problem

If you use bash as a login shell you might have had the problem of it getting broken and then being unable to login. Now that's a problem! I've burnt myself on this a couple of times. But, in both cases it was not a big deal to fix. (In one case, though, I was locked out over the weekend until I could get to the box.) This is more of a problem in some operating systems (like FreeBSD) where bash is not part of the base system. In that respect, it's a risk worth having because of FreeBSD's great separation of the base system and third party software -- and the ability to easily update that software. And, bash is just a great shell.

As long as you've got console, it's easy enough to fix. You can just drop into (or boot to) single user mode and then run 'chsh [<username>]'. If you don't have console and all of your network enabled user accounts use bash you've got a real problem.

So, how to prevent this once and for all? I've got several suggestions. 1) Have a back-up account that uses a shell from the base system. This is simple and effective. But, having to remember another user name and having to remember and/or update another password is not ideal. 2) Use a 'toor'-like system on your own user account. This is interesting. I tested this out and it works alright. Just reverse your username (e.g., 'kace' -> 'ecak'), create that account, then use 'vipw' to change the uid on that account to your original uid and the home directory to your home directory. But, make this other username use a base system shell. This is really nearly the same as solution 1), except you'll not need to remember a new user name.

Finally, the one I like best: no new account, no second password: 3) Change your login shell to '/bin/csh' then add this code to the ".login" file in your home directory:

if ( { bash -c 'echo blah > /dev/null' } ) then
    exec bash -l
else
    echo '=== bash broken ==='
endif

This simply tests bash every time you login and then replaces csh with a bash login shell as long as it's working. Simple and effective. It may seem like too much overhead, but it's not really. This isn't some system task that will be repeated hundreds of times a day. You don't actually login that much. The small cost in computer time of running csh and then bash and then finally bash once more is a trifle in comparison to the human time that this measure may one day save you.

I first tested and implemented this solution with '/bin/sh' and it worked, though the code is slightly different and it goes into the ".profile" file. But, upon reflection that's a bad idea. 'sh' is a little faster than 'csh', but using 'sh' requires that you have a ".bash_profile" or a ".bash_login" file in your home directory. If you don't, or something happens to them, then bash will read ".profile" and you'll be in a loop, re-executing bash over and over. Ack! Let's just solve the problem instead of creating new, more interesting ones. :)

Update:

If you want to run any tests on these ideas, you may want to "break" bash or create and assign yourself a broken shell. (Be careful! Don't lock yourself out! Test on a box that you have console access to until you are satisfied.) One quick and easy way to break bash is this: "chmod -x /usr/local/bin/bash" (or your path to bash). On the other hand, the system seems to handle a non-executable shell slightly differently from a broken shell. For testing purposes it's broken enough I think. :) But, if you want to be a stickler, a more realistic way to emulate a broken shell might be to assign yourself as a login shell a utility that always returns a non-zero exit status, perhaps '/usr/bin/false'. (And, you'll have to put it in '/etc/shells/ first.) ... In particular, something like "ssh problem-box '/bin/sh' " may seem to work while your login shell is not broken, but, in fact, the command '/bin/sh' is being passed to your login shell, and if it's broken that won't work.

Labels:

11 December 2007

Stupid printing tricks

Why do so many people send Adobe PDF files? Especially if it's just text. Why not just send text? Why should I have to open another application to read your precious newsletter?!

Ugh. Anyway, sometimes PDF's are useful. Maybe they've got maps and directions or whatever. Then maybe you'll want to print them out. Well, I don't know what's going on with my Adobe Reader (port "print/acroread7"). I know I've printed from it in the past. But, today it's telling me that "/usr/bin/lp" doesn't exist. It bloody well does exist. It doesn't work though, :) , I'm using CUPS and a network printer, so what I want is to use "/usr/local/bin/lp" -- but, sure enough, old acroread is telling me it doesn't exist either. It does.

OK, I'm not going to argue with a broken application. I need a hard copy, fast. So, on to the stupid trick. When you choose "Print" and get that dialog box, down near the bottom is the "Print to file" check box. Check that, choose a filename, click OK, then just pipe the resulting file to "/usr/local/bin/lp" (in my case, anyway) and you're in business. My actual command was something like this: "cat outfile.ps | /usr/local/bin/lp" and Adobe Reader had appended the '.ps' itself. (Not sure if this trick will work with a non-PostScript printer. Might need a little Ghostscript "glue".)

Labels: