«Правильный» способ интерпретации аргументов perl текущей оболочкой - PullRequest
0 голосов
/ 30 апреля 2018

Извините, это довольно просто, и я подозреваю дубликат, но после некоторых поисков я выхожу пустым:

С учетом следующего скрипта:

#!/usr/bin/perl
use strict;
use warnings;
use IPC::Run3;
my $stdout2;
print $ARGV[0];
print "\n";
my @cmd1 = split /\s+/,  $ARGV[0] ;
run3 (\@cmd1, \undef, \$stdout2, \$stdout2);
print $stdout2

И работает так:

£ perl comp.pl "md5sum *(.)"
md5sum *(.)
md5sum: '*(.)': No such file or directory

Достаточно справедливо. Оболочка *(.) не интерпретируется оболочкой, и, вероятно, большинство сочтет это функцией. Но я бы хотел, чтобы это интерпретировалось текущей оболочкой (или zsh определенно подойдет).

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

С добавлением "zsh" и "-c" к cmd1 все в порядке, если это разумный способ сделать это. Просто кажется, что это не так.

Мое намерение также состоит в том, чтобы в конце концов передать немного более сложные команды этому скрипту, например:

perl comp.pl 'md5sum *(.)' 'ssh remoteHost "md5sum *(.)"'

У меня нет возражений против не-Perl ответов на проблему, которую вы, вероятно, можете понять, которую я пытаюсь решить (я подозреваю, что rsync может сделать это), но я в первую очередь заинтересован в решении этого через Perl, так как в конечном счете, в этом сравнении будет логика, специфичная для бизнеса.

EDIT

Я пробовал различные формы:

my $cmd = $ARGV[0];
run3 (\$cmd, \undef, \$stdout2, \$stdout2);

документация, кажется, думает, что это будет хорошо, но я получаю:

Not an ARRAY reference at /usr/local/share/perl/5.22.1/IPC/Run3.pm line 320.

1 Ответ

0 голосов
/ 30 апреля 2018

Документы IPC :: Run3 говорят, что для команды можно передать строку вместо arrayref

run3($cmd, $stdin, $stdout, $stderr, \%options)

...

$ CMD

Обычно $ cmd будет ссылкой ARRAY, а дочерний элемент вызывается через

system @$cmd;

Но $ cmd также может быть строкой, и в этом случае дочерний элемент вызывается через

system $cmd;

В этом случае строка $cmd передается в оболочку, если она содержит метасимволы оболочки. Так что берите ввод, не разбивая его, $cmd = $ARGV[0], или присоединяйте его после проверки, $cmd = join ' ', @cmd;

Даже в целом это не предпочтительный способ, и документы предупреждают, чтобы увидеть system для " ловушек ".

Здесь все еще намного хуже, поскольку вы будете передавать пользовательский ввод непосредственно для исполнения! Не берите в голову возможные гнусные намерения, просто подумайте, что может сделать опечатка. Даже без этого существует просто разница между вводом команды в терминале и передачей ее в скрипт, который может ее редактировать, изменять, обнаруживать ошибки и т. Д.

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

Анализ может включать в себя идентификацию известных и принятых метасимволов при соответствующем цитировании частей ввода, которые не должны интерпретироваться , например, с использованием String :: ShellQuote .

Но я бы посоветовал пересмотреть проект, чтобы вы не отправляли в сценарий полные команды, а указывали с ключевыми словами, что должно произойти. Такие вещи, как глобализация (сборка списка файлов), сделаны из Perl очень красиво и с большим контролем. Делайте снаружи только то, что необходимо; как правило, тогда не будет необходимости в оболочке.

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