它仍然涉及一个临时文件,但如果您使用的是具有/dev/fd
文件系统的 Linux 等操作系统,您可以打开一个临时文件,立即将其删除以保持整洁,并/dev/fd/N
作为文件名传递给neomutt
,其中 N 是基础文件perl 文件句柄的描述符编号。如果您使用核心File::Temp
模块创建临时文件,则可以安全地完成,无需潜在的竞争条件或手动删除文件。
system
但是,在执行子程序之前阻止描述符被关闭有点麻烦。
例子:
#!/usr/bin/env perl
use strict;
use warnings;
use File::Temp qw/tempfile/;
use Fcntl qw/:DEFAULT/;
# Get a handle to an anonymous temporary file
my $fh = tempfile;
print $fh <<EOF;
set beep = 0
set beep_new = 0
set bounce = ask-yes
set check_mbox_size = 1
set check_new = 1
EOF
flush $fh;
# Clear the CLOEXEC bit so the descriptor is available to the program run
# by system
my $flags = fcntl $fh, F_GETFD, 0
or die "Unable to get descriptor flags: $!";
fcntl $fh, F_SETFD, $flags & ~FD_CLOEXEC
or die "Unable to set descriptor flags: $!";
my $fd = fileno $fh;
system("cat", "/dev/fd/$fd");
完全避免临时文件(但有点复杂)的另一种方法是打开一个管道,并派生一个将数据写入其中的子节点,然后再次使用/dev/fd/N
带有 neomutt 的接口:
#!/usr/bin/env perl
use strict;
use warnings;
use Fcntl qw/:DEFAULT/;
pipe my $reader, my $writer or die "Unable to pipe: $!\n";
my $pid = fork;
die "Unable to fork" unless defined $pid;
if ($pid == 0) { # Child process
close $reader;
print $writer <<EOF;
set beep = 0
set beep_new = 0
set bounce = ask-yes
set check_mbox_size = 1
set check_new = 1
EOF
close $writer;
exit;
} else { # Parent process
close $writer;
# Clear the CLOEXEC bit so the descriptor is available to the program run
# by system
my $flags = fcntl $reader, F_GETFD, 0;
fcntl $reader, F_SETFD, $flags & ~FD_CLOEXEC;
my $fd = fileno $reader;
system("cat", "/dev/fd/$fd");
close $reader;
waitpid $pid, 0; # Reap the child process
}