perl - 为什么 system() 即使它执行的程序死了也返回 0

标签 perl system

我正在尝试测试一段代码( $code ),它应该确保一次只运行一个程序实例:

#!/usr/bin/perl
# test_lock
use strict;
use warnings;

( my $code = <<'CODE') =~ s/^\s+//gm;
    #!/usr/bin/perl
    use strict;
    use warnings;
    use Fcntl qw(:flock);

    # Make sure only one instance of the program is running at a time.
    open our $Lock, '<', $0 or die "Can't lock myself $0: $!";
    flock $Lock, LOCK_EX | LOCK_NB
      or die "Another instance of $0 is already running. Exiting ...\n";

    sleep(2);
CODE

my $progfile = '/tmp/x';
open my $fh, '>', $progfile or die $!;
print $fh $code;
close $fh;

$|++;
my $ex1 = system("perl $progfile &");
print "First system(): $ex1\n";
my $ex2 = system("perl $progfile");
print "Second system(): $ex2\n";

我预计第二次调用 system()将返回一个非零值( $ex2 ),因为它无法获得锁和 die s。但是我得到:
$ perl test_lock
First system(): 0
Another instance of /tmp/x is already running. Exiting ...
Second system(): 0

我的假设有什么问题? (有没有更好的方法来测试 $code ?)

最佳答案

我认为这可能是因为您有竞争条件。你怎么知道错误实际上来自你的第二个过程?

因为如果你例如,运行:

perl /tmp/x & perl /tmp/x ; echo $?

您可能会得到零返回,因为比赛的“赢家”很可能是后一个过程(您捕获的返回代码)。 (多试几次,你会看到不同的结果)

您也确实有细微的不同,即 shell 在两个命令之间执行的操作 - 来自文档:

If there is only one scalar argument, the argument is checked for shell metacharacters, and if there are any, the entire argument is passed to the system's command shell for parsing (this is /bin/sh -c on Unix platforms, but varies on other platforms). If there are no shell metacharacters in the argument, it is split into words and passed directly to execvp , which is more efficient.



所以实际上你应该看到对 sh 的调用之前 perl在您的第一个中,这意味着实际上更有可能需要更长的时间才能到达锁定点。

这意味着您的命令更像是:
sh -c "perl /tmp/x"& perl /tmp/x; echo $?

运行几次,看看有多少次你得到非零错误代码。这并不常见,因为通常情况下,shell 启动的“延迟”足以确保第二个实例在大多数情况下赢得比赛!

如果你有 Linux - 试试 strace -fTt yourscript这将跟踪执行流程。或者您可以明智地使用 $$运行时报告进程pid。

关于perl - 为什么 system() 即使它执行的程序死了也返回 0,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33801002/

相关文章:

json - Perl:如果启动线程,JSON 会失败

python - 将数据分箱

php - 像 PHP 一样在 Perl 中启用错误消息

c++ - 在 dos 批处理文件中关闭屏幕更新

c - 函数 srand、rand 和 system 的隐式声明

haskell - 从 Haskell 中的系统命令读取输入

java - 同时将控制台输出写入文件和控制台

windows - 如何防止\n to 在 Windows 上被转换为\r\n

perl - 编写可维护的网络抓取应用程序的最佳方法是什么?

c - 使用echo在C中写入文件时如何换行