Perl'系统'失败消息

时间:2010-05-10 21:58:04

标签: perl

说我有这个名为simple.pl的perl“程序”:

#!/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);

对于系统和反引号,我收到此消息:

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通过说简单不存在来回应。这是一个误导性的信息。

如果我有办法甚至捕获可能是开始的编译消息。

7 个答案:

答案 0 :(得分:6)

这意味着系统无法在PATH上找到名为“simple.pl”的可执行文件。如果simple.pl在当前目录中,您可以尝试将“simple.pl”更改为“./simple.pl”。

实际上,我没有看到如何使这条消息更具描述性。如果你是perl,你会如何报告此错误?

顺便说一句,我不会尝试从simple2.pl内部运行“simple2.pl”:)

答案 1 :(得分:3)

是的,检查文件是否存在且是否可执行,如果不存在,则打印更具描述性的消息。

unless (-ex $filename) {
  print "I am unable to execute file $filename.";
}

答案 2 :(得分:2)

如果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";
}

如果要取消程序中的消息,则需要在使用system()启动程序之前重定向STDOUT,STDERR。

或使用IPC::System::Simple之类的内容 或IPC :: Open3(在核心)。

答案 3 :(得分:1)

启用warnings pragma的奖励积分!有一个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
   $?
  最后一次管道关闭,反引号命令,成功调用waitwaitpidsystem运算符返回的状态。

$?为零时,表示成功。

请记住,warnings编译指示是词法,因此,不是禁用整个程序的警告,而是只为一个子程序执行此操作:

sub calculate_abc {
  no warnings 'exec';

  # ...
}

答案 4 :(得分:1)

如果你试图执行一些你知道的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变量,它包含正在运行的解释器的文件名。

答案 5 :(得分:0)

我有完全相同的问题并且发现没有安装perl。所以bash脚本试图在没有解释器的情况下执行perl。

ls /usr/bin/perl

答案 6 :(得分:0)

尝试指定“ simple.pl”文件的完整路径。