Что такое команда eval в bash?
eval является частью POSIX. Это интерфейс, который может быть встроенным в оболочку.
Он примет аргумент и создаст его команду, которая будет выполняться оболочкой. Вот пример справочной страницы:
Это распространенная функция во многих языках, например, Perl и JavaScript. Посмотрите на perldoc eval для других примеров: http://perldoc.perl.org/functions/eval.html
Оболочка пытается выполнить echo и VAR=value две отдельные команды. Выдает ошибку о второй строке. Назначение остается неэффективным.
Последнее, но не менее важное, eval может быть очень опасной командой. Любой ввод в eval команду должен быть тщательно проверен, чтобы избежать проблем безопасности.
eval не имеет man-страницы, потому что это не отдельная внешняя команда, а скорее встроенная оболочка, то есть команда, внутренняя и известная только shell ( bash ). Соответствующая часть bash справочной страницы гласит:
Кроме того, вывод, если help eval это:
eval это мощная команда, и если вы намереваетесь ее использовать, вы должны быть очень осторожны, чтобы не допустить возможных рисков безопасности, связанных с ней.
Оператор eval говорит оболочке принять аргументы eval в качестве команды и выполнить их через командную строку. Это полезно в ситуации как ниже:
В вашем скрипте, если вы определяете команду в переменную, а затем хотите использовать эту команду, тогда вы должны использовать eval:
Что такое Eval?
Термин «встроенный» подразумевает, что оболочка может запускать утилиту напрямую и не нуждается в ее поиске.
Что оно делает?
Как оно это делает?
На шаге 6 будет выполнен встроенный.
На шаге 6 eval вызывает отправку обработанной строки обратно на шаг 1.
Это единственное условие, при котором последовательность выполнения возвращается назад.
Эффекты разбора дважды.
Первый.
Удаление цитаты всегда должно выполняться последним.
Таким образом, всегда есть один уровень цитирования удален.
Во-вторых.
Как следствие этого первого эффекта, дополнительные / различные части строки становятся доступными для разбора оболочки и всех других шагов.
Пример.
Косвенность.
Что позволяет выполнять косвенные расширения:
Чтобы «увидеть», что eval будет производить в первом цикле (чтобы его можно было снова оценить), используйте echo. Или любая команда / скрипт / программа, которая четко показывает аргументы:
Замените eval на echo, чтобы «увидеть», что происходит:
Также можно показать все «части» строки с помощью:
В этом примере это только одно эхо и одна переменная, но помните об этом, чтобы помочь в оценке более сложных случаев.
Исправление
Надо сказать, что: в приведенном выше коде есть ошибка, вы это видите?
Легко: отсутствуют некоторые цитаты.
Как? Вы можете спросить. Все просто, давайте изменим переменные (не код):
Если это не убедит вас, попробуйте это:
Почему?
Отсутствующие цитаты. Чтобы он работал правильно (добавьте внутренние «$a» и внешние \» кавычки).
Попробуйте это (совершенно безопасно):
О руководстве:
Более простой способ получить помощь: в bash вы можете help eval обратиться за помощью к встроенному.
Почему Эвал называют злом?
Потому что это привязка текста к коду динамически.
Другими словами: он преобразует список своих аргументов (и / или расширений таких аргументов) в исполняемую строку. Если по какой-либо причине злоумышленник установил аргумент, вы будете выполнять код злоумышленника.
Или даже проще, с помощью eval вы говорите, кто бы ни определил значение одного или нескольких аргументов:
Да ладно, сядь здесь и набери любую командную строку, я выполню ее своими силами.
Это опасно? Всем должно быть ясно, что это так.
Правило безопасности для eval должно быть таким:
Выполняйте eval только для переменных, которым вы дали его значение.
В оболочках это реализовано как встроенная команда оболочки.
По сути, eval принимает строку в качестве аргумента и оценивает / интерпретирует код в ней. В оболочках eval может принимать более одного аргумента, но eval просто объединяет их для формирования строки для оценки.
Он очень мощный, потому что вы можете динамически создавать код и запускать его, чего вы не можете делать в скомпилированных языках, таких как C.
Но это также опасно, так как важно очистить динамические (предоставляемые извне) части того, что передается, по eval той причине, что это интерпретируется как шелл-код.
Злобность eval часто преувеличивается.
ОК, это опасно, но, по крайней мере, мы знаем, что это опасно.
Команда eval в Bash и ее типичное использование
После чтения справочных страниц bash и в отношении этого сообщения.
Мне все еще трудно понять, что именно делает команда eval и которая будет ее типичным использованием. Например, если мы делаем:
Что именно происходит здесь и как знак доллара и обратная косая черта связаны с проблемой?
eval принимает строку в качестве аргумента и оценивает ее так, как если бы вы набрали эту строку в командной строке. (Если вы передаете несколько аргументов, они сначала соединяются с пробелами между ними.)
$ <$n>является синтаксической ошибкой в bash. Внутри фигурных скобок вы можете иметь только имя переменной с некоторыми префиксами и суффиксами, но вы не можете иметь произвольный синтаксис bash и, в частности, вы не можете использовать расширение переменной. Существует способ сказать “значение переменной, имя которой находится в этой переменной”, хотя:
Просто подумайте об eval как о “оценке вашего выражения за одно дополнительное время до выполнения”
Итак, eval сначала оценит (путем оценки здесь я имею в виду заменяющие переменные, заменяю экранированные символы правильными и т.д.), а затем снова запустите результирующее выражение.
eval используется, когда вы хотите динамически создавать переменные или читать выходы из программ, специально предназначенных для чтения следующим образом. См. http://mywiki.wooledge.org/BashFAQ/048. Ссылка также содержит некоторые типичные способы использования eval и связанные с ней риски.
По моему опыту, “типичное” использование eval – это запуск команд, которые генерируют команды оболочки для установки переменных среды.
Возможно, у вас есть система, которая использует набор переменных среды, и у вас есть script или программа, которая определяет, какие из них должны быть установлены, и их значения. Всякий раз, когда вы запускаете script или программу, он запускается в разветвленном процессе, поэтому все, что он делает непосредственно с переменными среды, теряется при выходе. Но script или программа может отправлять команды экспорта в стандартный вывод.
Без eval вам нужно будет перенаправить stdout в временный файл, указать временный файл и затем удалить его. С помощью eval вы можете просто:
Обратите внимание, что цитаты важны. Возьмите этот (надуманный) пример:
Оператор eval сообщает оболочке принимать аргументы evals как команду и запускать их через командную строку. Это полезно в ситуации, как показано ниже:
В вашем script, если вы определяете команду в переменной, а позже вы хотите использовать эту команду, вы должны использовать eval:
Оператор bash eval позволяет выполнять строки кода, рассчитанные или полученные, вашим скриптом bash.
Возможно, самым простым примером будет программа bash, которая открывает другой скрипт bash в виде текстового файла, читает каждую строку текста и использует eval для их выполнения по порядку. Это по сути то же поведение, что и source оператор bash, и это то, что можно было бы использовать, если бы не было необходимости выполнять какое-либо преобразование (например, фильтрацию или подстановку) в содержимом импортированного скрипта.
eval концептуально прост. Однако строгий синтаксис языка bash и порядок разбора интерпретатора bash могут быть нюансированы и сделать eval кажутся загадочными и трудными в использовании или понимании. Вот основные положения:
Аргумент, переданный eval представляет собой строковое выражение, которое вычисляется во время выполнения. eval выполнит окончательный анализируемый результат своего аргумента как фактическую строку кода в вашем скрипте.
Синтаксис и порядок синтаксического анализа строгие. Если результат не является исполняемой строкой кода bash, в рамках вашего сценария программа выйдет из eval выражении eval когда пытается выполнить мусор.
При тестировании вы можете заменить выражение eval echo и посмотреть, что отображается. Если это законный код в текущем контексте, выполнение его через eval будет работать.
Следующие примеры могут помочь выяснить, как работает eval…
eval перед “нормальным” кодом является NOP
Выполните назначение var с использованием имен переменных, переданных как строковые значения.
Это, будучи окончательным результатом синтаксического анализа строк, является тем, что будет выполнено eval, следовательно, результат выражения echo в конце…
Добавление большего количества ссылок на пример 2
Вышеприведенное несколько сложнее, чем предыдущий пример, в большей степени полагаясь на порядок синтаксического анализа и особенности bash. Строка eval будет грубо обрабатываться внутренне в следующем порядке (обратите внимание, что следующие утверждения представляют собой псевдокод, а не настоящий код, чтобы попытаться показать, как инструкция будет разбита на внутренние шаги, чтобы получить конечный результат).
Если принятый порядок синтаксического анализа не объясняет, что делает eval, третий пример может более подробно описать синтаксический анализ, чтобы разъяснить, что происходит.
Узнайте, содержат ли строки, чьи имена содержатся в строках, строковые значения.
На первой итерации:
Я изначально намеренно не узнал, как использовать eval, потому что большинство людей рекомендуют держаться подальше от него, как чума. Однако недавно я обнаружил прецедент, который заставил меня facepalm не признать его раньше.
Если у вас есть задания cron, которые вы хотите запустить интерактивно для тестирования, вы можете просмотреть содержимое файла с помощью cat, а также скопировать и вставить задание cron для его запуска. К сожалению, это касается касания мыши, что является грехом в моей книге.
Допустим, у вас есть работа cron в /etc/cron.d/repeatme с содержимым:
*/10 * * * * root program arg1 arg2
Вы не можете выполнить это как скрипт со всем нежелательным перед ним, но мы можем использовать cut, чтобы избавиться от всего мусора, обернуть его в подоболочку и выполнить строку с eval
Команда cut выдает только 6-е поле файла, ограниченное пробелами. Затем Eval выполняет эту команду.
В качестве примера я использовал работу cron, но концепция заключается в форматировании текста из stdout, а затем для оценки этого текста.
Использование eval в этом случае не является неуверенным, потому что мы точно знаем, что мы будем оценивать перед вами.
Мне нравится “оценка вашего выражения за одно дополнительное время перед исполнением”, и я хотел бы пояснить в другом примере.
Любопытные результаты в Варианте 2 состоят в том, что мы бы передали 2 параметра следующим образом:
Как это для счетчика интуитивно понятным? Дополнительный eval будет исправлять это.
выводит ошибки, утверждая, что файлы a и tty не существуют. Я понял, что это означает, что tty не интерпретируется перед выполнением grep, но вместо этого bash передал tty в качестве параметра grep, который интерпретировал его как имя файла.
Существует также ситуация вложенного перенаправления, которая должна обрабатываться согласованными скобками, которые должны указывать дочерний процесс, но bash является примитивным разделителем слов, создавая параметры для отправки в программу, поэтому круглые скобки не сопоставляются сначала, но интерпретируется как увиденный.
Я определился с grep и задал файл как параметр вместо использования канала. Я также упростил базовую команду, передав вывод из команды в виде файла, так что i/o piping не будет вложен:
на самом деле не требуется, но устраняет вложенную трубу и также хорошо работает.
В заключение, bash, похоже, не похож на вложенное pipping. Важно понимать, что bash не является новой волновой программой, написанной рекурсивным образом. Вместо этого bash представляет собой старую программу 1,2,3, которая добавлена с функциями. В целях обеспечения обратной совместимости первоначальный способ интерпретации никогда не был изменен. Если bash было переписано в скобки первого совпадения, сколько ошибок было бы введено во сколько программ bash? Многие программисты любят быть загадочными.
Недавно мне пришлось использовать eval для того, чтобы заставить несколько расширений расширений быть оцененными в том порядке, в котором я нуждался. Bash делает несколько расширений фигурных скобок слева направо, поэтому
но мне понадобилось второе расширение скобки, сделанное первым, уступая
Лучшее, что я мог придумать, чтобы это сделать
Может быть какая-то хитроумная схема, включающая вложенные расширения расширений, что позволяет это произойти за один шаг, но если я слишком стар и глуп, чтобы увидеть это.
Вы спрашивали о типичных целях.
Одна общая жалоба на сценарии оболочки – это то, что вы (якобы) не можете передавать по ссылке, чтобы вернуть значения из функций.
Но на самом деле, через “eval”, вы можете пройти по ссылке. Вызывающий может передать список назначений переменных, которые будут оцениваться вызывающим. Он передается по ссылке, потому что вызывающий может разрешать указывать имя (имена) результирующей переменной (ей) – см. Пример ниже. Результатам ошибок могут быть возвращены стандартные имена, такие как errno и errstr.
Вот пример прохождения по ссылке в bash:
Результат выглядит следующим образом:
В этом текстовом выходе существует почти неограниченная ширина полосы! И есть больше возможностей, если используются несколько выходных строк: например, первая строка может использоваться для назначений переменных, вторая для непрерывного “потока мысли”, но выходит за рамки этой публикации.
команда eval в Bash и ее типичное использование
Что именно здесь происходит, и как знак доллара и обратная косая черта связаны с проблемой?
eval принимает строку в качестве аргумента и оценивает ее так, как если бы вы ввели эту строку в командной строке. (Если вы передаете несколько аргументов, они сначала объединяются с пробелами между ними.)
$ <$n>— это синтаксическая ошибка в bash. Внутри фигурных скобок у вас может быть только имя переменной с некоторыми возможными префиксами и суффиксами, но вы не можете иметь произвольный синтаксис bash и, в частности, вы не можете использовать расширение переменных. Есть способ сказать «значение переменной, имя которой находится в этой переменной», хотя:
Просто думайте о eval как о «оценке вашего выражения еще один раз перед выполнением»
Поэтому eval сначала оценит (под оценкой здесь я подразумеваю замену переменных, замену экранированных символов на правильные и т.д.), А затем снова запускаю результирующее выражение.
eval используется, когда вы хотите динамически создавать переменные или читать выходные данные программ, специально предназначенных для чтения таким образом. См. http://mywiki.wooledge.org/BashFAQ/048 для примеров. Ссылка также содержит некоторые типичные способы использования eval и риски, связанные с этим.
Возможно, у вас есть система, которая использует набор переменных среды, и у вас есть сценарий или программа, которая определяет, какие из них следует установить, и их значения. Каждый раз, когда вы запускаете скрипт или программу, он запускается в разветвленном процессе, поэтому все, что он делает непосредственно с переменными среды, теряется при выходе. Но этот скрипт или программа может отправлять команды экспорта в stdout.
Без eval вам нужно будет перенаправить стандартный вывод во временный файл, создать временный файл и затем удалить его. С eval вы можете просто:
Обратите внимание, что цитаты важны. Возьмите этот (надуманный) пример:
Оператор eval говорит командной консоли принять аргументы eval в качестве команды и выполнить их через командную строку. Это полезно в ситуации как ниже:
В вашем сценарии, если вы определяете команду в переменную, а затем хотите использовать эту команду, вам следует использовать eval:
Оператор bash eval позволяет вам выполнять строки кода, рассчитанные или полученные вашим bash-скриптом.
eval концептуально прост. Однако строгий синтаксис языка bash и порядок синтаксического анализа интерпретатора bash могут привести к нюансам, что сделает eval загадочным, сложным в использовании или понимании. Вот основы:
Синтаксис и порядок разбора являются строгими. Если результат не является исполняемой строкой кода bash, в рамках вашего скрипта программа завершится сбоем в операторе eval при попытке выполнить мусор.
оператор eval перед «нормальным» кодом является NOP
Выполните присваивание переменных, используя имена переменных, переданные в виде строковых значений.
Добавим больше косвенности к примеру 2
Вышесказанное немного сложнее, чем в предыдущем примере, в большей степени опираясь на порядок синтаксического анализа и особенности bash. Строка eval будет грубо проанализирована внутри в следующем порядке (обратите внимание, что следующие операторы являются псевдокодом, а не реальным кодом, просто чтобы попытаться показать, как оператор будет разбит на шаги внутри для достижения конечного результата).
Если предполагаемый порядок синтаксического анализа не объясняет, что eval делает достаточно, третий пример может описать синтаксический анализ более подробно, чтобы помочь прояснить, что происходит.
Узнайте, содержат ли переменные, чьи names содержатся в строках, сами значения строк.
На первой итерации:
Изначально я намеренно никогда не изучал, как использовать eval, потому что большинство людей будут рекомендовать держаться подальше от него, как от чумы. Однако недавно я обнаружил случай использования, который заставил меня помазать лицо за то, что я не узнал его раньше.
Если у вас есть задания cron, которые вы хотите запустить для тестирования в интерактивном режиме, вы можете просмотреть содержимое файла с помощью cat, а затем скопировать и вставить задание cron для его запуска. К сожалению, это касается прикосновения мыши, что является грехом в моей книге.
Допустим, у вас есть работа cron по адресу /etc/cron.d/repeatme с содержимым:
*/10 * * * * root program arg1 arg2
Вы не можете выполнить это как скрипт со всем мусором перед ним, но мы можем использовать cut, чтобы избавиться от всего мусора, обернуть его в подоболочку и выполнить строку с помощью eval
Команда cut распечатывает только 6-е поле файла, разделенное пробелами. Затем Eval выполняет эту команду.
В качестве примера я использовал задание cron, но концепция заключается в том, чтобы отформатировать текст из stdout, а затем оценить этот текст.
Использование eval в этом случае небезопасно, потому что мы точно знаем, что будем оценивать заранее.
Вы спрашивали о типичных целях.
Одна из распространенных претензий к сценариям Shell заключается в том, что вы (предположительно) не можете перейти по ссылке, чтобы получить значения из функций.
Вот пример передачи по ссылке в bash:
Вывод выглядит так:
но мне нужно было сделать второе расширение скобки первым, давая
Лучшее, что я мог придумать, чтобы сделать это, было
Может быть какая-то хитрая схема с использованием вложенных фигурных скобок, которая позволяет этому происходить за один шаг, но если это так, я слишком стар и глуп, чтобы это увидеть.
Мне нравится ответ «оцениваю свое выражение за один раз до исполнения», и я хотел бы уточнить на другом примере.
Любопытные результаты в варианте 2 заключаются в том, что мы передали бы 2 параметра следующим образом:
Как это для счетчика интуитивно? Дополнительный eval это исправит.
выводит ошибки, утверждая, что файлы a и tty не существуют. Я понял, что это означает, что tty не интерпретируется перед выполнением grep, а вместо этого bash передает tty в качестве параметра grep, который интерпретирует его как имя файла.
Существует также ситуация с вложенным перенаправлением, которое должно обрабатываться соответствующими скобками, которые должны указывать дочерний процесс, но bash примитивно является разделителем Word, создавая параметры для отправки в программу, поэтому круглые скобки не сопоставляются первыми, а интерпретируются как видел.
Я получил конкретный с grep, и указал файл в качестве параметра вместо использования канала. Я также упростил базовую команду, передавая выходные данные из команды в виде файла, так что трубопровод ввода-вывода не будет вложенным:
не очень желательно, но устраняет вложенную трубу, а также хорошо работает.
Что такое команда eval в bash?
eval является частью POSIX. Его интерфейс, который может быть встроенной оболочкой.
Его описание описано в «Руководстве программиста POSIX»: http://www.unix.com/man-page/posix/1posix/eval/
Он примет аргумент и построит его команду, которая будет выполнена оболочкой. Это пример manpage:
Это общая функция на многих языках, например Perl и JavaScript. Взгляните на perldoc eval для получения дополнительных примеров: http://perldoc.perl.org/functions/eval.html
Оболочка пытается выполнить echo и VAR=value виде двух отдельных команд. Это вызывает ошибку во второй строке. Назначение остается неэффективным.
И последнее, но не менее важное: eval может быть очень опасной командой. Любой вход для команды eval должен быть тщательно проверен, чтобы избежать проблем с безопасностью.
eval имеет никакой страницы man, потому что это не отдельная внешняя команда, а скорее встроенная оболочка, означающая команду, внутреннюю и известную только оболочкой ( bash ). Соответствующая часть страницы bash говорит:
Кроме того, выход, если help eval :
eval – мощная команда, и если вы намереваетесь ее использовать, вы должны быть очень осторожны, чтобы предотвратить возможные риски безопасности, которые приходят с ней.
Оператор eval сообщает оболочке принимать аргументы eval как команду и запускать их через командную строку. Это полезно в ситуации, как показано ниже:
В вашем скрипте, если вы определяете команду в переменной, а затем вы хотите использовать эту команду, вы должны использовать eval:
В оболочках он реализован как встроенная команда shell.
В принципе, eval принимает строку в качестве аргумента и вычисляет / интерпретирует код в ней. В оболочках eval может принимать несколько аргументов, но eval просто объединяет их, чтобы сформировать строку для оценки.
Это очень мощно, потому что вы можете динамически строить код и запускать его, что вы не можете сделать на скомпилированных языках, таких как C.
Но это также опасно, так как важно дезинфицировать динамические (извне предоставленные) части того, что передается eval по той причине, что оно интерпретируется как код оболочки.
Злость eval часто чрезмерно преувеличена.
Хорошо, это опасно, но, по крайней мере, мы знаем, что это опасно.
Что такое оценка?
eval – команда оболочки, которая обычно реализуется как встроенная.
Термин «встроенный» подразумевает, что оболочка может выполнить утилиту напрямую и не нуждается в ее поиске.
Что оно делает?
Проще говоря: дважды вводится строка ввода.
Как оно это делает?
Оболочка имеет последовательность шагов, которые следует «обрабатывать» строку. Вы можете посмотреть на это изображение и понять, что eval – единственная линия, которая поднимается вверх, назад к шагу 1, слева. Из описания POSIX :
На шаге 6 будет выполнен встроенный.
На шаге 6 eval заставляет обработанную строку отправлять на шаг 1.
Это единственное условие, при котором возвращается последовательность выполнения.
Эффекты разбора дважды.
Первый.
Удаление ссылок всегда должно выполняться последним.
Итак, всегда, один уровень цитирования удален.
Во-вторых.
Как следствие этого первого эффекта, дополнительные / разные части линии становятся подверженными анализу оболочки и всем остальным шагам.
Пример.
Косвенность.
Это позволяет выполнять косвенные расширения:
Чтобы «увидеть» то, что eval будет производить в первом цикле (для оценки снова), используйте эхо. Или любая команда / сценарий / программа, которая четко показывает аргументы:
Замените eval на эхо, чтобы «видеть», что происходит:
Также можно показать все «части» строки:
Который в этом примере является только одним эхом и одной переменной, но помните, что он помогает в оценке более сложных случаев.
Коррекция.
Надо сказать, что: в приведенном выше коде есть ошибка, видите ли вы это?
Легко: некоторые кавычки отсутствуют.
Как? вы можете спросить. Простой, давайте изменим переменные (а не код):
Если это вас не убедит, попробуйте следующее:
Зачем?
Отсутствующие котировки. Чтобы он работал корректно (добавьте внутренние «$a» и внешние \» цитаты.
Попробуйте это (совершенно безопасно):
О руководстве:
Более простой способ получить помощь: В bash вы можете help eval чтобы увидеть помощь для встроенного.
Почему eval называется злом?
Потому что он является обязательным текстом для кодирования динамически.
Другими словами: он преобразует список своих аргументов (и / или расширений таких аргументов) в выполненную строку. Если по какой-либо причине аргумент был установлен злоумышленником, вы будете выполнять код злоумышленника.
Или даже проще, с eval вы говорите тому, кто определил значение одного или нескольких аргументов:
C’mon, сидите здесь и вводите любую командную строку, я исполню ее своими силами.
Это опасно? Должно быть ясно, для всех, кто это.
Правила безопасности для eval должны быть:
Выполняйте eval только для переменных, которым вы присвоили значение.



