这条线究竟做了什么,它是如何做到的?打开我的$ fh_echo,' - |'或者执行“$ sshstr \”$ str \“”

时间:2010-08-09 23:45:00

标签: perl exec

以下是perl中的这一行:

open my $fh_echo, '-|' or exec "$sshstr \"$str\"";

基本上它是exec的$ sshstr然后输出进入$ fh_echo,不知何故。我很好奇这个操作背后的机制。有人可以解释一下' - |'装置

此外,如何将输出加载到$ fh_echo?它是一点一点输出还是$ fh_echo只是exec输出的句柄?

哈哈,我甚至不能谷歌这个因为 - |不要出现在结果中。

2 个答案:

答案 0 :(得分:4)

perlfork。这是一个分叉管道。

基本上,|-管道输出到分叉子进程,-|从父进程读取(在子进程内)。

来自perldoc -f open

  

如果在命令' - '上打开管道,即'| - '或' - |'使用open()的2参数(或1参数)形式,然后有一个隐式fork完成,并且                  open的返回值是父进程中子进程的pid,子进程内为0。

在您的示例中,您打开一个管道来读取子进程,然后分叉,然后在子进程中用$sshstr替换进程。

答案 1 :(得分:2)

这似乎与open my $fh_echo, "-|", "$sshstr \"$str\""完全相同。它贬低为:

exec qq[$sexec qq[$sshstr "$str"] unless open my $fh_echo, '-|'

当事情成功打开时,输出并没有真正加载到$ fh_echo中,$ fh_echo变成了一个文件句柄,通过管道在open()的最右边的参数中输出可执行文件。有关管道的更多信息,请查看wikipedia page。应该指出的是,你给出的例子并没有打开任何东西。因为在您提供的示例的右侧没有命令,open()将始终返回指示失败的非true值,并且表达式的右侧将始终运行。见http://ideone.com/wupJ8

如果要获得更多成功,我们将使用open my $f, "-|", "echo hi"作为更好的示例。这样做是重新定义stdin,因为子进程是管道的右侧,使其大致相当于以下内容:

pipe my $fh_echo, my $childout;

if (fork == 0) {
    close STDOUT; 
    open STDOUT, ">>&", $childout;

    exec "echo hi";
}

首先创建一个管道,然后分叉。在子进程中,stdout被重新定义为管道的写入端。然后调用exec(有关更多详细信息,请参阅exec(2)),它将当前进程替换为给定进程。从那时起,由于stdout已被重新定义为管道的可写端,因此stdout的所有输出实际上都将写入管道,而不是目标可能曾经存在的那些。

另外,要进一步详细说明exec“echo hi”缺陷到shell,因为它不是完全限定的可执行路径。也就是说,它实际上被perl读为exec "/bin/sh", "echo hi",因为perl决定不做出给定表达式可能意味着什么的决定。

希望这能解释机制。