I've been tasked with understanding and debugging some legacy code written in Perl 5. The comments aren't great, and I have almost zero experience with the language (I'm a Python guy; some shell scripting experience). Basically, I need to understand it to the point where I can decide if it will be worth it to rewrite it in Python to match the rest of our code base and be more readable to those who aren't familiar with Perl's less obvious syntax (at least, to the uninitated...) or just leave it as is and do our best to make small changes as necessary despite having an incomplete understanding of what's going on.
Perl is being invoked to process some data from within a script in our organization's internal scripting language (which is used to interact with our proprietary hardware). The part written in the in the proprietary scripting language is similar to a shellscript in that every line sent to the interpreter will be written in the log, so while not as easy as debugging something like Python in a modern IDE, it's possible to figure out what's going on by checking the logs. But perl, as a programming language, only prints/logs what you tell it to. So as of right now, it's kind of a black box.
I looked at the Perl docs and saw that there is a command line option to launch the debugger -d, along with -Dtls to configure debugger behavior (those are the recommend options to "watch how perl executes your program"). But when I tried running that in the script, i got the following...warning? error?
Recompile perl with -DDEBUGGING to use -D switch (did you mean -d ?)
Because it's being called inside a proprietary-scripting langauge script, if this debugger is just an interactive shell, I don't think it will suit this purpose (because I can't send things to stdin while the proprietary-scripting langauge script is running). But if it's not interactive, adding a 2nd perl installation to the server for debugging wouldn't be out of the question, so if anyone has experience with this debugger mode, and options, I would appreciate some feedback about that.
I'm quite familiar with Python, so I know alot of tricks to log everything or to set up a debug environment to use the VS code debugger, but with Perl, I'm out of my comfort zone.
My question is: is there some sort of easy way (a flag or something) to call Perl in such a way where every command sent to the interpreter is written to the console/stdout/ or a logfile in the same way as a shell script? Or is there another good way to debug perl scripts (other than using the interactive debug shell)? Or do I have no better option than to take the time to go through this rather massive script and put print statements everywhere?
Thanks for reading a lengthy question.
CodePudding user response:
You can use the Perl debugger non-interactively to print each statement as they are executed. Here is an example: Consider you have a Perl script p.pl
, for example:
use feature qw(say);
use strict;
use warnings;
$DB::trace=1; # <-- turn on AutoTrace from this point..
{
my $bar = "xyz";
$bar =~ s/y//;
say "bar = $bar";
func1();
}
sub func1 {
for (1..3) {
say "1 : $_";
func2($_);
}
say "Done 1";
}
sub func2 {
my $x = shift;
my $bar = $x ** 2;
say "2: $bar";
}
Then execute p.pl
like this:
$ PERLDB_OPTS="NonStop=1 AutoTrace=0" perl -d p.pl
main::(p.pl:7): my $bar = "xyz";
main::(p.pl:7): my $bar = "xyz";
main::(p.pl:8): $bar =~ s/y//;
main::(p.pl:9): say "bar = $bar";
bar = xz
main::(p.pl:10): func1();
main::func1(p.pl:14): for (1..3) {
main::func1(p.pl:15): say "1 : $_";
1 : 1
main::func1(p.pl:16): func2($_);
main::func2(p.pl:22): my $x = shift;
main::func2(p.pl:23): my $bar = $x ** 2;
main::func2(p.pl:24): say "2: $bar";
2: 1
main::func1(p.pl:15): say "1 : $_";
1 : 2
main::func1(p.pl:16): func2($_);
main::func2(p.pl:22): my $x = shift;
main::func2(p.pl:23): my $bar = $x ** 2;
main::func2(p.pl:24): say "2: $bar";
2: 4
main::func1(p.pl:15): say "1 : $_";
1 : 3
main::func1(p.pl:16): func2($_);
main::func2(p.pl:22): my $x = shift;
main::func2(p.pl:23): my $bar = $x ** 2;
main::func2(p.pl:24): say "2: $bar";
2: 9
main::func1(p.pl:18): say "Done 1";
Done 1
CodePudding user response:
You can emulate bash -x ...
in a Perl script with the Devel::DumpTrace
module.
#!/usr/bin/perl
# demo.pl: a demonstration of Devel::DumpTrace
$a = 1;
$b = 3;
$c = 2 * $a 7 * $b;
@d = ($a, $b, $c $b);
$ perl -d:DumpTrace demo.pl
>>>>> demo.pl:3: $a:1 = 1;
>>>>> demo.pl:4: $b:3 = 3;
>>>>> demo.pl:5: $c:23 = 2 * $a:1 7 * $b:3;
>>>>> demo.pl:6: @d:(1,3,26) = ($a:1, $b:3, $c:23 $b:3);
There are settings to produce more or less output, and ways to just turn tracing on for interesting sections of code. It works best if you also have PPI
installed, but it also works without PPI.
For something lighter weight and which may already be installed on your system, also see Devel::Trace
.