2009-03-06 3 views
14

При использовании вызовов system() в Perl вы должны избегать аргументов оболочки, или это делается автоматически?Должен ли я избегать аргументов оболочки в Perl?

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

+0

Что вы имеете в виду, избежать арг оболочки? Вы имеете в виду поставить перед любыми символами типа «>» или «» или вы хотите включить escaping $, чтобы люди не могли вводить ваши переменные Perl? Или что? Приведите пример того, что вы имеете в виду. –

+0

Как добавить фигурные скобки внутри Системные вызовы .... system ("$ jboss_client/subsystem = logging/size-rotating-file-handler = SAMPLE: добавить \\ (formatter = \ {yyyy \} \\)"); Я всегда получаю выход, как показано ниже. Formatter = yyyy instaed of farmatter = {yyyy}. Можете ли вы дать мне IDEA, чтобы решить эту проблему? –

ответ

37

Если вы используете system $cmd, @args вместо system "$cmd @args" (массив, а не строки), то вам не придется бежать аргументы, потому что ни оболочка не запускается (см system). system {$cmd} $cmd, @args не будет вызывать оболочку, даже если $ cmd содержит метасимволы, а @args пуст (это задокументировано как часть exec). Если аргументы поступают от ввода пользователем (или другого ненадежного источника), вы все равно захотите их разблокировать. См. -T в документах perlrun и документах perlsec.

Если вам необходимо прочитать выход или отправить ввод в команду, qx и readpipe не имеют эквивалента. Вместо этого используйте open my $output, "-|", $cmd, @args или open my $input, "|-", $cmd, @args, хотя это не переносимо, поскольку для этого требуется реальный fork, что означает только Unix ... Я думаю. Возможно, он будет работать на Windows с его симулированной вилкой. Лучший вариант - это что-то вроде IPC::Run, в котором также будут обрабатываться случаи команд трубопровода для других команд, которые не будут обрабатываться ни в форме с несколькими командами, ни в форме 4 arg open.

+3

+1 для синтаксиса I-never-registered-they-added-that-synt. Прекрасный. – chaos

+0

В качестве дополнения 'system {'cmd'} 'cmd'' всегда обходит' sh', даже если '' cmd'' содержит символы, которые обычно интерпретируются оболочкой. – ephemient

+0

Вы должны добавить, что * причина *, почему вам не нужно избегать метасимволов оболочки с помощью «system» cmd «@args», заключается в том, что в этом случае никакая оболочка не вызывается (так как OP задавал более простую оболочку, метакары будут экранированы » автоматически ", что не так). – 8jean

14

В Windows ситуация немного неприятнее. В принципе, все программы Win32 получают одну длинную строку командной строки - оболочка (обычно cmd.exe) может сначала выполнить некоторую интерпретацию, например, перераспределение , но не разделить его на границах слов для программы. Каждая программа должна выполнять этот синтаксический анализ (если они того пожелают - некоторые программы не беспокоят). В программах на C и C++ подпрограммы, предоставляемые библиотеками времени выполнения, поставляемыми с инструментальной цепочкой компилятора, обычно выполняют этот этап синтаксического анализа до вызова main().

Проблема в том, что в целом вы не знаете, как данная программа будет анализировать свою командную строку. Многие программы скомпилированы с некоторой версией MSVC++, чьи quirky parsing rules are described here, но многие другие компилируются с различными компиляторами, использующими разные соглашения.

Это усугубляется тем фактом, что у cmd.exe есть свои собственные причудливые правила синтаксического анализа. Каретка (^) рассматривается как escape-символ, который цитирует следующий символ, а текст внутри двойных кавычек рассматривается как цитируемый, если выполняется список сложных критериев (см. cmd /? для подробных подробностей). Если ваша команда содержит какие-то странные символы, очень легко понять, какие части текста «процитированы» и которые не должны синхронизироваться с вашей целевой программой, и все ад разрывается.

Таким образом, самый безопасный подход для экранирования аргументы на окнах:

  1. аргументы Побег в порядке, ожидаемые в командной строке разборе логику программы, которую вы звоните. (Надеюсь, вы знаете, что это за логика, а если нет, попробуйте несколько примеров и догадайтесь.)
  2. Соедините экранированные аргументы пробелами.
  3. Префикс каждый не-буквенно-цифровой символ полученной строки с номером ^.
  4. Приложите любые переадресации или другие обмороки оболочки (например, соединения команд с &&).
  5. Запустите команду с system() или обратными окнами.
+0

Интересная информация - спасибо. Это не подрывает Windows для этого Unixophile, но помогает узнать, что происходит за кулисами. (Ссылка на страницу немного спокойна о роли каретки, она упоминает ее, но только по исключению. Непонятно, как она обрабатывает^\ или^", например.) –

+0

Я согласен с Джонатаном Леффлером. (на мой взгляд) ужасный способ обрабатывать аргументы командной строки. –

+1

Я полностью согласен с тем, что это ужасная ситуация. Хотя справедливости ради, большая часть ужаса, вероятно, связана с похвальной преданностью MS поддерживать обратную совместимость (посмотреть, как навязчивые, они замечают отличный блог Раймонда Чена когда-нибудь.) –

0

Ответы на ваш вопрос были очень полезными. В конце я последовал за советом @ runrig, но затем использовал команду open3() основного модуля, чтобы я мог захватить вывод из STDERR, а также STDOUT.

Для образца кода open3() при работе с @ Runrig, решение которого, увидеть мой соответствующий вопрос и ответ:
Calling system commands from Perl

2
sub esc_chars { 
    # will change, for example, a!!a to a\!\!a 
    @_ =~ s/([;<>\*\|`&\$!#\(\)\[\]\{\}:'"])/\\$1/g; 
    return @_; 
    } 

http://www.slac.stanford.edu/slac/www/resource/how-to-use/cgi-rexx/cgi-esc.html

+0

Кто-нибудь знает, откуда этот список символов ? Я не мог найти это perl docs. Я бы предпочел не читать исходный код функции exec Perl, который это возможно. – MarcH

1

Если вы используете систему "$ CMD @args" (строка), вам придется избегать аргументов, потому что вызывается оболочка.

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

" - double quote 
$ - dollar 
@ - at symbol 
\ - backslash 
+0

Я думаю, что OP говорил о интерпретации оболочек, не избегая случайной интерполяции скаляров и массивов. –

Смежные вопросы