Perl «системные» сообщения об ошибках - PullRequest
1 голос
/ 11 мая 2010

Скажем, у меня есть эта "perl" программа на perl, которая называется simple.pl:

#!/usr/bin/perl
use xyz; # xyz is bogus and doesn't exist

И у меня также есть эта "программа", которая называется simple2.pl:

#!/usr/bin/perl
system("simple.pl");

my $abc = `simple.pl`;
printf("abc %s\n", $abc);

для системы и backtick, я получаю это сообщение:

Can't exec "simple.pl": No such file or directory at scripts/perl/simple2.pl line 7.
Can't exec "simple.pl": No such file or directory at scripts/perl/simple2.pl line 9.

Не очень полезно для пользователя, вызывающего simple2.pl. Есть ли способ получить более полезное сообщение?

Примечание. simple.pl существует в текущем каталоге. Настоящая проблема в том, что simple.pl не компилируется. simple2 отвечает, что simple не существует. это вводящее в заблуждение сообщение.

Если бы у меня был способ даже захватить сообщение компиляции, это было бы началом.

Ответы [ 6 ]

6 голосов
/ 11 мая 2010

Это означает, что система не может найти исполняемый файл с именем "simple.pl" в вашей переменной PATH. Если ваш simple.pl находится в текущем каталоге, вы можете попробовать изменить «simple.pl» на «./simple.pl».

На самом деле, я не вижу, как сделать это сообщение более информативным. Если бы вы были Perl, как бы вы сообщили об этой ошибке?

Кстати, я бы не стал запускать "simple2.pl" из simple2.pl:)

3 голосов
/ 11 мая 2010

Да, проверьте, существует ли файл и является ли он исполняемым, а если нет, напечатайте более описательное сообщение.

unless (-ex $filename) {
  print "I am unable to execute file $filename.";
}
2 голосов
/ 11 мая 2010

Если Perl сообщает, что не может найти файл, значит, он не может найти файл. И проблема больше в вашем коде. Посмотрите на этот пример.

sidburn@sid:~/perl$ cat test.pl 
#!/usr/bin/env perl
use strict;
use warnings;
use xyz;
sidburn@sid:~/perl$ cat test2.pl 
#!/usr/bin/env perl
use strict;
use warnings;
system('test.pl');
sidburn@sid:~/perl$ cat test3.pl 
#!/usr/bin/env perl
use strict;
use warnings;
system('./test.pl');

Если вы выполните test2.pl, вы получите:

sidburn@sid:~/perl$ ./test2.pl 
Can't exec "test.pl": No such file or directory at ./test2.pl line 4.

Если вы выполните test3.pl, вы получите:

sidburn@sid:~/perl$ ./test3.pl 
Can't locate xyz.pm in @INC (@INC contains: /home/sidburn/perl510/lib/5.10.1/i686-linux /home/sidburn/perl510/lib/5.10.1 /home/sidburn/perl510/lib/site_perl/5.10.1/i686-linux /home/sidburn/perl510/lib/site_perl/5.10.1 .) at ./test.pl line 4.
BEGIN failed--compilation aborted at ./test.pl line 4.

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

Вам необходимо указать «./», если он находится в текущем каталоге. Но обратите внимание, что «текущий каталог» не означает каталог, к которому относится ваш скрипт.

Если вы хотите позже, вы, вероятно, захотите сделать

use FindBin;

с этим вы можете сделать что-то вроде этого:

#!/usr/bin/env perl
use strict;
use warnings;
use FindBin;
use File::Spec::Functions;

my $exe = catfile($FindBin::RealBin, 'test.pl');

print $exe, "\n";
system($exe);

Если вы хотите проверить, правильно ли возвращается система, вам нужно проверить возвращаемое значение из команды system () или $? позже это содержит значение.

if ( $? != 0 ) {
    die "Cannot execute $exe.\n";
}

если вы хотите подавить сообщения из вашей программы, вам нужно перенаправить STDOUT, STDERR перед запуском вашей программы с помощью system ().

Или используйте что-то вроде IPC :: System :: Simple Или IPC :: Open3 (в основном).

1 голос
/ 11 мая 2010

Если вы пытаетесь выполнить что-то, что, как вы знаете, является скриптом Perl, почему бы не вызвать интерпретатор напрямую, а не иметь дело с системой, которая знает, как выполнить файл?

my $file = 'simple.pl';

-e $file or die "file '$file' not found";

system "perl $file";
# or
print `perl $file`;

для запуска с той же установкой perl, на которой запущен ваш текущий скрипт:

 system "$^X $file";   # or `$^X $file`

$^X - это специальная переменная Perl, которая содержит имя файла работающего интерпретатора.

1 голос
/ 11 мая 2010

Бонусные баллы за включение warnings прагмы! Имейте upvote!

Вы хотите использовать обратные метки или qx// для захвата вывода внешней программы, а не system. Чтобы заменить ваше собственное сообщение об ошибке, которое будет иметь смысл для ваших пользователей (больше очков за вас!), Вы можете сделать что-то, как в

#! /usr/bin/perl

use strict;
use warnings;
no warnings 'exec';

chomp(my $abc = `simple2.pl`);
if ($? == 0) {
  printf("abc %s\n", $abc);
}
else {
  die "$0: unable to calculate abc\n";
}

Если вы незнакомы, $? - это

$ CHILD_ERROR
$
Статус, возвращаемый последним закрытием канала, командой backtick, успешным вызовом wait или waitpid или оператором system.

Когда $? равно нулю, это означает успех.

Помните, что прагма warnings является лексической, поэтому вместо отключения предупреждения для всей программы вы можете сделать это только для одной подпрограммы:

sub calculate_abc {
  no warnings 'exec';

  # ...
}
0 голосов
/ 25 мая 2016

У меня была точно такая же проблема, и я понял, что Perl не установлен. Таким образом, bash-скрипт пытался выполнить Perl без интерпретатора.

ls /usr/bin/perl

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