How do I restrict Perl debugger output to lines in my own script? - perl

I'm running the debugger in noninteractive mode, with the output written to a file. I want to print out each line of my Perl script as it executes, but only lines in the script itself. I don't want to see the library code (File::Basename, Exporter::import, etc.) that the script calls. This seems like the sort of thing that should be easy to do, but the documentation for perldebug only discusses limiting the depth for dumping structures. Is what I want possible, and if so, how?
Note that I'm executing my program as follows:
PERLDB_OPTS="LineInfo=temp.txt NonStop=1 AutoTrace=1 frame=2" perl -dS myprog.pl arg0 arg1

By default, Devel::DumpTrace doesn't step into system modules, and you can exercise fine control over what modules the debugger will step into (it's not easy, but it's possible). Something like
DUMPTRACE_FH=temp.txt perl -d:DumpTrace=quiet myprog.pl
would be similar to what you're apparently trying to do.
Devel::DumpTrace also does a lot more processing on each line -- figuring out variable values and including them in the output -- so it may be overkill and run a lot slower than perl -dS ...
(Crikey, that's now two plugs for Devel::DumpTrace this week!)

Are you talking about not wanting to step through functions outside of your own program? For that, you want to use n instead of s.
From perldebug:
s [expr] Single step. Executes until the beginning of another
statement, descending into subroutine calls. If an
expression is supplied that includes function calls, it too
will be singleā€stepped.
n [expr] Next. Executes over subroutine calls, until the beginning
of the next statement. If an expression is supplied that
includes function calls, those functions will be executed
with stops before each statement.

Related

How can I have one perl script call another and get the return results?

How can I have one perl script call another perl script and get the return results?
I have perl Script B, which does a lot of database work, prints out nothing, and simply exits with a 0 or a 3.
So I would like perl Script A call Script B and get its results. But when I call:
my $result = system("perl importOrig.pl filename=$filename");
or
my $result = system("/usr/bin/perl /var/www/cgi-bin/importOrig.pl filename=$filename");
I get back a -1, and Script B is never called.
I have debugged Script B, and when called manually there are no glitches.
So obviously I am making an error in my call above, and not sure what it is.
There are many things to consider.
Zeroth, there's the perlipc docs for InterProcess Communication. What's the value in the error variable $!?
First, use $^X, which is the path to the perl you are executing. Since subprocesses inherit your environment, you want to use the same perl so it doesn't confuse itself with PERL5LIB and so on.
system("$^X /var/www/cgi-bin/importOrig.pl filename=$filename")
Second, CGI programs tend to expect particular environment variables to be set, such as REQUEST_METHOD. Calling them as normal command-line programs often leaves out those things. Try running the program from the command line to see how it complains. Check that it gets the environment it wants. You might also check the permissions of the program to see if you (or whatever user runs the calling program) are allowed to read it (or its directory, etc). You say there are no glitches, so maybe that's not your particular problem. But, do the two environments match in all the ways they should?
Third, consider making the second program a modulino. You could run it normally as a script from the command line, but you could also load it as a Perl library and use its features directly. This obviates all the IPC stuff. You could even fork so that stuff runs concurrently.

Set arbitrary breakpoint in debugger

I have been using the perl interactive debugger (basically perl -d script)
I have a script that has quite a lot of modules imported and I need to debug a problem.
What I do is start the debugger and go over lines, stepping into where necessary.
But this is tedious as I need to step into many lines of code and function calls.
Question: Let's say that after going over the lines of code I eventually step into function A::B::C::foo() of some module where is the problem I am debugging.
Is there a way to set a break point in that function in the beginning of the debugging session so that I jump there directly instead of going over the code line by line until I reach there?
I know that I can add a break point in the same file my debugger is currently but how can I add a breakpoint in a line that is outside of the debugger's scope at this point (to some arbitrary file/module that eventually the debugger would have reached)?
Note:
Just to clarify: It is not like A::B::C::foo() is in line X of the script. It is eventually called after going down the call chain of a lot other functions in many modules
You can set a breakpoint to a subroutine with the documented b sub syntax. In this case, just use
b A::B::C::foo
c
You may set a break point by defining file name and then line number
b YourModule.pm:line_number
where line number is inside the module function you want to break at.
You can even put a breakpoint on a sub that hasn't been loaded/defined yet using the postpone option:
b postpone Name::Of::Sub::Yet::To::Be::Created

how to read texts on the terminal inside perl script

Is there any way to capture the texts on termianl screen inside a perl script. I know there are some functions like system,exec,backticks but the problem is that they execute commands FROM the script.For ex:- in terminal i write cd/ (or) ls,and after that i run my perl script which will read what was written on termianl screen(in this case, scipt will capture cd/ (or) ls-whichever was given to termianl). I came with one solution that by passing the commands which you wrote on termianl as a command line arguments to the script,but any other way???
Like this maybe:
history | perl -ne 'print $_'
As I understand it, in a situation where you've typed some stuff into a terminal like this:
[tai#littlerobot ~] echo "Hello"
Hello
[tai#littlerobot ~] perl myscript.pl
You want myscript.pl to be able to access the echo "Hello" part, and possibly also the Hello that was that command's output.
Perl does not provide such a feature. No programming language does or can provide such a feature because the process in which your script/program runs has no intrinsic knowledge about what happened in the same terminal before it was run. The only way it could access this text would be if it could ask the currently running terminal, which will have some record of this information (i.e. the scrollback buffer), even if it cannot distinguish between which characters in the text were typed by you, and which are output. However, I know of no terminal that exposes that information via any kind of public API.
So if you want myscript.pl to be able to access that echo "Hello", you'll need to pass it to your script. Piping history to your script (as shown by Mark Setchell in his answer) is one technique. history is a shell built-in, so it has as much knowledge as your shell has (which is not quite the same knowledge as your terminal has). In particular it can give you a list of what commands have been typed in this shell session. However, it cannot tell you about the output generated by those commands. And it cannot tell you about other shell sessions, so doing this in Perl is fairly useless:
my #history = `tcsh -c history`;
The last thing you could try (though it would be incredibly complicated to do) would be to ask the X server (or Windows if running on that operating system) for a screen shot and then attempt to locate which rectangle the current terminal is running in and perform OCR on it. This would be fraught with problems though, such as dealing with overlapping windows.
So, in summary, you cannot do this. It's nothing to do with Perl. You cannot do this in any programming language.

Workflow to debug for a Perl programmer

I am new to Perl and I have the following problem.
I have a log output and I have found where this log output comes from. I mean the subroutine in some module that prints it.
Now e.g. in Java via Eclipse I would use e.g. Call hierarchy and other utilities to see how/when/who calls the method and figure out how to reproduce what I need and debug.
How can I do this in Perl? Via e.g. grep? If I grep e.g. for the module name I get hundrends of lines ranging from use A require A C::B::A B::A C::B::A::some_routine C::B::A::some_other_routine etc.
On top of this I am worried that perhaps the routine I am interested in is not called directly but some script e.g. runs the module that is of interest to me via some obscure (to me due to my ignorance in Perl) manner.
So how would I go debug something in Perl in the most efficient way? What do you Perl gurus suggest for me to do and become more efficient?
Run the program under the Perl debugger:
perl -d scriptname arguments...
Set a breakpoint in the function you care about, and when the program stops at the breakpoint use the T debugger command to display a stack trace, which will show where the function was called from.
From your comments, I'm not sure this actually addresses what you're looking for. Maybe what you want is a cross-reference of the Perl application? See the FAQ How do I cross-reference my Perl programs?
Most of the time getting a stack trace (along with some debugging info) is a good start. One can use standard Carp module to generate stack traces:
use Carp;
print_to_log(Carp::longmess("We're here"));
Or there's an object-oriented module for that as well.
To get a dump of the call stack without modifying any code, you can use the perl command line to run your program under Carp::Always:
perl -MCarp::Always my_program.pl

Why shouldn't I use shell tools in Perl code?

It is generally advised not to use additional linux tools in a Perl code;
e.g if someone intends to print the last line of a text file he can:
$last_line = `tail -1 $file` ;
or otherwise, open the file and read it line by line
open(INFO,$file);
while(<INFO>) {
$last_line = $_ if eof;
}
What are the pitfalls of using the previous and why should I avoid using shell tools in my code?
thanx,
Efficiency - you don't have to spawn a new process
Portability - you don't have to worry about an executable not existing, accepting different switches, or having different output
Ease of use - you don't have to parse the output, the results are already in a usable form
Error handling - you have finer-grained control over errors and what to do about them in Perl.
It's better to keep all the action in Perl because it's faster and because it's more secure. It's faster because you're not spawning a new process, and it's more secure because you don't have to worry about shell meta character trickery.
For example, in your first case if $file contained "afilename ; rm -rf ~" you would be a very unhappy camper.
P.S. The best all-Perlway to do the tail is to use File::ReadBackwards
One of the primary reasons (besides portability) for not executing shell commands is that it introduces overhead by spawning another process. That's why much of the same functionality is available via CPAN in Perl modules.
One reason is that your Perl code might be running in an environment where there is no shell tool called 'tail'.
It's a personal call depending on the project:
Is it going to be always used in shell environments with tail?
Do you care about only using pure Perl code?
Using tail? Fine. But that's really a special case, since it's so easy to use and since it is so trivial.
The problem in general is not really efficiency or portability, that is largely irrelevant; the issue is ease of use. To run an external utility, you have to find out what arguments it accepts, write code to transform your program's data structures to that format, quote them properly, build the command line, and run the application. Then, you might have to feed it data and read data from it (involving complexity like an event loop, worrying about deadlocking, etc.), and finally interpret the return value. (UNIX processes consider "0" true and anything else false, but Perl assumes the opposite. foo() and die is hard to read.) This is a lot of work to do, and that's why people avoid it. It's much easier to create an instance of a class and call methods on it to get the data you need.
(You can abstract away processes this way; see Crypt::GpgME for example. It handles the complexity associated with invoking gpg, which would normally involve creating multiple filehandles other than STDOUT, STDIN, and STDERR, among other things.)
The main reason I see for doing it all in Perl would be for robustness. Your use of tail will fail if the filename has shell metacharacters or spaces or doesn't exist or isn't accessible. From Perl, characters in the filename aren't an issue, and you can distinguish between errors in accessing the file. Sometimes being robust is more important than speedy coding and sometimes it's not.