How to debug a perl script used inside another perlscript? - perl

How to debug a perl script used inside another perlscript. We can debug both separately. Is it possible to debug in one step?
Ex:
!/user/bin/perl
my $param= 8;
my #res=\`perl extract.pl $config`;
print "The results is .... #res\n";
Similarly, can we debug the perl scripts used inside shell script?
Thanks.

You can add -d switch to the shebang line of the script you are invoking:
#!/usr/bin/perl -d

A dynamic solution:
my $dswitch = $INC{"perl5db.pl"} ? "-d" : "";
my #res=`perl $dswitch extract.pl $config`;
$INC{"perl5db.pl"} is true when you are using the debugger, and false when you are not.

The "correct" thing to do would be to change your design so you are not calling the other script through a system command. Then you would have a single debugging environment.
The best design would be to make extract.pl into a module.
You could also use the do command to import the code from the other file: do 'extract.pl'. Then the only change needed would probably be the way you pass $config in.
Either of these approaches would be quite simple to implement and would have other benefits for continued development. Maybe you have a good reason not to do it this way, but I would consider this first if you haven't already.

Just debug extract.pl passing in the value in $config. If you don't know what it is, the age-old printf will do that for you.
say "\$config='$config'";
And then do:
perl -d extract.pl 'Stuff that printed in config'.
As the two are isolated processes, the only communication is what is passed on the command line and what is printed by the called script. So the called script should be capable of being tested without the calling script. (Unless you've set up some sort of IPC or shared memory or something tricky like that.)

Related

How do I make a perl script run another perl script?

I am writing a large Perl script, which needs to utilize other existing Perl scripts. The problem is the main script needs to reference many different scripts from different folders. For example the main script would be contained in:
/perl/programs/io
It may need to run a script which is stored in:
/perl/programs/tools
Note that there are other orthogonal folders besides tools so I need to be able to access any of them on the fly.
Currently this is what I got:
my $mynumber = '../tools/convert.pl bin2dec 1011';
In theory it should move back from the io directory then enter the appropriate tool directory and call the convert.pl script while passing it the parameters.
All this does is store the string in the single quotes to $myNumber.
I like to assign the output of a command to an array so I can loop through the array to find error or other messages. For example if I'm making a zip file to email to someone I want to check to see if the zip program had any errors before I continue to make and send the email.
#msgs = `zip -f myfile.zip *.pl`; # Use backticks
You can also assign the output to a scalar:
$msg = `ls -al *.pl`; # Use backticks
To run any system command or script all you have to do is use `backticks`. From observing another programer's perl code, I misread these strange quotes for 'single quotes'.
backticks are also nice because they return the text in STDOUT to your perl script so that the output can be assigned to a variable, something I have found impossible if using system("");
The similar question answer does not work with my version of perl. The line
use IPC::System::Simple qw(system capture);
throws some errors. However just using system works, like this:
my $mynumber = system($^X, "../tools/convert.pl", 'bin2dec', '1011');
I can use the above without setting equal to something to execute scripts which return no value and are only sent arguments.
This seems to be the easiest way to do what I need to and the entire programs folder can be moved anywhere and it will still work as no parent directories above programs are used.

What does 'echo' do within a perl variable declaration?

I am working on transcribing an outdated file from perl to python and got caught up with some perl syntax.
my $jobID = `echo \$JOBID`;
chomp($jobID);
unless ($jobID) {
print "Please specify a job\n";
exit;
}
Thus far, I have been able to transcribe all of the command-line parsing extremely easily but am very fairly stuck here with what exactly this code is doing (specifically the echo within the declaration on line 1).
Within the perl script cmd-line parsing options - that enables one to set the jobID - it states that "default = $JOBID". So my assumption is that the first line in this code simply sets this default jobID until one is specified.
If this is the case why would you need to use echo within the variable default declaration? Is this good practice in perl or am I missing a larger picture?
I have tried searching low and high for this but can't seem to google ninja my way to anything useful.
Any help on the 'echo' would be greatly appreciated (or any good reads on this as well)!
This is one way to get a value from a shell variable. The backticks (`) run the shell command and give you the output. So the echo is running inside of a shell and in this case it just returns the one shell variable. A cleaner way to get this in Perl is to use %ENV like so:
my $jobID = $ENV{'JOBID'};
This also removes the need for chomp, avoids creating an extra process, and is much more efficient.
It is evaluating an environment variable named $JOBID and storing the result in $jobID, which (as duskwuff points out) is better accomplished using $ENV{JOBID}.
The backticks around the echo \$JOBID tell Perl to invoke the specified command in a subshell and return the output of the invoked command.

Perl: Calling a perl script from another

I have a perl script which calls another script. I am calling it using backticks and passing argument to that script and it works fine.
`CQPerl call_script.pl $agr1 $agr2 $arg3`;
But please suggest if there is another better way to do so. How can I check if the script errored out because of the calling script or the script that was called. How do I do that check from the calling script itself?
If you wan't to do error checking, backticks may be a wrong approach. You probably want to use the system function. See the documentation for all the details of error handling, examples included.
Perl has a number of possibilites to execute other scripts / commands:
backticks / qx{} When you want to read all the output at once after the program has terminated
exec When you wan't to continue your process as another program — never returns if succesfull
system When you are only interested in the success or failure of the command
open When you want to pipe information to or from the command
do and require Execute another Perl script here. Similar to C's #include
There are modules to do a three-way open so that you have access to STDIN, STDOUT and STDERR of the program you executed. See the apropriate parts of perlipc for advanced information.
And always use the multi-argument forms of these calls to avoid shell escaping (can be annoying and very insecure).
Check the value of the perl special variable $? to determine if there was an error.

.pm file that's loaded on every invocation of the perl interpreter?

I thought I remember reading somewhere about where perl can be configured to automatically load a certain .pm file on start up.
I know about PERL5OPT, but to my recollection, this was a specific file that would be loaded if it exists.
Is it a compile option that can be set (i.e. via Configure)?
Reading through perldoc perlrun it looks like you are looking for what is talked about in the -f option:
-f
Disable executing $Config{sitelib}/sitecustomize.pl at startup.
Perl can be built so that it by default will try to execute
$Config{sitelib}/sitecustomize.pl at startup (in a BEGIN block). This
is a hook that allows the sysadmin to customize how Perl behaves. It
can for instance be used to add entries to the #INC array to make Perl
find modules in non-standard locations.
Perl actually inserts the following code:
BEGIN {
do { local $!; -f "$Config{sitelib}/sitecustomize.pl"; }
&& do "$Config{sitelib}/sitecustomize.pl";
}
Since it is an actual do (not a require), sitecustomize.pl doesn't
need to return a true value. The code is run in package main , in its
own lexical scope. However, if the script dies, $# will not be set.
The value of $Config{sitelib} is also determined in C code and not
read from Config.pm , which is not loaded.
The code is executed very early. For example, any changes made to #INC
will show up in the output of perl -V. Of course, END blocks will be
likewise executed very late.
To determine at runtime if this capability has been compiled in your
perl, you can check the value of $Config{usesitecustomize} .
I've never done this, but it looks like if you put what you want in $Config{sitelib}/sitecustomize.pl you'll get what you are looking for.
See:
http://perldoc.perl.org/perlrun.html
http://www.nntp.perl.org/group/perl.perl5.porters/2007/10/msg129926.html
I'm confused by what you mean by "on start up". If you mean when a script / CGI / whatever is "started", then just use the module in the script:
use Data::Dumper;
Or do you mean something else?

Can I insert break point into source perl program?

I want the perl program launch debugger when some condition hit. Some other language has debug() statement supported by library, is there any similar statement in perl?
If I understand you correctly, you need to use a specific debugger variable in your code - $DB::single. Setting this to a true value in your code will cause the debugger to stop on that line.
$x = 1234;
$DB::single = 1;
enter_problematic_sub_now();
Your code will then stop at the line with $DB::single set to 1.
Of course, if you can't actually ensure that your code is running in the debugger then you have another problem entirely. You will need to run your code via perl -d as well.
Have you tried adding the -d switch to the shebang line at the top of your script? Something like
#!/usr/bin/perl -d
use strict;
use warnings;
$|=1;$\="\n";
print "Test";
It really depends exactly how it gets launched, but at least in simple cases this should start the debugger.
Edit:
You can then set a breakpoint on a specific line with a certain condition using
> b [line] [condition]
and hit
> c
to continue with running the script - the debugger will stop at the specified line when the condition is met
Well, there is something which will enable you to do something like breakpoints, but the functionality is wider: Perl Debugger.
Essentially the -d switch allows you to communicate with the perl executable, and allows the perl executable to communicate with you.
More