Output of perl debugger to file (Windows) - perl

I tried to list all the subroutines of a script with the perl debugger and put the results in an external file. But It didn't work.
My code:
perl -d -S myscript.pl > results.txt
-S = list all subroutines
-d = debug perl script
Greets,

The -S isn't supposed to be used as a command line switch. Running perl -d will start a debugger process, and one of the commands you can use there is S.
Example:
$ perl -d tmp/splithttpdconf.pl
Loading DB routines from perl5db.pl version 1.28
Editor support available.
Enter h or `h h' for help, or `man perldebug' for more help.
main::(tmp/splithttpdconf.pl:6): my $basedir = shift;
DB<1> S main::
main::BEGIN
main::debug
main::splitconf
DB<2>
In order to get the kind of output you want, you can to use the profiler module Devel::DProf instead. It'll output profiler info into a file which can be read by the dprofpp program. Here's an example to get the list of subroutines:
perl -d:DProf perlscript.pl; dprofpp -T
If you only want the subroutines within your own script, and not those loaded from other modules, add a grep to it, e.g.:
perl -d:DProf perlscript.pl; dprofpp -T | grep main::
Though for the particular question of knowing what subroutines exist in a given program, provided you use a consistent coding style it'd probably be easier to just do a grep "sub.*{" to start with.

In your home directory, create a file called .perldb with the following contents:
parse_options("NonStop=1 LineInfo=results.txt AutoTrace=1 frame=2");
And then run the command
perl -d myscript.pl
If you want to scan and list the entire subroutine's what Perl see's before it runs:
perl -MO=Deparse -f myscript.pl

Related

A change of shebang + eval leads to the perl script failure

This is a question derives from another post. Based upon the comments and answer from that post, I change the following shebang + eval into another one:
Old works version
#!/bin/perl
eval 'exec perl5 -S $0 ${1+"$#"}'
if 0;
New doesn't work version
#!/bin/sh
eval 'exec perl5 -S $0 ${1+"$#"}'
if 0;
Notice that I change #!/bin/perl to #!/bin/sh and based upon my understanding, the new version should also work because the script is treated like shell script and eval get executed and perl5 is invoked to use perl to execute the same script. However, when I actually run this, I got:
/bin/sh: -S: invalid option
Can anyone explain why this case the script is failed. Do I misunderstand something? I'm using ksh
Also this web page I found online seems suggest that my new version should work as well.
Thanks much!
From the Perl documentation:
If the #! line does not contain the word "perl" nor the word "indir", the program named after the #! is executed instead of the Perl interpreter. This is slightly bizarre, but it helps people on machines that don't do #!, because they can tell a program that their SHELL is /usr/bin/perl, and Perl will then dispatch the program to the correct interpreter for them.
So if you launch the modified version as ./script:
Your shell executes ./script
The kernel actually executes /bin/sh ./script
sh executes perl5 -S ./script
perl5 executes /bin/sh -S ./script because it sees a shebang that doesn't contain perl.
sh dies because it doesn't recognize the -S option.
And if you launch the modified version as perl5 script:
Your shell executes perl5 script
perl5 executes /bin/sh -S script because it sees a shebang that doesn't contain perl.
sh dies because it doesn't recognize the -S option.
Also this web page I found online seems suggest that my new version should work as well.
The code on that page is significantly different than the code you used. In that code, there's an explicit instruction (-x) to ignore the actual shebang line, and to look for one that contains perl later in the file (which is also missing from your code).

Perl verbose output?

Is there are a way to get Perl debug output, similar to bash -x but in Perl?
I do not need strikt or diagnose messages (they compile the code but do not print the line that the Perl interpreter executes).
Assuming you are using some kind of unix you can use the Devel::Trace perl module.
If it is not installed you can install it from CPAN like this:
sudo perl -MCPAN -e 'install Devel::Trace'
Once you have it you can run your script like this:
perl -d:Trace myscript.pl
And it will do exactly what bash -x does (note that the name of the Trace package is case sensitive).

Pass parameter to a perl script executed trough qsub

Hi would like to pass a parameter to my perl script that should be executed trough qsub.
So I run:
qsub -l nodes=node01 -v "i=500" Test.pl
While in Test.pl I try to call i parameter in several way:
use Getopt::Long;
$result = GetOptions ("i" => \$num);
open(FILE,">/data/home/FILEout.txt");
print FILE "$num\n";
print FILE "$ARGV[0]";
close(FILE);
Unfortunatelly output file of the perl script is always empty.
Do you have any suggestions? Where I'm wrong? Help please
According to all documentation I can find -v sets an environment var, so you'd use $ENV{i} to get 500. (Check your own documentation to confirm.)
If you wanted to actually pass an arg to your script, you could try using
qsub ... Test.pl -i=500
But based on my web search, that might only work for some versions of qsub. Others would require that you make a helper script (say Test.sh)
#!/bin/sh
Test.pl "-i=$i"
along with the command
qsub ... -v 'i=500' Test.sh
If qsub ... Test.pl ...args... is supported and you can change your script, the simplest solution is
qsub ... Test.pl 500
and
my ($i) = #ARGV;
I Finally get the solution that works with PBRProfessional 10.4.
There are two way to solve it:
First one is the following
echo "perl /path/to/Test.pl -i 500" | qsub -l nodes=node06
Second one is two use
qsub -l nodes=node06 -v i=500 Test.pl
and read the parameter in the Test.pl through $ENV{i}

How to check if a Perl script doesn't have any compilation errors?

I am calling many Perl scripts in my Bash script (sometimes from csh also).
At the start of the Bash script I want to put a test which checks if all the Perl scripts are devoid of any compilation errors.
One way of doing this would be to actually call the Perl script from the Bash script and grep for "compilation error" in the piped log file, but this becomes messy as different Perl scripts are called at different points in the code, so I want to do this at the very start of the Bash script.
Is there a way to check if the Perl script has no compilation error?
Beware!!
Using the below command to check compilation errors in your Perl program can be dangerous.
$ perl -c yourperlprogram
Randal has written a very nice article on this topic which you should check out
Sanity-checking your Perl code (Linux Magazine Column 91, Mar 2007)
Quoting from his article:
Probably the simplest thing we can tell is "is it valid?". For this,
we invoke perl itself, passing the compile-only switch:
perl -c ourprogram
For this operation, perl compiles the program,
but stops just short of the execution phase. This means that every
part of the program text is translated into the internal data
structure that represents the working program, but we haven't actually
executed any code. If there are any syntax errors, we're informed, and
the compilation aborts.
Actually, that's a bit of a lie. Thanks to BEGIN blocks (including
their layered-on cousin, the use directive), some Perl code may have
been executed during this theoretically safe "syntax check". For
example, if your code contains:
BEGIN { warn "Hello, world!\n" }
then you will see that message,
even during perl -c! This is somewhat surprising to people who
consider "compile only" to mean "executes no code". Consider the
code that contains:
BEGIN { system "rm", "-rf", "/" }
and you'll see the problem with
that argument. Oops.
Apart from perl -c program.pl, it's also better to find warnings using the command:
perl -w program.pl
For details see: http://www.perl.com/pub/2004/08/09/commandline.html
I use the following part of a bash func for larger perl projects :
# foreach perl app in the src/perl dir
while read -r dir ; do
echo -e "\n"
echo "start compiling $dir ..." ;
cd $product_instance_dir/src/perl/$dir ;
# run the autoloader utility
find . -name '*.pm' -exec perl -MAutoSplit -e 'autosplit($ARGV[0], $ARGV[1], 0, 1, 1)' {} \;
# foreach perl file check the syntax by setting the correct INC dirs
while read -r file ; do
perl -MCarp::Always -I `pwd` -I `pwd`/lib -wc "$file"
# run the perltidy inline
# perltidy -b "$file"
# sleep 3
ret=$? ;
test $ret -ne 0 && break 2 ;
done < <(find "." -type f \( -name "*.pl" -or -name "*.pm" \))
test $ret -ne 0 && break ;
echo "stop compiling $dir ..." ;
echo -e "\n\n"
cd $product_instance_dir ;
done < <(ls -1 "src/perl")
When you need to check errors/warnings before running but your file depends on mutliple other files you can add option -I:
perl -I /path/to/dependency/lib -c /path/to/file/to/check
Edit: from man perlrun
Directories specified by -I are prepended to the search path for modules (#INC).

How can I debug a Perl script?

When I run a Perl script, how can I debug it? For example, in ksh I add the -x flag. But how I do the same in Perl?
perl -d your_script.pl args
is how you debug Perl. It launches you into an interactive gdb-style command line debugger.
To run your script under the Perl debugger you should use the -d switch:
perl -d script.pl
But Perl is flexible. It supplies some hooks, and you may force the debugger to work as you want
So to use different debuggers you may do:
perl -d:DebugHooks::Terminal script.pl
# OR
perl -d:Trepan script.pl
Look these modules here and here.
There are several most interesting Perl modules that hook into Perl debugger internals: Devel::NYTProf and Devel::Cover
And many others.
If using an interactive debugger is OK for you, you can try perldebug.
I would also recommend using the Perl debugger.
However, since you asked about something like shell's -x have a look at the Devel::Trace module which does something similar.
Use Eclipse with EPIC: It gives you a nice IDE with debugging possibilities, including the ability to place breakpoints and the Perl Expression View for inspecting the value of variables.
If you want to do remote debugging (for CGI or if you don't want to mess output with debug command line), use this:
Given test:
use v5.14;
say 1;
say 2;
say 3;
Start a listener on whatever host and port on terminal 1 (here localhost:12345):
$ nc -v -l localhost -p 12345
For readline support use rlwrap (you can use on perl -d too):
$ rlwrap nc -v -l localhost -p 12345
And start the test on another terminal (say terminal 2):
$ PERLDB_OPTS="RemotePort=localhost:12345" perl -d test
Input/Output on terminal 1:
Connection from 127.0.0.1:42994
Loading DB routines from perl5db.pl version 1.49
Editor support available.
Enter h or 'h h' for help, or 'man perldebug' for more help.
main::(test:2): say 1;
DB<1> n
main::(test:3): say 2;
DB<1> select $DB::OUT
DB<2> n
2
main::(test:4): say 3;
DB<2> n
3
Debugged program terminated. Use q to quit or R to restart,
use o inhibit_exit to avoid stopping after program termination,
h q, h R or h o to get additional info.
DB<2>
Output on terminal 2:
1
Note the sentence if you want output on debug terminal
select $DB::OUT
If you are Vim user, install this plugin: dbg.vim which provides basic support for Perl.
The most effective debugging tool is still careful thought, coupled
with judiciously placed print statements.
Brian Kernighan, "Unix for Beginners" (1979)
(And enhancing print statements with Data::Dumper)
Note that the Perldebugger can also be invoked from the scripts shebang line, which is how I mostly use the -x flag you refer to, to debug shell scripts.
#! /usr/bin/perl -d