我可以从Perl捕获shell调用吗?
我有一个调用其他程序的Perl脚本,即它使用管道调用我可以从Perl捕获shell调用吗?,perl,debugging,shell,shellexecute,system-calls,Perl,Debugging,Shell,Shellexecute,System Calls,我有一个调用其他程序的Perl脚本,即它使用管道调用system和/或exec和/或open,和/或使用backtick操作符 我能否以这样一种方式运行这个脚本,它将打印出上面每个脚本的参数,以便我可以看到它调用了什么 例如,像这样的程序,我无法修改 #!/usr/bin/perl sub get_arg {return "argument$_[0]";} system "./foo", get_arg(1), get_arg(2); print `./foo abc def`; 可能是这样的
system
和/或exec
和/或open
,和/或使用backtick操作符
我能否以这样一种方式运行这个脚本,它将打印出上面每个脚本的参数,以便我可以看到它调用了什么
例如,像这样的程序,我无法修改
#!/usr/bin/perl
sub get_arg {return "argument$_[0]";}
system "./foo", get_arg(1), get_arg(2);
print `./foo abc def`;
可能是这样的
perl—在./myscript.pl上的shell跟踪
在这种情况下,它将输出
./foo argument1 argument2
./foo abc def
丢弃myscript.pl的正常输出或将其与此跟踪混合是可以接受的
非常感谢。否,系统命令不会将其执行的命令放入任何特殊变量中
#!/usr/bin/perl
sub get_arg {return "argument$_[0]";}
my $command = './foo ' . join(' ', get_arg(1), get_arg(2));
print "$command\n";
my $resp = `$command`; # or system($command);
print `ls *bar*`;
这被认为是高级Perl,但您可以在编译时在
CORE::GLOBAL
命名空间中定义子例程,并劫持Perl的内置函数。
调用核心
命名空间中的函数将调用原始内置函数
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;
要将此功能应用于任意独立脚本,可以将此代码放入一个简单的模块(例如,ShellTrace.pm
),然后使用-MShellTrace
开关调用perl
。(HT:perlman):
你想让脚本看到shell扩展后命令的样子吗?我想捕获外部程序的执行及其参数。编辑以澄清——脚本是不可变的。我正在寻找一个类似于
strace
的解决方案。这是一个令人印象深刻的技巧,但它需要修改脚本。有没有一种方法可以在这样建立的环境中调用未更改的脚本?是的-将这些更改放在.pm
文件中(例如ShellTrace.pm
,并使用perl-MShellTrace./myscript.pl
调用脚本
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
...