I have a Perl script which invokes other programs, i.e. it calls system
and/or exec
and/or open
with a pipe and/or uses the backtick operator.
Can I run this script in such a way that it will print out the arguments to each of the above so that I can see what it is calling into?
For example a program like this which I cannot modify
#!/usr/bin/perl
sub get_arg {return "argument$_[0]";}
system "./foo", get_arg(1), get_arg(2);
print `./foo abc def`;
Invoked something perhaps like this
perl --shell-trace-on ./myscript.pl
Which will in this case output
./foo argument1 argument2
./foo abc def
It is acceptable to throw away myscript.pl's normal output or blend it with this trace.
Thanks a lot.
This is considered advanced Perl, but you can define subroutines in the CORE::GLOBAL
namespace at compile time and hijack Perl's builtin functions.
Calling functions in the CORE
namespace will invoke the original builtin functions.
BEGIN {
# have to use a BEGIN block so these functions are defined before
# run time
*CORE::GLOBAL::system = sub {
print STDERR "about to invoke system @_\n";
return CORE::system(@_);
};
*CORE::GLOBAL::qx = sub {
print STDERR "about to invoke qx/backticks @_\n";
return CORE::qx(@_);
};
*CORE::GLOBAL::exec = sub { ... };
};
system("sleep 5");
print `ls`;
1;
To apply this feature to an arbitrary standalone script, you can put this code into a simple module (say, ShellTrace.pm
), and then invoke perl
with the -MShellTrace
switch. (HT: perlman):
package ShellTrace;
BEGIN {
*CORE::GLOBAL::system = sub { ... };
*CORE::GLOBAL::qx = sub { ... };
*CORE::GLOBAL::exec = sub { ... };
*CORE::GLOBAL::open = sub { ... };
}
1;
$ perl -MShellTrace ./myscript.pl
about to invoke system ./foo argument1 argument2
about to invoke qx/backticks ./foo abc def
...