perl で exec 後に file descriptor を渡す

通常は 0, 1, 2 しか渡されない。

open my $fh, ">", "file.txt";
exec "ls", "-al", "/proc/$$/fd";
> perl test.pl
total 0
dr-x------ 2 skaji skaji  0 Mar 29 03:04 .
dr-xr-xr-x 9 skaji skaji  0 Mar 29 03:04 ..
lrwx------ 1 skaji skaji 64 Mar 29 03:04 0 -> /dev/pts/5
lrwx------ 1 skaji skaji 64 Mar 29 03:04 1 -> /dev/pts/5
lrwx------ 1 skaji skaji 64 Mar 29 03:04 2 -> /dev/pts/5
lr-x------ 1 skaji skaji 64 Mar 29 03:04 3 -> /proc/20500/fd

(注:3 -> /proc/20500/fd は ls 自身が開いたもの)

方法1 : FD_CLOEXEC を 0 にする

use Fcntl;
open my $fh, ">", "file.txt";
fcntl $fh, F_SETFD, 0; # FD_CLOEXEC を 0 に
exec "ls", "-al", "/proc/$$/fd";
> perl test.pl
total 0
dr-x------ 2 skaji skaji  0 Mar 29 03:07 .
dr-xr-xr-x 9 skaji skaji  0 Mar 29 03:07 ..
lrwx------ 1 skaji skaji 64 Mar 29 03:07 0 -> /dev/pts/5
lrwx------ 1 skaji skaji 64 Mar 29 03:07 1 -> /dev/pts/5
lrwx------ 1 skaji skaji 64 Mar 29 03:07 2 -> /dev/pts/5
l-wx------ 1 skaji skaji 64 Mar 29 03:07 3 -> /home/skaji/file.txt
lr-x------ 1 skaji skaji 64 Mar 29 03:07 4 -> /proc/20651/fd

方法2 : $^F をいじる

perldoc -v '$^F' 曰く、$^F 以下の file descriptor のみ exec に渡すらしい。よってこれを大きくすれば渡せる。

my $fh;
{
    local $^F = 10;
    open $fh, ">", "file.txt";
}
exec "ls", "-al", "/proc/$$/fd";

SEE ALSO