Как я могу проверить возвращаемое значение/статус выхода perl -MCPAN -e?

В настоящее время я пишу программу установки для своей компании, чтобы мы могли легко настраивать новые машины. Одна его часть представляет собой серию модулей CPAN, которые устанавливаются с помощью отдельных perl -MCPAN -e 'install "Module::Name"' команд. Я сделал массив модулей (около 200), который устанавливается через цикл foreach в скрипте bash. Однако теперь я хочу проверить статус выхода установки модуля перед запуском новой, возможно ли это? Вот что я пробовал до сих пор:

for i in "${CPANmodules[@]}"
do
    echo -e "\033[1;32mInstalling CPAN module $i \033[0m"
    perl -MCPAN -e "install \"$i\""
    if [ $? -ne 0 ]
    then
        echo "Error installing module $i"
    fi
done

Я также пробовал следующее, но безуспешно:

perl -MCPAN -e 'install "Madeup::Modulename"'
perl -e 'print $?'

Однако это всегда возвращает 0, даже если модуль даже не существует.

Любая помощь будет оценена по достоинству.


person Bifrost    schedule 15.09.2014    source источник
comment
Просто предположение: вы можете сделать 'install "Madeup::Modulename" or exit 1'?   -  person Tom Fenech    schedule 15.09.2014
comment
Отличное предложение, но оно ничего не меняет.   -  person Bifrost    schedule 15.09.2014
comment
Быстрый тест здесь с предложением от @TomFenech работал на моем компьютере с CentOS 5 (после того, как я выполнил настройку CPAN, поскольку я никогда раньше не использовал его на этом компьютере).   -  person Etan Reisner    schedule 15.09.2014
comment
Он по-прежнему возвращает 0 для меня. Вы использовали точный синтаксис, опубликованный Томом?   -  person Bifrost    schedule 15.09.2014


Ответы (2)


Вы можете использовать команду failed, чтобы отобразить все модули, которым не удалось выполнить make, test или install. в текущем сеансе. К сожалению, failed не возвращает количество ошибок, а просто выводит результаты в STDOUT.

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

perl -MCPAN -wE '
    CPAN::Shell->install("Foo::Bar");
    open my $buffer, ">", \my $failed or die $!;
    my $stdout = select $buffer;
    CPAN::Shell->failed;
    select $stdout;
    close $buffer;
    exit 1 unless $failed =~ /Nothing failed in this session/'

(Код для перенаправления STDOUT на переменную, взятую из ответа simbabque на другой вопрос SO)

Обратите внимание, что если модуль не найден в CPAN, это вернет ноль, поскольку он даже не дойдет до фазы make.

Вы также можете использовать команду uptodate, которая возвращает 1, если указанный модуль установлен и обновлен:

perl -MCPAN -wE '
    $name = "Foo::Bar";
    CPAN::Shell->install($name);
    $mod = CPAN::Shell->expandany($name);
    exit(! defined $mod || ! $mod->uptodate)'

Конечно, это не сработает, если вы устанавливаете более старые версии модулей (и я не уверен насчет разрабатываемых версий).


Если вы хотите попробовать другой установщик, cpanm фактически возвращает разумные значения: 0 для успешных установок и обновления, 1 для модулей, которые не найдены или не могут быть установлены.

person ThisSuitIsBlackNot    schedule 15.09.2014
comment
Спасибо за Ваш ответ. Думаю, мне придется переключиться на cpanm, если я хочу получить ту функциональность, которую планировал. - person Bifrost; 16.09.2014
comment
@Bifrost Лично я предпочитаю cpanm, потому что, среди прочего, он намного менее многословен, чем cpan по умолчанию. - person ThisSuitIsBlackNot; 16.09.2014

Используйте эту форму метода установки CPAN

sudo perl -MCPAN -e 'CPAN::Shell->install("Devel::Cover") or exit 18'
person edem    schedule 15.09.2014
comment
Изменить: это всегда возвращает 18. Пробовал с вымышленным именем, модулем, который уже был установлен, и модулем, который еще не был установлен (но был успешно установлен). Всего вернулось 18. - person Bifrost; 15.09.2014
comment
Отредактировал мой предыдущий комментарий. Спасибо за ваш ответ. - person Bifrost; 15.09.2014