Есть ли способ заставить этот Perl-код захватывать stderr, а также stdout из tcsh?

    open UNIT_TESTER, qq(tcsh -c "gpath $dir/$tsttgt;  bin/rununittests"|);
    while(<UNIT_TESTER>){
        reportError($ignore{testabort},$tsttgt,"test problem detected for $tsttgt:$_ ") if /core dumped/;
        reportError($ignore{testabort},$tsttgt,"test problem detected for $tsttgt:$_ ") if /\[  FAILED  \]/;
        writelog($tsttgt,$_);
    }
    close UNIT_TESTER;

Я попытался перенаправить stderr на stdout, используя этот синтаксис, но это не сработало:

open UNIT_TESTER, qq(tcsh -c "gpath $dir/$tsttgt;  bin/rununittests >& "|);

Я также читал обсуждение perl FAQ, но это было связано с bash: http://www.perl.com/doc/FAQs/FAQ/oldfaq-html/Q5.15.html


person mikelong    schedule 08.06.2010    source источник


Ответы (4)


Я бы посоветовал вам выполнять захват с помощью модуля Capture::Tiny из CPAN. Он маленький, простой и хорошо протестированный. Он имеет элегантный API, и если у вас полностью отсутствуют какие-либо зависимости, его можно легко встроить в вашу программу.

Кроме того: если у вас есть какой-либо контроль над запущенной программой тестирования, я бы посоветовал вам изучить Test Anything Протокол. Если вы можете заставить свою тестовую программу выводить TAP, то ваш вариант использования, включая хорошее резюме тестов, становится таким же простым, как:

perl -MTest::Harness -e 'runtests(@ARGV)' bin/rununittests

NB о втором абзаце: потенциально недавний Test::Harness требуется. Кроме того, это не совсем то, что вам нужно в отношении вызова оболочки, но это должно приблизить вас к этому.

person tsee    schedule 08.06.2010

Попробуйте перенаправить дескриптор 2 (stderr) на дескриптор 1 (stdout) следующим образом.

открыть UNIT_TESTER, qq(tcsh -c "gpath $dir/$tsttgt; bin/rununittests 2>&1 "|);

person BillThor    schedule 08.06.2010
comment
Это нотация оболочки Bourne/Korn/POSIX/Bash; не «tcsh», если он не претерпел серьезных изменений. - person Jonathan Leffler; 08.06.2010

На ум приходят два варианта (как минимум):

open UNIT_TESTER, qq(tcsh -c "gpath $dir/$tsttgt >&;  bin/rununittests >& "|);

и

open UNIT_TESTER, qq(sh -c "{ gpath $dir/$tsttgt;  bin/rununittests; } 2>&1"|);

Второй - обман; он использует нотацию оболочки Bourne/Korn/POSIX/Bash. Обратите внимание, что если вы не будете осторожны, вы получите вывод ошибки только второй команды, а не первой.

person Jonathan Leffler    schedule 08.06.2010
comment
@mikelong: Если вы считаете, что это должен быть tcsh, то вас нужно отправить искать Программирование оболочки C считается вредным. Кроме того, с осторожностью вы можете использовать: qq(tcsh -c "sh -c '{ ... ; } 2>&1'"|_;, который использует tcsh для запуска sh для захвата вывода. Если вы будете осторожны, вы также можете использовать «exec». - person Jonathan Leffler; 08.06.2010

Благодаря BillThor я наткнулся на решение:

open UNIT_TESTER, qq(tcsh -c "gpath $dir/$tsttgt;  bin/rununittests |& cat "|);
person mikelong    schedule 08.06.2010
comment
Нет, это не так, но на самом деле мне нужен только результат второй команды. - person mikelong; 08.06.2010