Be careful what you wish for, it may come true

After almost three years of guerilla linux advocacy at my company they finally agreed to deploy some Linux servers. One of which is to be the replacement for my beloved HP-UX ftp server.

So I’m having to port the users, data and all important scripts over from the HP-UX korn shell to the Red Hat RHEL5 korn shell.

I’ve found a couple of gotchas in doing this, not with the korn shell per se but with other seemingly innocuous command line utilities that are just a little different between HP-UX and RHEL5. So I thought I would share these with you:-


In HP-UX you can use tail -2 filename to show the last 2 lines of a file or tail +2 filename to start showing a file from line 2 through to the end.

In RHEL5 you have to use the -n option. Thus to show the last two lines of a file it is tail -n -2 filename (no need for the minus sign but it makes it more obvious to me) and tail -n +2 filename to show from line 2 onwards.

Kubuntu rather nicely puts up a warning if you don’t use the -n option saying the other method is deprecated but it still works.


In a script if you want to have in a variable the number of lines in a file in HP-UX I would do:-

NUMLINES=$(wc -l /etc/passwd | cut -d” ” -f1)

The wc command counts the umber of characters words and lines in a file and by itself produces output like

simon@constance:~$ wc /etc/passwd
   32   47 1465 /etc/passwd

Note there are leading spaces before the different counts but when you use just one of the counts such as the number of lines with -l there are no leading spaces:-

simon@constance:~$ wc -l /etc/passwd
32 /etc/passwd

So you can use the cut command with a delimiter of a space " " to get the first field from the wc -l command and thus have the number of lines. This is what cut -d" " -f1 means.

The snag with wc -l when you use it in a pipe in a script or output it to a file (i.e. whenever not run directly from the command line) it still puts the leading spaces in meaning you would need a cut -d" " -f6 or -f7 depending on how many leading spaces there are. This obviously is not usable when you don't know how many leading spaces there are.

So I use awk instead in the following way:-

NUMLINES=$(wc -l /etc/passwd | awk ' { print $1 } ')

Uses any (and all) whitespace as a single delimiter so it works regardless of how many leading spaces there might be. It's just a bit longer to type and I always think it is a lot of overhead to fire up the full power of awk just to cut out one field.

Interestingly the info page for wc on RHEL5 specifically says there is a GNU standard to ensure no leading spaced when a single count such as -l is used. So perhaps the fact this does not work in a script is in fact a bug. Certainly here onKubuntu wc -l works "as advertised" with no leading spaces even when used in a script.

cd ~ (tilde expansion)

You can use cd ~ to change to your home directory and you can use cd ~username to change to the home directory of username as extracted from /etc/passwd

However on RHEL5 (and Kubuntu) using cd ~$SOMEVAR in a script does not work as it gets executed as a literal of cd '~username'. See the following example:

simon@constance:~$ cd ~gareth
simon@constance:/home/gareth$ pwd
simon@constance:/home/gareth$ cd ~
simon@constance:~$ pwd
simon@constance:~$ USER=gareth
simon@constance:~$ cd ~$USER
bash: cd: ~gareth: No such file or directory

The only way round this I have found is to put an eval in front of the cd command

simon@constance:~$ eval cd ~$USER
simon@constance:/home/gareth$ pwd

I suspect this behaviour is related to a security feature to stop arbitrary code being executed if the contents of a variable is set by a user to something potentially malicious, a bit like SQL injection attacks.

So I have ways round the gotchas I have found so far and I only have 30 or so scripts to check for things like this and adjust but I must admit I wasn't expecting to be caught out by such subtle changes from HP-UX to Linux RHEL5.


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s