Я запускаю neomutt в цикле с Perl. Значения конфигурации поступают из PostgreSQL, но neomutt читает только из файлов. Как имитировать файл из Perl?
Я запускаю цикл while(1) в Perl, чтобы извлечь адреса электронной почты и значения конфигурации каждого из них из таблиц PostgreSQL. Прямо сейчас я пишу временный файл и использую neomutt -nF the_temp_file с системой. Затем я отключаю файл. Неомутт уходит. Затем цикл дает мне список адресов электронной почты, чтобы снова запустить 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
Это возможно? Спасибо
1 ответ
Он по-прежнему включает временный файл, но если вы используете ОС, например Linux, в которой есть
/dev/fd
файловой системе, вы можете открыть временный файл, немедленно удалить его, чтобы все было в порядке, и передать в качестве имени файла
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
}