One of Perl's better-kept secrets is its built-in debugger, a powerful utility that allows developers to rapidly track down errors in their Perl scripts. This article introduces you to the Perl debugger, explaining how to use it to step through scripts, set breakpoints, inspect variables and objects, watch expressions and perform stack traces.
It's important to note that this line has not yet been executed; rather, it is the line that will be executed next. This is a very common mistake made by newbies to the Perl debugger, so be warned!
In order to execute the next line of the script, type "s".
main::(mailer.pl:6): unless($ARGV[0]) main::(mailer.pl:7): { DB<1> s main::(mailer.pl:12): my $id = $ARGV[0]; DB<1> s main::(mailer.pl:16): my $dbh = DBI->connect("DBI:mysql:database=db198;host=localhost", "root", DBI->"secret", {'RaiseError' => 1}) or die ("Cannot connect to database"); DB<1> s DBI::connect(/usr/lib/perl5/vendor_perl/5.8.0/i386-linux-thread-multi/DBI.pm :442): 442: my $class = shift; DB<1> s DBI::connect(/usr/lib/perl5/vendor_perl/5.8.0/i386-linux-thread-multi/DBI.pm :443): 443: my($dsn, $user, $pass, $attr, $old_driver) = @_; DB<1> s DBI::connect(/usr/lib/perl5/vendor_perl/5.8.0/i386-linux-thread-multi/DBI.pm :444): 444: my $driver; DB<1> s DBI::connect(/usr/lib/perl5/vendor_perl/5.8.0/i386-linux-thread-multi/DBI.pm :445): 445: my $dbh; DB<1> s DBI::connect(/usr/lib/perl5/vendor_perl/5.8.0/i386-linux-thread-multi/DBI.pm :448): 448: ($old_driver, $attr) = ($attr, $old_driver) if $attr and !ref($attr); DB<1> s
The "s" command steps through each line of the script, ducking into subroutines as and when needed - as clearly illustrated in the snippet above (note how the status message next to each line of the script changes to display which subroutine the script is currently executing).
If you'd like to "step over" subroutines, you can use the "n" command instead, which executes subroutines as a single step. This is useful if you have a large number of subroutine calls in your code and are more interested in general program flow than specific or isolated problems.
main::(mailer.pl:6): unless($ARGV[0]) main::(mailer.pl:7): { DB<1> n main::(mailer.pl:12): my $id = $ARGV[0]; DB<1> n main::(mailer.pl:16): my $dbh = DBI->connect("DBI:mysql:database=test;host=localhost", "root", "", {'RaiseError' => 1}) or die ("Cannot connect to database"); DB<1> n nmain::(mailer.pl:19): my $sendmail = "/usr/sbin/sendmail -t"; DB<1> main::(mailer.pl:20): my $reply_to = "Reply-to: foo\@bar.org"; DB<1> n main::(mailer.pl:21): my $subject = "Subject: FOOBAR"; DB<1> n main::(mailer.pl:22): my $content = "Hello and how are you doing? This is the message body";
You can hit the "Enter" key repeatedly to repeat the last "n" or "s" command.
You can use the "l" command you learnt on the previous page to view the contents of a subroutine, simply by specifying the package/subroutine name after the "l" command.
DB<11> l DBI::connect Switching to file '/usr/lib/perl5/vendor_perl/5.8.0/i386-linux-thread-multi/DBI.pm'. 441 sub connect { 442: my $class = shift; 443: my($dsn, $user, $pass, $attr, $old_driver) = @_; 444: my $driver; 445: my $dbh; 446 447 # switch $old_driver<->$attr if called in old style 448: ($old_driver, $attr) = ($attr, $old_driver) if $attr and !ref($attr); 449 450: my $connect_meth = (ref $attr) ? $attr->{dbi_connect_method} : undef;
If you're currently inside a subroutine and would like to execute all its remaining statements until it generates a return value, simply use the "r" command. The debugger will continue through the subroutine, and print the return value from the subroutine once it finishes execution.
DB<1> s DBI::connect(/usr/lib/perl5/vendor_perl/5.8.0/i386-linux-thread-multi/DBI.pm :443): 443: my($dsn, $user, $pass, $attr, $old_driver) = @_; DB<1> r scalar context return from DBI::connect: empty hash main::(mailer.pl:19): my $sendmail = "/usr/sbin/sendmail -t";
{mospagebreak title=Digging Deeper}
One of the Perl debugger's most oft-used features is its ability to X-ray any variable or object and display its contents. This is accomplised via the "x" command, as illustrated in the following example:
DB<7> @friends = qw(Rachel Ross Joey Monica Chandler Phoebe);
The "X" command displays a complete list of all the variables the Perl script knows about, including environment and shell variables, special Perl built-ins and variables local to the script itself.