我有一个使用system()
调用外部可执行文件的perl脚本。我想测量这些外部程序所占用的CPU秒数。理想情况下,我想使用shell builtin time
命令运行它们(这是在Linux系统上)。像这样:
system("time /path/to/command")
现在,time
将其输出打印到stderr,但为了这样做,启动它在单独的子shell中给出的命令。这意味着为了在shell中手动运行时捕获时间输出,您需要显式使用子shell并重定向子shell的stderr:
$ time ( command > command.log 2> command.er) 2> time.out
文件time.out
将具有time
命令的输出,而command.er
具有command
的stderr。不幸的是,括号打破了perl的系统调用:
$ time ( ls ) 2> er ## works
$ perl -e 'system("time (ls)")'
sh: 1: Syntax error: word unexpected (expecting ")")
这意味着我无法捕获time
的输出。为了使事情变得更糟,这似乎取决于版本:
$ perl --version | head -n2
This is perl 5, version 18, subversion 2 (v5.18.2) built for x86_64-linux-gnu-thread-multi
但如果我尝试使用更新版本的相同内容:
$ perl --version | head -n2
This is perl 5, version 24, subversion 1 (v5.24.1) built for x86_64-linux-thread-multi
$ perl -e 'system("time (ls)")'
file1
real 0m0.002s
user 0m0.000s
sys 0m0.000s
不幸的是,我需要在生产机器上运行,因此升级Perl不是一种选择。那么,我如何在Perl 5.18中对系统调用进行计时?我需要user
和sys
值,因此只记录开始和结束时间无济于事。我愿意使用专用模块,如果这是必要的,虽然我更喜欢让我使用shell time
的技巧。
更新:事实证明,行为的差异不是因为更新的perl版本,而是因为我在/bin/sh
为bash
的Arch系统上测试了它,而其他命令在/bin/sh
为dash
的Ubuntu系统上运行,这是一个不支持子shell括号的最小shell。
答案 0 :(得分:3)
您已使用bash
测试了该命令,但已将其传递给sh
。
system("time (ls)")
是
的缩写system("/bin/sh", "-c", "time (ls)")
但你想要
system("/bin/bash", "-c", "time (ls)")
答案 1 :(得分:1)
$ time ( ls ) 2> er ## works
$ perl -e 'system("time (ls)")'
sh: 1: Syntax error: word unexpected (expecting ")")
问题在于,在第一种情况下,您的shell可能是/bin/bash
,而在第二种情况下,它是/bin/sh
。如果要使用其他shell运行命令,可以使用system LIST
形式:
system("/bin/bash", "-c", "time(ls)")
注1:有PERL5SHELL
个environmnet值,但这似乎只在Win32上生效。
注意2:如果要测量子进程的CPU时间,可以使用Unix::Getrusage或BSD::Resource模块。