2013-07-15 23 views
2

open3只需要STDIN,STDOUT和STDERR。如果正在運行該命令使用其他文件描述符然後open3無法捕捉那些:Perl:open3,但對於n個文件描述符

echo foo # Can be captured 
echo foo >&2 # Can be catured 
echo foo >&3 # Cannot be captured (with open3) 

我特地到IPC ::運行::來看,這似乎能夠應付,但我還需要和PID我發現IPC :: Run :: run沒有辦法給我。

是否有openN或IPC :: Run :: run的方式給我PID?

背景

這適用於GNU並行的可能的擴展,所以你可以做:

parallel 'echo {} start >&3;sleep 10;echo {} end >&3' ::: a b c 3>out.file 

,而不必從混合不同作業的輸出。 GNU Parallel需要跟蹤每個pid - 特別是當使用--keep-order時。

+0

爲什麼你想要的PID? – ikegami

+0

IPC :: Open3不會阻止您在fd3上放置管道。它只是不會爲你做。 – ikegami

+0

孩子的pid在IPC :: Run內部已知。只需用'IPC :: Run :: start'替換IPC :: Run :: run'並轉儲返回的對象即可。不幸的是,這是沒有記錄,所以你自己... –

回答

0

fd3已經存在,所以你需要做的就是確保孩子們繼承它。既然它是自己繼承的,你根本不需要做任何事情。

$ perl -e' 
    system "echo foo >&3"; 
' 3>bar 

$ cat bar 
foo 

但是,如果你想確保它的繼承,你可以使用下面的

$ perl -e' 
    use Fcntl qw(F_GETFD F_SETFD FD_CLOEXEC); 
    if (open(my $fh, ">&=", 3)) { 
     my $flags = fcntl($fh, F_GETFD, 0) 
     or die $!; 
     fcntl($fh, F_SETFD, $flags & ~FD_CLOEXEC) 
     or die $!; 
    } 

    system "echo foo >&3"; 
' 3>bar 

$ cat bar 
foo 
+0

我不希望它繼承。我想把fd3上的子打印件放在一個文件中,當孩子死亡時,打印fd3上的文件。我知道如何做最後一部分(當孩子死亡時打印)。 –

+0

請記住,在GNU並行中,我可以同時爲多個孩子寫入他們的fd3,而且我不希望混合輸出,所以GNU並行需要在輸出達到GNU並行的fd3之前捕獲輸出。 –

+0

如果你可以使open4(fd0,fd1,fd2,fd3,cmd,arg)並以open3爲基礎,那也可以。 –