Using The Perl Debugger - Step By Step (
Page 2 of 6 )
When you first enter the debugger, you're placed at the first executable line
of your Perl script.
$ perl -d mailer.pl 877
Loading DB routines from perl5db.pl
version 1.19
Editor support available.
Enter h or `h h' for help, or `man perldebug' for more help.
main::(mailer.pl:6): unless($ARGV[0])
main::(mailer.pl:7):
{
DB<1>
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);
DB<8> x @friends
0 'Rachel'
1 'Ross'
2 'Joey'
3
'Monica'
4 'Chandler'
5 'Phoebe
You can use the "p" command to print the value of any variable,
DB<4> p $sendmail
/usr/sbin/sendmail -t
DB<7> $movie="Star Wars"
DB<8> p $movie
Star Wars
or the "V" command, followed by a package name, to view all the variables in
that package.
DB<32> V DBI
%DBI_methods = (
'db' =>
HASH(0x81e292c)
'CLEAR' => HASH(0x8281ff8)
'O' => 4
'DESTROY'
=> undef
'EXISTS' => HASH(0x8281ff8)
-> REUSED_ADDRESS
'FETCH'
=> HASH(0x808b198)
'O' => 1028
'FIRSTKEY' =>
HASH(0x8281ff8)
-> REUSED_ADDRESS
'NEXTKEY' =>
HASH(0x8281ff8)
-> REUSED_ADDRESS
'STORE' => HASH(0x8284968)
'O'
=> 1040
'_not_impl' => undef
'begin_work' =>
HASH(0x83155a8)
'O' => 1024
'U' => ARRAY(0x831556c)
0 1
1
2
2 '[ \\%attr ]'
'column_info' => HASH(0x81e2680)
'O' =>
512
'U' => ARRAY(0x81e2644)
0 1
1 6
2 '$catalog, $schema, $table,
$column [, \\%attr ]'
'commit' => HASH(0x8315608)
'O' => 1152
'U'
=> ARRAY(0x83155d8)
0 1
1 1
...
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.
DB<32> X
FileHandle(STDIN) => fileno(0)
$^V =
"\cE\cH\c@"
$2 = ''
$1 = 'main'
$movie = 'Star Wars'
$^WARNING_BITS
= "\c@\c@\c@\c@\c@\c@\c@\c@\c@\c@\c@\c@"
$< = 515
FileHandle(stdin)
=> fileno(0)
@ARGV = (
0 'ueruir'
)
@INC = (
0
'/usr/lib/perl5/5.8.0/i386-linux-thread-multi'
1 '/usr/lib/perl5/5.8.0'
2
'/usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi'
3
'/usr/lib/perl5/site_perl/5.8.0'
4 '/usr/lib/perl5/site_perl'
5
'/usr/lib/perl5/vendor_perl/5.8.0/i386-linux-thread-multi'
6
'/usr/lib/perl5/vendor_perl/5.8.0'
7 '/usr/lib/perl5/vendor_perl'
8
'.'
)
%INC = (
'AutoLoader.pm' =>
'/usr/lib/perl5/5.8.0/AutoLoader.pm'
'Carp.pm' =>
'/usr/lib/perl5/5.8.0/Carp.pm'
'Carp/Heavy.pm' =>
'/usr/lib/perl5/5.8.0/Carp/Heavy.pm'
'Config.pm' =>
'/usr/lib/perl5/5.8.0/i386-linux-thread-multi/Config.pm'
'DBD/mysql.pm' =>
'/usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi/DBD/mysql.pm'
...
You can also use the "M" command to display a list of all loaded modules
(together with version numbers),
DB<32> M
'AutoLoader.pm' => '5.59 from
/usr/lib/perl5/5.8.0/AutoLoader.pm'
'Carp.pm' => '1.01 from
/usr/lib/perl5/5.8.0/Carp.pm' 'Carp/Heavy.pm' =>
'/usr/lib/perl5/5.8.0/Carp/Heavy.pm'
'Config.pm' =>
'/usr/lib/perl5/5.8.0/i386-linux-thread-multi/Config.pm'
'DBD/mysql.pm' =>
'2.0416 from
/usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi/DBD/mysql.pm'
'DBI.pm'
=> '1.30 from
/usr/lib/perl5/vendor_perl/5.8.0/i386-linux-thread-multi/DBI.pm'
'DynaLoader.pm'
=> '1.04 from
/usr/lib/perl5/5.8.0/i386-linux-thread-multi/DynaLoader.pm'
'Exporter.pm'
=> '5.566 from /usr/lib/perl5/5.8.0/Exporter.pm' 'Exporter/Heavy.pm' =>
'5.566 from /usr/lib/perl5/5.8.0/Exporter/Heavy.pm'
'Term/Cap.pm' => '1.07
from /usr/lib/perl5/5.8.0/Term/Cap.pm' 'Term/ReadLine.pm' => '1.00 from
/usr/lib/perl5/5.8.0/Term/ReadLine.pm'
'dumpvar.pl' =>
'/usr/lib/perl5/5.8.0/dumpvar.pl'
'perl5db.pl' => '1.19 from
/usr/lib/perl5/5.8.0/perl5db.pl' 'strict.pm' => '1.02 from
/usr/lib/perl5/5.8.0/strict.pm' 'vars.pm' => '1.01 from
/usr/lib/perl5/5.8.0/vars.pm' 'warnings.pm' => '1.00 from
/usr/lib/perl5/5.8.0/warnings.pm' 'warnings/register.pm' => '1.00 from
/usr/lib/perl5/5.8.0/warnings/register.pm'
and the "m" command, followed by a package name, to view the methods
available in that package.
DB<33> m
DBI
CLONE
_clone_dbis
_dbtype_names
_debug_dispatch
_rebless
_rebless_dbtype_subclass
_set_isa
_setup_driver
available_drivers
bootstrap
carp
confess
connect
connect_cached
connect_test_perf
constant
croak
data_sources
dbi_profile
via
Exporter: export_ok_tags
via Exporter: export_tags
via Exporter:
export_to_level
via DynaLoader: AUTOLOAD
via DynaLoader:
boot_DynaLoader
via DynaLoader: dl_install_xsub
...
Finally, you can obtain a complete list of subroutines in your script (and
all its linked packages) with the "S" command,
DB<35> S
AutoLoader::AUTOLOAD
AutoLoader::BEGIN
AutoLoader::__ANON__[/usr/lib/perl5/5.8.0/AutoLoader.pm:96]
AutoLoader::import
AutoLoader::unimport
Carp::BEGIN
Carp::caller_info
Carp::carp
Carp::cluck
Carp::confess
Carp::croak
Carp::export_fail
Carp::format_arg
Carp::get_status
DBD::mysql::AUTOLOAD
DBD::mysql::BEGIN
DBD::mysql::_OdbcParse
DBD::mysql::_OdbcParseHost
DBD::mysql::db::ANSI2db
DBD::mysql::db::BEGIN
DBD::mysql::db::_SelectDB
DBD::mysql::db::admin
DBI::BEGIN
DBI::CLONE
DBI::DBI_tie::STORE
...
and filter that list down to a specific subset by adding a search
pattern.
DB<35> S
connect
DBD::_::db::disconnect
DBD::_::dr::connect
DBD::_::dr::connect_cached
DBD::_::dr::disconnect_all
DBD::mysql::dr::connect
DBI::connect
DBI::connect_cached
DBI::connect_test_perf
DBI::disconnect
DBI::disconnect_all