2015-07-08 4 views
1

Я пытаюсь написать программу Perl, которая выполнит скрипт bash. Сценарий Perl выглядит следующим образомВыполнение скрипта bash из программы 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 существует, а также попытка из командной строки выполнить ту же команду, которую я пытаюсь запустить из скрипта Perl (/usr/libexec/webmin/foobar/script /path/filename.tar), и он работает правильно.

+0

Вы писали, что вы проверили разрешения, но только уточнить: делает пользователь, выполняющий '/ USR/libexec/Webmin/Foobar/скрипт "также имеет разрешение на выполнение? И вы также проверили предложение о shebang (#!)? Так, например, если скрипт начинается с '#!/Bin/bash', то проверить, существует ли'/bin/bash' и исполняемый файл. – fejese

+0

Проверял все это, и, как я уже сказал, если я запустил то же самое из командной строки, то отлично – Cris

+0

Пожалуйста, добавьте '-f или die qq {File" $ _ "не существует} для $ command, $ directory;' непосредственно перед системный вызов и сообщить результат – Borodin

ответ

8

В Perl вызов system с одним аргументом (в скалярном контексте) и вызов его несколькими скалярными аргументами (в контексте списка) делает different things.

В скалярном контексте вызова

system($command) 

запустит внешнюю оболочку и выполнить $command в нем. Если строка в $command имеет аргументы, они также будут переданы вызову. Так, например

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

будет вычисляться

sh -c "ls /" 

где оболочка получает всю строку, то есть команды со всеми аргументами. Кроме того, $command будет работать со всеми стандартными переменными окружения. Это может быть проблема безопасности, см. here и here для нескольких примеров.

С другой стороны, если вы вызываете систему с массивом (в контексте списка), Perl не будет вызывать оболочку и давать ей аргумент $command, а скорее попытаться выполнить первый элемент массива напрямую и дать это другие аргументы в качестве параметров. Так

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

ls будет вызывать непосредственно, без порождая оболочки между ними.

Возвращаясь к вашему вопросу: ваш код говорит

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" 

выполнит script с foo.tar в качестве аргумента. Но если вы вызовете его в контексте списка, он попытается найти исполняемый файл с именем /path/to/script /path/to/foo.tar, и это не удастся.

0

Я нашел проблему. изменил команду системы удаления второго параметра, и теперь он работает

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

В справедливости я не понимал, что случилось в первом примере, но теперь работает хорошо, если кто-нибудь может объяснить, вероятно, это может быть интересно понять

0

Существует несколько способов выполнения команды bash/скриптов в perl.

  1. Система
  2. backquate
  3. Exec
Смежные вопросы