Perl 的 system() 如何打印它正在运行的命令?
Posted
技术标签:
【中文标题】Perl 的 system() 如何打印它正在运行的命令?【英文标题】:How can Perl's system() print the command that it's running? 【发布时间】:2010-09-06 05:50:55 【问题描述】:在 Perl 中,您可以使用 system() 或 ``(反引号)来执行系统命令。您甚至可以将命令的输出捕获到变量中。但是,这会在后台隐藏程序执行,因此执行脚本的人看不到它。
通常这很有用,但有时我想看看幕后发生了什么。您是如何做到的,以便将执行的命令打印到终端,并将这些程序的输出打印到终端?这将是 .bat
相当于“@echo on”。
【问题讨论】:
【参考方案1】:我不知道执行此操作的任何默认方式,但您可以定义一个子例程来为您执行此操作:
sub execute
my $cmd = shift;
print "$cmd\n";
system($cmd);
my $cmd = $ARGV[0];
execute($cmd);
然后看看它的实际效果:
pbook:~/foo rudd$ perl foo.pl ls
ls
file1 file2 foo.pl
【讨论】:
【参考方案2】:据我了解,system() 将打印命令的结果,但不会分配它。例如。
[daniel@tux /]$ perl -e '$ls = system("ls"); print "Result: $ls\n"'
bin dev home lost+found misc net proc sbin srv System tools var
boot etc lib media mnt opt root selinux sys tmp usr
Result: 0
反引号将捕获命令的输出而不是打印它:
[daniel@tux /]$ perl -e '$ls = `ls`; print "Result: $ls\n"'
Result: bin
boot
dev
etc
home
lib
等等……
更新:如果你想打印命令名称为 system()
'd 为好,我认为Rudd 的方法很好。在此重复以进行合并:
sub execute
my $cmd = shift;
print "$cmd\n";
system($cmd);
my $cmd = $ARGV[0];
execute($cmd);
【讨论】:
【参考方案3】:改用 open 。然后你可以捕获命令的输出。
open(LS,"|ls");
print LS;
【讨论】:
【参考方案4】:这是一个更新的执行,它将打印结果并返回它们:
sub execute
my $cmd = shift;
print "$cmd\n";
my $ret = `$cmd`;
print $ret;
return $ret;
【讨论】:
【参考方案5】:嗯,有趣的是,不同的人以不同的方式回答这个问题。在我看来,mk 和 Daniel Fone 将其解释为想要查看/操作命令的标准输出(他们的解决方案都没有捕获标准错误 fwiw)。我认为Rudd 更接近了。您可以对 Rudd 的响应做出的一种改变是用您自己的版本覆盖内置的 system() 命令,这样您就不必重写现有代码来使用他的 execute() 命令。
使用 Rudd 帖子中的 execute() 子程序,您可以在代码顶部添加类似这样的内容:
if ($DEBUG)
*"CORE::GLOBAL::system" = \&"main::execute";
我认为这会起作用,但我不得不承认这是巫术,而且我已经有一段时间没有编写此代码了。这是我多年前编写的代码,用于在模块加载时拦截本地(调用命名空间)或全局级别的系统调用:
# importing into either the calling or global namespace _must_ be
# done from import(). Doing it elsewhere will not have desired results.
delete($optshandle_system);
if ($do_system)
if ($do_system eq 'local')
*"$callpkg\::system" = \&"$_package\::system";
else
*"CORE::GLOBAL::system" = \&"$_package\::system";
【讨论】:
替换全局system
命令最大的问题是system
有一个复杂的原型,不能被用户指定的原型系统复制。因此,如果您将 system
替换为您的自定义版本,某些代码将无法正常工作。【参考方案6】:
与答案中提到的其他技术相结合的另一种技术是使用tee
命令。例如:
open(F, "ls | tee /dev/tty |");
while (<F>)
print length($_), "\n";
close(F);
这将打印出当前目录中的文件(作为tee /dev/tty
的结果)并打印出每个读取的文件名的长度。
【讨论】:
以上是关于Perl 的 system() 如何打印它正在运行的命令?的主要内容,如果未能解决你的问题,请参考以下文章
Python - 调用 perl 作为子进程 - 等待完成其后台进程并打印到 shell
如何将 Perl 的 system() 的输出重定向到文件句柄?