Wednesday, December 5, 2012

Writing Portable Shell Scripts

Why write portable scripts?
Our aim is to write maintainable scripts that will run on any version of Unix or Linux. Bash is getting popular these days due to linux and it is not uncommon to see bash-only features being used. Such scripts are unportable. Non-portable scripts inculcate bad scripting habits and also cause practical problems on production systems.

For what shells do we target our scripts?
We try and write scripts that will run on old sh, ksh and bash. This is the Bourne shell family. All but the simplest scripts will fail to run reliably on csh etc.

What is /bin/sh?
This is very hard to answer. Usually it is the old Bourne shell. On many systems, it will just start bash or some other shell. On linux it commonly starts bash with some additional parameters to get bash to simulate the old Bourne shell.

What is the POSIX shell?
Most systems have one shell that is called the POSIX shell. On many systems this is /bin/sh or is found in an altogether different location like /usr/xpg4/bin/sh on Solaris.

Should our scripts be fully portable or POSIX compliant?
There is a major decision to be made - whether to aim for old sh or for the POSIX shell. It is usually not possible to get a complex script to work on both. The reason is that old sh is not well documented and isn't very POSIX compliant. It also doesn't have many important features that are a mainstay of modern shells. On the other hand, POSIX compliant scripts will run on any version of bash and ksh but may fail on plain old sh.

What versions of the unix shell are available?
bash 3.0, ksh88 and ksh93 are the most common. There are literally dozens of available shells such as dash, tcsh, ash etc.

How to know what shell you are on?

echo $SHELL (or echo $0 from within scripts) does this.

It is very tricky to discover the shell version and here are some examples:

[xgt@m-net ~]$ bash --version
GNU bash, version 3.1.17(0)-release (i386-portbld-freebsd6.2)
Copyright (C) 2005 Free Software Foundation, Inc.

$ echo $KSH_VERSION
@(#)PD KSH v5.2.14.2 99/07/13.2

# /usr/ccs/bin/what /usr/bin/ksh
/usr/bin/ksh:
        Version M-11/16/88i
        SunOS 5.10 Generic 118872-04 Aug 2006

Can we check for or modify the behaviour of the shell?
Most shells have a command line flag that gets them to behave in a particular way, e.g. to behave POSIX compliant or masquerade as another shell.
We can force POSIX compliance in bash by starting it with --posix or starting your script file with the following :
/bin/bash --posix

No comments:

Post a Comment