Debugging shell scripts

[problem]

You need to debug a shell script.

[/problem]

[solution]

Most shells (zsh, ksh, bash …) can either run with a minus x (-x) option or by specifying set -x.

If you have an existing shell, that you’d like to run in debug mode – just run it like this: bash -x scriptname. Or ksh -x for korn shell.

[/solution]

[example]

You can also edit the follow and put a minus x after the interpreter line, for example:

#!/bin/ksh -x

or

#!/bin/bash -x

Debugging on the command line can be performed, simply by typing set -x. Like this:


$ set -x
+ set -x
$ date
+ date
Tue Jun 13 18:59:44 WST 2006
$ echo "hello world"
+ echo 'hello world'
hello world
$ set +x
+ set +x
$ date
Tue Jun 13 18:59:57 WST 2006

[/example]

[reference]

[tags]Debug Shell Scripts, Unix Coding School[/tags]

[/reference]

Procs started by cron

[problem]

Sometimes you want to list all processes that have been initiated by cron.

[/problem]

[solution]

To do this you first need to know the Process ID (PID) of the cron process, then to list all children of that process.

Luckily Solaris has ptree and pgrep, so it is simple.

[/solution]

[example]


ptree `pgrep cron`

Looks like Linux also has pgrep and pstree:


pstree -p `pgrep cron`

[/example]

[reference]

[tags]Process commands, Unix Coding School[/tags]

[/reference]

Proc run timings

[problem]

You want to ascertain how long your script takes to run, displaying thousands of seconds and including CPU utilization.

[/problem]

[solution]

Just use the time command.

Really simple and an excellent way to see how long your scripts take. Plus showing the anticipated load on the system.

[/solution]

[example]

[marcus@bree marcus]$ time ps
PID TTY TIME CMD
27973 pts/0 00:00:00 bash
28120 pts/0 00:00:00 ps

real 0m0.025s
user 0m0.010s
sys 0m0.020s

[/example]

[reference]

[tags], Unix Coding School[/tags]

[/reference]

Ways Display Procs

[problem]

You want to display processes, commands within the process tree.

[/problem]

[solution]

There are a number of ways to search the process tree.

Here are a few:

Show all processes for user apache.


ps -fu apache

Show all process on a given terminal (try command tty to see your own)


ps -ftpts/0

[/solution]

[example]

Show a given process


ps -fpPID

[/example]

[reference]

[tags], Unix Coding School[/tags]

[/reference]

Using FIFOs

[problem]

You want to create and use an UNIX FIFO.

[/problem]

[solution]

FIFO means first in, first out.

To create a FIFO (also called a named pipe), UNIX supplies the mknod command.

[/solution]

[example]

This is the code to generate a FIFO:


$ mknod myFIFO p

Then the resulting named pipe:


$ ls -ld myFIFO
prw-r--r-- 1 marcus adm 0 Jun 13 21:15 myFIFO

To use the FIFO, you need to have a process that is reading from it. This could be a bit of Perl, C code, etc.

A perfect way to demonstrate using FIFOs, is tail -f:


$ tail -f myFIFO

Then a test:


$ echo "
Hello there
This is a test of FIFOs
" > myFIFO

From the tail -f when now see following output:

Hello there
This is a test of FIFOs

[/example]

[reference]

– as always an excellent description on wikipedia

[/reference]

[reference]

[tags]FIFO, Named Pipes, mknod, Unix Coding School[/tags]

[/reference]

Find pattern in file

[problem]

You need to find a pattern in a file. Using regular expression.

[/problem]

[solution]

Normal command to display something in a file, is grep.


grep "pattern" filename

[/solution]

[example]

You can also display the line number it occured on (-n) and ignore case (-i):


grep -n -i "pattern" filename

Also you can match more than one pattern:


egrep "patternA|patternB" filename

To match the beginning of a line (^) or the end of line ($) – this will only match lines with this specific pattern on:


grep "^patternA$" filename

We can also use wildcards and ranges – this will match any line with PATTERN in it followed by any amount of numbers:


grep "^.*PATTERN[0-9]*$" filename

[/example]

[reference]

[tags]grep, regular expression, Unix Coding School[/tags]

[/reference]

SED extract line from file

[problem]

You want to extract a specific line number from a file.

[/problem]

[solution]

Once you have your line number – see previous post on grep, we can extract lines around the pattern.

To do this sed (stream editor) can be used to print just desired lines – this says don’t print all lines (-n); start at line 456 and finish at line 466 – print:


sed -n 456,466p filename

[/solution]

[example]

Also with sed, we can say delete specific lines – in this case remove lines 5 to 10:


sed 5,10d filename

That’s not all sed can accept patterns, as start/end identifiers:


sed /start_pattern/,/end_pattern/d filename

[/example]

[reference]

[tags], Unix Coding School[/tags]

[/reference]

SED Tips

[problem]

Following on from the last post on removing lines with sed, how do we use sed to substitute output on the fly?

[/problem]

[solution]

This says substitute occurences of PATT with REPLACE global (or all occurences).


sed 's/PATT/REPLACE/g' filename

[/solution]

[example]

So to replace all occurences of Unix with UNIX:


sed 's/Unix/UNIX/g' filename

We can also replace patterns, with variable values, like this:


sed "s/PATT/${THEVAR}/g" filename

[/example]

[reference]

[tags]SED, Unix Coding School[/tags]

[/reference]

Read File To Var

[problem]

You want to read a file into a Perl variable.

[/problem]

[solution]

Following on from the Simple PHP demo of opening and reading contents of files, here is the Perl version.

Following script takes filename as a parameter, then opens it read-only and reads contents in data variable. Then it echoes a header and footer line, with the data in the middle.

[/solution]

[example]


#!/usr/bin/perl

$filename=$ARGV[0];

open($FH,") { $data.=$_; }

close($FH);

print "################# beginning of $filename ################\n";
print "$data";
print "\n################# end of $filename ################\n";

exit(0);

__END__

Here is a run through:


$ perl readfiles.pl rhyme.txt
################# beginning of rhyme.txt ################
Mary had a little lamb,
It was always bleating.

################# end of rhyme.txt ################

[/example]

[reference]

[tags], Perl Coding School[/tags]

[/reference]

List User Login Details

[problem]

Needing to view current activity of users on the system.

[/problem]

[solution]

Most flavours of UNIX provide a number of tools, to tell you who is logged in or when they last accessed the system.

[/solution]

[example]

A favorite of mine, is who -Hu – really good for seeing who is idle, quite literally! 🙂

Also you can just run last – although beware of rolled logs. Generally in /var/adm/wtmp* on Solaris and /var/log/wtmp* on Linux.

If you want to run last against an older file (by default it just uses wtmpx or wtmp) – just specify minus f – like this: last -f /var/log/wtmp.1

Additionally the finger command will quite often show last login time.

[/example]

[reference]

[tags]who, last, finger, Unix Coding School[/tags]

[/reference]