Is there any way to debug a bash script? E.g something that prints a sort of execution log like "calling line 1", "calling line 2" etc.
sh -x script [arg1 ...]
bash -x script [arg1 ...]
These give you a trace of what is being executed. (See also 'Clarification' near the bottom of the answer.)
Sometimes, you need to control the debugging within the script. In that case, as Cheeto reminded me, you can use:
set -x
This turns debugging on. You can then turn it off again with:
set +x
Also, shells generally provide options '-n
' for 'no execution' and '-v
' for 'verbose' mode; you can use these in combination to see whether the shell thinks it could execute your script - occasionally useful if you have an unbalanced quote somewhere.
There is contention that the '-x
' option in Bash is different from other shells (see the comments). The Bash Manual says:
-x
Print a trace of simple commands, for commands, case commands, select commands, and arithmetic for commands and their arguments or associated word lists after they are expanded and before they are executed. The value of the PS4 variable is expanded and the resultant value is printed before the command and its expanded arguments.
That much does not seem to indicate different behaviour at all. I don't see any other relevant references to '-x
' in the manual. It does not describe differences in the startup sequence.
Clarification: On systems such as a typical Linux box, where '/bin/sh
' is a symlink to '/bin/bash
' (or to any Bash executable), the two command lines achieve the identical effect. On other systems (for example, Solaris), /bin/sh
is not Bash, and the two command lines would give (slightly) different results; most notably, '/bin/sh
' would be confused by constructs in Bash that it does not recognize at all. When invoked by name like this, the 'shebang' line ('#!/bin/bash
' vs '#!/bin/sh
') at the start of the file has no effect on how the contents are interpreted. I've not found anything in the Bash Manual that indicates different behaviour from Bash depending on whether it is invoked as 'sh' or 'bash'.
I've used the following methods to debug my script.
set -e
makes the script stop immediately if any external program returns a non-zero exit status. This is useful if your script attempts to handle all error cases and where a failure to do so should be trapped.
set -x
was mentioned above and is certainly the most useful of all the debugging methods.
set -n
might also be useful if you want to check your script for syntax errors.
strace
is also useful to see what's going on. Especially useful if you haven't written the script yourself.
Some assorted comments:
http://bash-hackers.org/wiki/doku.php/scripting/debuggingtips