1

我在 perl 中运行了一个 while(1) 循环,以从 PostgreSQL 表中提取电子邮件地址和每个人的配置值。现在,我编写了一个临时文件并将 neomutt -nF the_temp_file 与 system. 然后我取消链接文件。尼奥马特辞职。然后循环为我提供了电子邮件地址列表,以使用我选择的任何一个地址重新启动 neomutt。

我还没有在 neomutt 邮件列表上问过这个问题,但我会的。一般来说,我想知道是否有一种方法可以在不将临时文件写入文件系统的情况下模拟临时文件。

为了更清楚:

获取配置值,例如:

set beep = 0
set beep_new = 0
set bounce = ask-yes
set check_mbox_size = 1
set check_new = 1

并将其直接发送到地点 neomutt 期望在 neomutt -F config_file 有一个文件

这可能吗?谢谢

4

1 回答 1

1

它仍然涉及一个临时文件,但如果您使用的是具有/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
}
于 2021-10-05T22:29:49.920 回答