2017-01-09 3 views
1

Пока у меня установлены соответствующие программы - fortune не установлен по умолчанию в Ubuntu 16.04 - я могу использовать следующую команду, чтобы иметь функциональность для работы с текстом моего компьютера скажите мне, чтобы вернуться к работе, а затем прочитал мне вдохновляющие цитаты из fortune:Использовать подстановку команд с backticks внутри subprocess.call()

spd-say "get back to work and remember `fortune`" 

Здесь я использую подстановку команд с обратными кавычками, чтобы добавить результат вызова fortune команду на строку текста для чтения , В Python, я могу использовать subprocess сделать это:

subprocess.call(['spd-say', 'get back to work']) 

Однако команда замещение не обратные кавычки появляются здесь работать:

subprocess.call(['spd-say', 'get back to work and remember `fortune`']) 

В этом случае, я услышу: «вернуться работать и помнить фортуну ». Я предполагаю, что это потому, что subprocess передает строку с одной кавычкой, и такая подстановка команд работает только в строках с двойными кавычками.

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

Я также пытался писать всю команду в виде одной строки, и разорвать его с помощью shlex.split():

import shlex 
command = 'spd-say "get back to work and remember `fortune`"' 
command_args = shlex.split(command) 

Но это дает мне:

['spd-say', 'get back to work and remember `fortune`'] 

Опять же, не двойные кавычки.

Есть ли способ, чтобы заставить обернуть один аргумент в двойных кавычках (если это действительно проблема), или в противном случае труба выход команды fortune к spd-say так, как описано выше, с использованием subprocess.call()?

+1

В стороне - я настоятельно рекомендую избегать 'shlex.split()' в пользу жесткого кодирования ваших списков: как человек, вы точно знаете *, как вы хотите, чтобы они разобрались, так что вы могли бы также передать их в этом виде (также это означает, что читателю нужно только знать синтаксис синтаксиса * - синтаксис Python - vs two, Python и shell). Первый подход позволяет легко попасть в проблему, выполняя что-то вроде 'shlex.split (« your-command --file =% s »% filename)», который может расширяться до нескольких аргументов, если имя файла содержит пробелы, ['your-command', '--file =% s'% filename] ', что недвусмысленно. –

ответ

2

Расширение подстановок команд является операцией оболочки. Без shell=True, есть is no shell участвует в subprocess операций. Это очень желательно поведение в целом: если вы передаете имена файлов в качестве входных данных, вы не хотите, чтобы имя файла содержало $(rm -rf $HOME) (и да, все эти символы являются законными в именах файлов в типичных системах UNIX), чтобы вызвать удаление контента.

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

subprocess.call('spd-say "get back to work and remember $(fortune)"', shell=True) 

...что эквивалентно к следующему, безshell=True:

subprocess.call(['sh', '-c', 'spd-say "get back to work and remember $(fortune)"']) 

Кстати, если вы передаете массив с shell=True, только первый аргумент обрабатывается как сценарий (и, таким образом, имеет команду замены и т.п. выполненные расширения); другие аргументы буквальные аргументы, которые могут быть интерпретированы с помощью самого сценария:

subprocess.call(
    ['spd-say "$1 $(fortune)"',      # this is a script 
    "_",           # this is a literal for $0 in the script 
    "get back to work, don't $(rm), and remember" # this is a literal for $1 in the script 
    ], shell=True) 

$(rm) не выполняется, потому что здесь только содержание в первом элементе списка ('spd-say "$1 $(fortune)"') трактуется как текст сценария.

+0

Спасибо за ответ! Я знаю об угрозах безопасности, связанных с использованием 'shell = True', который вы даете хороший пример в своем ответе. Тем не менее, мне интересно, если в простой программе, подобной приведенной выше (для аргументов, если мой сценарий делает не что иное, как сделать этот единственный вызов subprocess.call()), существует ли еще опасность злоупотребления или эксплуатации? Единственное, о чем я могу думать, это то, что команда 'fortune' была заменена чем-то злым, так что когда' $ (фортуна) 'запускается, происходит что-то плохое, но это не кажется вероятным ... – elethan

+1

Исключая случаи, такие как shellshock, где у вас есть другие побочные эффекты от выполнения оболочки, основным риском является то, что вы подставляете ненадежный/неаудированный контент в сам сценарий скрипта. Если строка '' 'spd-say 'вернется к работе и запомнит« fortune' »,' '' hardcoded в вашем программном обеспечении, вы в полном порядке; если вы конкатенируете что-то, что вы получили от пользователя, файловой системы или иначе менее доверенного источника при ее создании, напротив, тогда вам угрожает опасность. –

+1

Это действительно такая же вещь, как SQL-инъекция - если вы генерируете SQL путем объединения или замены значений, тогда вы рискуете атаковать инъекциями; если только динамические значения передаются вне диапазона в аргументах, и ваш запрос не делает ничего необоснованного/небезопасного с этими значениями, то вы, вероятно, в порядке. Здесь речь идет о том, является ли это первым аргументом - самим сценарием - что вы подставляете значения в, или если это последующие аргументы (которые не интерпретируются как текст сценария). –

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