Shell Debugging

General | Utilities | Yak

General

The easiest way to enable shell debugging is via the -x option to the shell, which enables command tracing. The -x can either be specified on the command line, or on the first line of the shell script.

$ cat somescript
#!/bin/sh
echo foo
$ sh -x somescript
+ echo foo
foo

$ perl -i -ple 's/sh/sh -x/' somescript
$ cat somescript
#!/bin/sh -x
echo foo
$ chmod +x somescript
$ ./somescript
+ echo foo
foo

If the results of the -x option are too verbose, or if a single new command is being tested, prefix the command with echo to see what the command will be run as. This is good for seeing what complex commands look like before unleashing them on the system.

$ export FOO=/var/tmp
$ echo cd `dirname $FOO` && echo tar czf /tmp/vartmp.tgz `basename $FOO`
cd /var
tar cvzf /tmp/vartmp.tgz tmp
$ cd `dirname $FOO` && tar czf /tmp/vartmp.tgz `basename $FOO`

Login shell startup is also possible to debug. Bugs in startup script files make this necessary, or when the file a particular option is being set from needs to be located. Consult the manual for the shell in question to determine the verbose startup flag (-x as above for Bourne-based shells).

Utilities

If the input data is suspect, run it through od(1) or the newer hexdump(1) to see what characters the data contains. Unexpected characters can cause any number of problems, such as an export from a Microsoft databases containing non-printable characters, or a stray space after the shell path in /etc/passwd (prevents login, as /bin/sh is not listen in /etc/shells, but /bin/sh is).

$ echo foo | od -bc
0000000 146 157 157 012
f o o \n
0000004
$ echo foo | hexdump -bc
0000000 146 157 157 012
0000000 f o o \n
0000004

Note how echo added a newline. The following example shows UTF8 data in the file utf.

$ od -bc < utf
0000000 342 200 234 161 165 157 164 145 144 342 200 235
342 200 234 q u o t e d 342 200 235
0000014

Yak

On Unix systems one may need to know the various details of how a script is called (effective userid, command line arguments) or what environmental settings are available. The yak script can facilitate discovery of this information, by recording details of the command line arguments, environment, and standard input to a temporary file.

Example usage of the yak script follows.

LPRng Filter

The LPRng print server can run print jobs through filters. Many command line options are supplied, which yak can easily list to a file to assist with writing a proper print filter. Install yak locally, then add the following print queue definition to the printcap.

yak:
:client:mx=0:sh:lp=yak@%P
yak:
:server
:lp=/dev/null
:sd=/var/spool/lpd/%P
:if=/usr/local/bin/yak

Next, rebuild and restart LPRng, then send a test print job. Then investigate /tmp/yak.* for details on the environment.

# checkpc -f
Warning - changing ownership '/var/spool/lpd/yak' to 4/7
Warning - changing ownership '/var/spool/lpd/yak' to 4/7
# lpc reread all
# echo test | lpr -P yak
# cat /tmp/yak.*

Mac OS X StartupItems

To see what environment the Mac OS X StartupItems items are run in, install the YAK StartupItem into a StartupItems folder.

$ sudo tar xvzfC YAK.tar.gz /Library/StartupItems

Then, reboot the system, and look at the /tmp/YAK.* file to see what the environment was like.

Procmail Recipe

To debug the procmail environment, add the following to the procmail configuration file (such as .procmailrc). The c option means the following recipe should not disrupt the flow of e-mail from subsequent recipes.

:0c
| /usr/local/bin/yak