wget не ведет себя через IPC :: Open3 vs bash - PullRequest
4 голосов
/ 09 июня 2010

Я пытаюсь передать файл с удаленного веб-сайта локальной команде, и у меня возникают проблемы при обнаружении ошибок.

Код выглядит примерно так:

use IPC::Open3;

my @cmd = ('wget','-O','-','http://10.10.1.72/index.php');#any website will do here

my ($wget_pid,$wget_in,$wget_out,$wget_err);
if (!($wget_pid = open3($wget_in,$wget_out,$wget_err,@cmd))){
    print STDERR "failed to run open3\n";
    exit(1)
}
close($wget_in);
my @wget_outs = <$wget_out>;
my @wget_errs = <$wget_err>;
print STDERR "wget stderr: ".join('',@wget_errs);
#page and errors outputted on the next line, seems wrong
print STDERR "wget stdout: ".join('',@wget_outs);

#clean up after this, not shown is running the filtering command, closing and waitpid'ing

Когда я запускаю эту команду wget непосредственно из командной строки и перенаправляю stderr в файл, происходит что-то вменяемое - stdout будетзагруженная страница, stderr будет содержать информацию об открытии данной страницы.

wget -O - http://10.10.1.72/index.php 2> stderr_test_file

Когда я запускаю wget через open3, я получаю и страницу, и информацию, смешанную вместе в stdout.Я ожидаю загрузки страницы в одном потоке и STDERR от wget в другом.

Я вижу, что упростил код до такой степени, что не понятно, почему я хочу использовать open3, ноОбщий план состоит в том, что я хотел передать поток stdout другой программе фильтрации, как только я ее получил, а затем в конце я собирался прочитать stderr как из wget, так и из программы фильтрации, чтобы определить, что, если что-то пошло не так.

  • Я пытался избежать записи данных wget'd в файл, затем отфильтровать этот файл в другой файл, а затем прочитать вывод.
  • Это ключ, которыйЯ могу видеть, что пошло не так, не просто читая $?>> 8 (то есть я должен сказать пользователю, эй, что IP-адрес неправильный, или не тот тип сайта, или что-то в этом роде).
  • Наконец, я выбираю system / open3 / exec, а не другие запросы (например, обратные ссылки), потому что некоторые входные данные предоставляются ненадежными пользователями.

1 Ответ

3 голосов
/ 09 июня 2010

Вы передаете неопределенное значение в качестве аргумента дескриптора ошибки для open3, а IPC::Open3 говорит:

Если CHLD_ERR имеет значение false или тот же файловый дескриптор, что и CHLD_OUT, тогда STDOUT и STDERR дочернего объекта находятся в одном и том же файловом дескрипторе (это означает, что для файлового дескриптора STDERR не может использоваться автовыводимая лексика ОПИСАНИЕ) ...

Обходной путь - инициализировать $wget_err чем-то перед вызовом open3:

my ($wget_pid, $wget_in, $wget_out, $wget_err);
use Symbol qw(gensym);
$wget_err = gensym();
if (!$wget_pid = open3( ... ) ) { ... 
...