【问题标题】:Executing a bash script from a Perl program从 Perl 程序执行 bash 脚本
【发布时间】:2015-07-08 06:52:37
【问题描述】:

我正在尝试编写一个执行 bash 脚本的 Perl 程序。 Perl 脚本如下所示

#!/usr/bin/perl

use diagnostics;
use warnings;

require 'userlib.pl';
use CGI qw(:standard); 

ReadParse();

my $q = new CGI;
my $dir = $q->param('X');
my $s = $q->param('Y');

ui_print_header(undef, $text{'edit_title'}.$dir, "");

print  $dir."<br>";
print  $s."<br>";
print "Under Construction <br>";

use Cwd;
my $pwd = cwd();
my $directory = "/Logs/".$dir."/logmanager/".$s;
my $command = $pwd."/script ".$directory."/".$s.".tar";

print $command."<br>";
print $pwd."<br>";

chdir($directory);
my $pwd1 = cwd();
print $pwd1."<br>";

system($command, $directory) or die "Cannot open Dir: $!";

脚本失败并出现以下错误:


Can't exec "/usr/libexec/webmin/foobar/script
    /path/filename.tar": No such file or directory at /usr/libexec/webmin/foobar/program.cgi line 23 (#3)
(W exec) A system(), exec(), or piped open call could not execute the
named program for the indicated reason.  Typical reasons include: the
permissions were wrong on the file, the file wasn't found in
$ENV{PATH}, the executable in question was compiled for another
architecture, or the #! line in a script points to an interpreter that
can't be run for similar reasons.  (Or maybe your system doesn't support #!                  at all.)        

我检查了权限是否正确,我传递给我的 bash 脚本的 tar 文件存在,并且还尝试从命令行运行我尝试从 Perl 脚本运行的相同命令(@ 987654323@ ) 并且它工作正常。

【问题讨论】:

  • 你写过你已经检查了权限,但只是为了澄清一下:执行/usr/libexec/webmin/foobar/script的用户是否也有执行权限?您是否也检查了有关 shebang (#!) 的建议?例如,如果脚本以#!/bin/bash 开头,则检查/bin/bash 是否存在且可执行。
  • 检查了这一切,正如我所说,如果我从命令行运行相同的工作正常
  • 请在系统调用前加上-f or die qq{File "$_" doesn't exist} for $command, $directory;并报告结果

标签: linux bash perl shell


【解决方案1】:

在 Perl 中,使用一个参数(在标量上下文中)调用 system 并使用多个标量参数(在列表上下文中)调用它会执行 different things。

在标量上下文中,调用

system($command)

将启动一个外部shell并在其中执行$command。如果$command 中的字符串有参数,它们也会被传递给调用。比如

$command="ls /";
system($commmand);

将评估为

sh -c "ls /"

shell 给出了整个字符串,即带有所有参数的命令。此外,$command 将在设置所有正常环境变量的情况下运行。这可能是一个安全问题,请参阅 here 和 here 了解其中的几个示例。

另一方面,如果你用数组调用系统(在列表上下文中),Perl 不会调用 shell 并给它$command 作为参数,而是尝试直接执行数组的第一个元素并给它其他参数作为参数。所以

$command = "ls";
$directory = "/";
system($command, $directory);

将直接调用ls,而不会在两者之间产生一个shell。

回到你的问题:你的代码说

my $command = $pwd."/script ".$directory."/".$s.".tar";
system($command, $directory) or die "Cannot open Dir: $!";

注意这里的$command 类似于/path/to/script /path/to/foo.tar,参数已经是字符串的一部分。如果你在标量上下文中调用它

system($command)

一切都会好起来的,因为

sh -c "/path/to/script /path/to/foo.tar"

将以foo.tar 作为参数执行script。但是如果你在列表上下文中调用它,它会尝试定位一个名为/path/to/script /path/to/foo.tar的可执行文件,这会失败。

【讨论】:

    【解决方案2】:

    我发现了问题。 更改系统命令删除第二个参数,现在它正在工作

    system($command) or die "Cannot open Dir: $!";
    

    公平地说,我不明白第一个例子有什么问题,但现在工作正常,如果有人能解释一下,可能会很有趣,理解

    【讨论】:

      【解决方案3】:

      有多种方法可以在 perl 中执行 bash 命令/脚本。

      1. 系统
      2. 过时
      3. 执行

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-07-10
        • 2013-07-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-03-15
        • 2022-10-18
        • 2014-01-06
        相关资源
        最近更新 更多