Создайте имя команды и аргументы в виде массива и передайте его системе:
my(@command) = ("trash-put", 'home/$filename');
system @command;
Это означает, что Perl не вызывает оболочку для выполнения какого-либо расширения метасимвола (или перенаправления ввода-вывода, или передачи команд, или ...). Это значит, что он делает именно то, что вы сказали.
sub execute_command_error
{
system @_;
}
Заимствование информации из обильной коллекции комментариев:
Что четко задокументировано в perldoc -f system
или в perldoc.perl.org / functions / system.html (@Ether).
(См. Также обсуждение «exec» ниже, которое тесно связано.)
Вы хотели поместить $ filename в одинарные кавычки? (@Mobrule).
Я намеревался использовать одинарные кавычки - я демонстрирую, что $filename
не раскрывается Perl или Shell ... В моем тестовом скрипте я использовал 'my.$file
', и это дало мне файл с $
в названии - как я и предполагал.
Я думаю, что желаемое цитирование, если вы действительно хотите вызвать оболочку (например, если вы хотите использовать какой-либо конвейер), это $ command_line = "\" $ command \ "\" $ arg1 \ "\" $ arg2 \ ".. . ". (@Jefromi).
Добавление двойных кавычек вокруг аргументов не поможет при использовании встроенных $
, обратного ключа 1 , '$(...)
' и связанных с ним обозначений. Вам более всего нужны одинарные кавычки вокруг вещей, но затем вам нужно переписать встроенные одинарные кавычки как «'\''
», который генерирует одинарную кавычку для завершения текущего аргумента с одинарными кавычками, комбинацию с обратной косой чертой для представления одинарной кавычки и еще одна одиночная кавычка для возобновления аргумента в одинарных кавычках.
Это было бы хорошим решением, если бы я использовал системную команду напрямую; Тем не менее, я использую функцию webmin execute_command
, которая мне не нравится, поэтому я не знаю, как ее отредактировать, чтобы учесть массивы. Не могли бы вы расширить переписывание встроенных одинарных кавычек как "'\''
" ... Это то, что я сейчас буду использовать. (@ Брайан)
Грубо говоря, оболочка (Unix) обрабатывает одинарные кавычки так: «все от первой одинарной кавычки до следующей - буквальный текст, без метасимволов». Таким образом, чтобы оболочка воспринимала что-либо как буквальный текст, заключите его в один символ. Это касается всего, кроме самих одинарных кавычек. Как говорится в моем комментарии, вы должны использовать заменяющую строку из 4 символов, чтобы вставить одинарную кавычку в середину аргумента с одинарными кавычками.
Вероятно, есть более удобный способ сделать это, чем этот (возможно, с использованием одной или двух map
операций), но это должно работать:
for (my $i = 0; $i < scalar(@command); $i++)
{
$command[$i] =~ s/'/'\\''/g; # Replace single quotes by the magic sequence
$command[$i] = "'$command[$i]'"; # Wrap value in single quotes
}
Затем вы можете присоединиться к массиву, чтобы сделать одну строку для передачи execute_command
.
Лучше написать это как system {$ command [0]} @command для обработки случая, когда @command имеет один элемент. Это одна из вещей, о которой я говорю в главе «Методы безопасного программирования» Мастеринг Perl . (@Briandfoy).
Как правило, я приму это исправление. Я не уверен, что это важно в данном случае, хотя, где имя команды предоставляется программой, и только аргументы могут быть предоставлены пользователю. Имя команды 'trash-put' защищено от расширений оболочки (IFS сбрасывается оболочкой по умолчанию при запуске, поэтому путь атаки недоступен).
Эта проблема обсуждается на справочной странице 'perldoc -f exec' :
Если вы на самом деле не хотите выполнять первый аргумент, но хотите лгать программе, которую вы выполняете, относительно ее собственного имени, вы можете указать программу, которую вы на самом деле хотите запустить, как «косвенный объект» (без запятая) перед списком. (Это всегда вызывает интерпретацию LIST как многозначного списка, даже если в списке только один скаляр.)
Пример:
$shell = '/bin/csh';
exec $shell '-sh'; # pretend it's a login shell
или, точнее,
exec {'/bin/csh'} '-sh'; # pretend it's a login shell
Когда аргументы выполняются через системную оболочку, результаты зависят от ее особенностей и возможностей. Смотрите "STRING
" в perlop для деталей.
Использование косвенного объекта в exec или system также более безопасно. Такое использование (которое также хорошо работает с system ()) вызывает интерпретацию аргументов как многозначного списка, даже если список имел только один аргумент. Таким образом вы будете защищены от расширения оболочки или разделения слов с пробелами в них.
@args = ( "echo surprise" );
exec @args; # subject to shell escapes
# if @args == 1
exec { $args[0] } @args; # safe even with one-arg list
Первая версия, без косвенного объекта, запускала программу echo, передавая ей «неожиданный» аргумент. Вторая версия не сделала; он попытался запустить программу с именем «эхо-сюрприз», не нашел ее и установил $? к ненулевому значению, указывающему на ошибку.
1 Как получить обратный тик для отображения в Markdown?