Tille - I can see you, read those man pages!   Tille's Site

Troubleshooting shell scripts

This is a non-exclusive list of possible errors when executing your home brew scripts. And what to do about them, of course.

Syntax errors

Missing closing brackets

Go to the line causing the error and see what's wrong, after interpreting the error message. Example:

prompt> ./myscript
./myscript: line 5: unexpected EOF while looking for matching `)'
./myscript: line 10: syntax error: unexpected end of file

It is clear that something is wrong with brackets somewhere. Using the vim editor applying a handy colourscheme may help you to quicker find the culprit. In the example, line 5 is indeed the offending line, because the closing bracket is missing:

prompt> cat -n myscript
     1  #!/bin/bash
     2  # specific conversionscript for my html files to php
     3  LIST=$(ls *.html)
     4  for i in $LIST; do
     5          NEWNAME=$(ls $i | sed -e 's/html/php/'
     6          cat beginfile > $NEWNAME
     7          cat $i | sed -e '1,25d' | tac | sed -e '1,21d'| tac >> $NEWNAME
     8          cat endfile >> $NEWNAME
     9  done

Missing opening brackets

This gives a totally different message:

prompt> sed -n '5p' myscript
        NEWNAME=$ls $i | sed -e 's/html/php/')
		 ^ here should be a (

prompt> ./myscript
./myscript: line 5: syntax error near unexpected token `'s/html/php/')'
./myscript: line 5: `   NEWNAME=$ls $i | sed -e 's/html/php/')'

Missing quotes

If you forget opening or closing quotes, you will see this message for the line containing the error:

./example.sh[11]: syntax error at line 19 : `'' unmatched

Missing keywords

This happens when you leave out the ending done statement:

prompt> ./myscript
./myscript: line 9: syntax error: unexpected end of file

Similar errors may also result in syntax error near unexpected token.

Wrong assignment

prompt> sed -n '5p' myscript
        NEWNAME=ls $i | sed -e 's/html/php/'
		^ missing $(		    ^ missing )

prompt> ./myscript
./myscript: ./index1.html: Permission denied
./myscript: $NEWNAME: ambiguous redirect
./myscript: $NEWNAME: ambiguous redirect
<--output truncated-->

Other wrong combination:

prompt> sed -n '5p' myscript
	$NEWNAME=$(ls $i | sed -e 's/html/php/')
	^ too much $$

prompt> ./myscript
./myscript: =index1.php: command not found
./myscript: $NEWNAME: ambiguous redirect
./myscript: $NEWNAME: ambiguous redirect
<--output truncated-->

No assignment

Comment out the assignment for the LIST variable by means of a test. When executed, the script does noting at all, not even an error occurs.

That may be different in other cases, of course.

Syntax errors in invoked commands

In the next example, we forgot to end the search and replace expression for sed, see what happens now:

prompt> sed -n '5p' myscript
        NEWNAME=$(ls $i | sed -e 's/html/php')
					    ^ missing slash	

prompt> ./myscript
sed: -e expression #1, char 10: Unterminated `s' command
./myscript: $NEWNAME: ambiguous redirect
./myscript: $NEWNAME: ambiguous redirect
<--output truncated-->

Problems with conditionals using square brackets

There needs to be a space between the brackets and the expression enclosed, else two errors can be generated. When missing the first space, you'll see something like this:

prompt> [$VAR == "value" ] && echo "$VAR is set"
bash: [value: command not found

You'll see the same error if you leave out spaces at the beginning and at the end of the conditional test. If you leave out only the last space, this happens:

prompt> [ $VAR == "value"] && echo "$VAR is set"
[: missing `]'

Use the -x option to bash

Invoking your script with the bash -x yourscript command causes bash to print more information about what it is doing.

prompt> bash -x myscript
++ ls index1.html index2.html index3.html index.html
+ LIST=index1.html
++ ls index1.html
++ sed -e s/html/php/
+ NEWNAME=index1.php
+ cat beginfile
+ cat index1.html
+ sed -e 1,25d
+ tac
+ sed -e 1,21d
+ tac
+ cat endfile
<--output truncated-->

This may or may not give you clues for debugging your script, read carefully.

Using echo commands

Adding some echo commands here and there at strategic places - e.g. just after you assigned a value to a variable, after issuing a tricky command and such - provides with useful information and sureness about what is going on:

# specific conversionscript for my html files to php
LIST=$(ls *.html)
for i in $LIST; do
        echo "This is the value for i now: $i"
        NEWNAME=$(ls $i | sed -e 's/html/php/')
        echo "NEWNAME is now $NEWNAME"
        cat beginfile > $NEWNAME

# Next we use quotes and backticks.  backtick and dollar signs retain their
# meaning when inside double quotes.
# This is all just to see the new file growing.
        echo "`ls -l $NEWNAME`"
        cat $i | sed -e '1,25d' | tac | sed -e '1,21d'| tac >> $NEWNAME
        echo "`ls -l $NEWNAME`"
        cat endfile >> $NEWNAME
        echo "`ls -l $NEWNAME`"
© 1995-2010 Machtelt Garrels - tille - Powered by vIm - Best viewed with your eyes - Validated by W3C - Last update 20100511