Есть ли способ передачи данных из Perl в утилиту командной строки Unix - PullRequest
2 голосов
/ 08 декабря 2010

У меня есть утилита командной строки от стороннего производителя (она большая и написана на Java), которую я использую для обработки некоторых данных.Эта утилита ожидает информацию в файле с разделителями строк, а затем выводит обработанные данные в STDOUT.

На моих этапах тестирования я справился с написанием некоторого Perl для создания файла, полного информации для обработки, и последующей отправкой этого файлав эту стороннюю утилиту, но поскольку я близок к запуску этого кода в производство, я действительно предпочел бы просто направить данные в эту утилиту напрямую, а не сначала записывать эти данные в файл, так как это избавило бы меня от необходимостизаписать ненужную информацию на диск.Я недавно спросил на этой плате, как я могу сделать это в Unix, но с тех пор понял, что было бы невероятно удобнее фактически запускать его непосредственно из модуля Perl.Возможно, что-то вроде:

system(bin/someapp do-action --option1 some_value --input $piped_in_data)

В настоящее время я вызываю утилиту следующим образом:

bin/someapp do-action --option1 some_value --input some_file

По сути, я хочу написатьвсе мои данные либо в переменную, либо в STDOUT, а затем направить их в приложение Java через системный вызов в том же самом скрипте Perl или модуле.Это сделало бы мой код более плавным.Без этого мне бы пришлось написать сценарий Perl, который на полпути вызывает bash-файл, а затем, в свою очередь, должен был бы вызвать другой сценарий Perl для подготовки данных.Если бы это было возможно, я бы хотел остаться в Perl до конца.Есть идеи?

Ответы [ 3 ]

8 голосов
/ 08 декабря 2010

Если я правильно читаю ваш вопрос, вы хотите порождать процесс и иметь возможность как писать в его стандартный вывод, так и читать из его стандартного вывода.Если это так, то IPC :: Open2 - это именно то, что вам нужно.(Также см. IPC :: Open3 , который также необходимо прочитать из процесса 'stderr.)

Вот пример кода.Я отметил области, которые вам придется изменить.

#!/usr/bin/perl

use strict;
use warnings;

use IPC::Open2;

# Sample data -- ignore this.
my @words = qw(the quick brown fox jumped over the lazy dog);

# Automatically reap child processes.  This is important when forking.
$SIG{'CHLD'} = 'IGNORE';

# Spawn the external process here.  Change this to the process you need.
open2(*READER, *WRITER, "wc -c") or die "wc -c: $!";

# Fork into a child process.  The child process will write the data, while the
# parent process reads data back from the process.  We need to fork in case
# the process' output buffer fills up and it hangs waiting for someone to read
# its output.  This could cause a deadlock.
my $pid;
defined($pid = fork()) or die "fork: $!";

if (!$pid) {
    # This is the child.

    # Close handle to process' stdout; the child doesn't need it.
    close READER;

    # Write out some data.  Change this to print out your data.
    print WRITER $words[rand(@words)], " " for (1..100000);

    # Then close the handle to the process' stdin.
    close WRITER;
    # Terminate the child.
    exit;
}

# Parent closes its handle to the process' stdin immediately!  As long as one
# process has an open handle, the program on the receiving end of the data will
# never see EOF and may continue waiting.
close WRITER;

# Read in data from the process.  Change this to whatever you need to do to
# process the incoming data.
print "READ: $_" while (<READER>);

# Close the handle to the process' stdin.  After this call, the process should
# be finished executing and will terminate on its own.
close READER;
1 голос
/ 08 декабря 2010

Если все, что вы хотите сделать, это передать STDOUT из вашей программы в STDIN вашей другой программы, вы можете сделать это с помощью стандартной команды Perl open:

open (CMD, "|$command") or die qq(Couldn't execute $command for piping);

Затем все, что вам нужноДля отправки данных в эту команду используется оператор print:

print CMD $dataToCommand;

И, наконец, вы закрываете канал с помощью оператора close:

close (CMD);

PERL HINT

В Perl есть команда под названием perldoc, которая может предоставить вам документацию по любой функции Perl или модулю Perl, установленному в вашей системе.Чтобы получить больше информации о команде open, введите:

$ perldoc -f open

-f говорит, что это функция Perl

Если вы делаете то, что cdhowie сказал в своем ответе (вы порождаете процесс, затем читаете и пишете этому процессу), вам понадобится IPC::Open2.Чтобы получить информацию о модуле IPC::Open2, введите:

$ perldoc IPC::Open2
1 голос
/ 08 декабря 2010

Если он принимает только файлы, откройте файл "/ proc / self / fd / 0", который совпадает с STDIN. В остальном смотрите ответ cdhowies.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...