Что такое «вечная» команда в bash?

Что вы можете сделать с помощью команды eval? Почему это полезно? Это какая-то встроенная функция в bash? Для этого нет страницы man.

131 голос | спросил LanceBaynes 23 +04002011-10-23T00:02:33+04:00312011bEurope/MoscowSun, 23 Oct 2011 00:02:33 +0400 2011, 00:02:33

7 ответов


103

eval является частью POSIX. Его интерфейс, который может быть встроенной оболочкой.

Описано в «Руководстве программиста POSIX»: http://www.unix.com/человек-страница /POSIX /1posix /Eval /

eval - construct command by concatenating arguments

Он примет аргумент и построит его команду, которая будет выполнена оболочкой. Это пример manpage:

1) foo=10 x=foo
2) y='$'$x
3) echo $y
4) $foo
5) eval y='$'$x
6) echo $y
7) 10
  1. В первой строке вы определяете $foo со значением '10' и $x со значением 'foo'.
  2. Теперь определите $y, который состоит из строки '$foo'. Знак доллара должен быть экранирован с помощью '$'.
  3. Чтобы проверить результат, echo $y.
  4. Результатом будет строка '$foo'
  5. Теперь мы повторяем назначение с помощью eval. Сначала он оценит $x строку 'foo'. Теперь у нас есть оператор y=$foo, который будет оцениваться как y=10.
  6. Результатом echo $y теперь является значение '10'.

Это обычная функция на многих языках, например. Perl и JavaScript. Взгляните на perldoc eval для получения дополнительных примеров: http://perldoc.perl.org/functions/eval.html

ответил echox 23 +04002011-10-23T00:37:51+04:00312011bEurope/MoscowSun, 23 Oct 2011 00:37:51 +0400 2011, 00:37:51
49

Да, eval является внутренней командой bash, поэтому она описана в man-странице bash.

eval [arg ...]
    The  args  are read and concatenated together into a single com-
    mand.  This command is then read and executed by the shell,  and
    its  exit status is returned as the value of eval.  If there are
    no args, or only null arguments, eval returns 0.

Обычно он используется в сочетании с Command Substitution . Без явного eval оболочка пытается выполнить выполнить результат подстановки команды, а не оценить .

Скажите, что вы хотите закодировать эквивалент VAR=value; echo $VAR. Обратите внимание на разницу в том, как оболочка обрабатывает записи echo VAR=value:

  1. [email protected]:~> $( echo VAR=value )
    bash: VAR=value: command not found
    [email protected]:~> echo $VAR
    <empty line>
    

    Оболочка пытается выполнить echo и VAR=value как две отдельные команды. Это вызывает ошибку во второй строке. Назначение остается неэффективным.

  2. [email protected]:~> eval $( echo VAR=value )
    [email protected]:~> echo $VAR
    value
    
    Оболочка объединяет (объединяет) две строки echo и VAR=value, анализирует этот отдельный блок в соответствии с соответствующими правилами и выполняет его.

И последнее, но не менее важное: eval может быть очень опасной командой. Любой вход в команду eval должен быть тщательно проверен, чтобы избежать проблем с безопасностью.

ответил andcoz 23 +04002011-10-23T00:36:10+04:00312011bEurope/MoscowSun, 23 Oct 2011 00:36:10 +0400 2011, 00:36:10
16

eval не имеет man-страницы, потому что это не отдельная внешняя команда, а скорее встроенная оболочка, то есть команда, внутренняя и известная только оболочкой (bash). В соответствующей части справочной страницы bash указано:

eval [arg ...]
    The args are read and concatenated together into a single command.  
    This command is then  read  and executed by the shell, and its exit 
    status is returned as the value of eval.  If there are no args, or only 
    null arguments, eval returns 0

Кроме того, вывод, если help eval:

eval: eval [arg ...]
    Execute arguments as a shell command.

    Combine ARGs into a single string, use the result as input to the shell,
    and execute the resulting commands.

    Exit Status:
    Returns exit status of command or success if command is null.

eval - мощная команда, и если вы собираетесь ее использовать, вы должны быть очень осторожны, чтобы предотвратить возможное

ответил jw013 23 +04002011-10-23T00:35:27+04:00312011bEurope/MoscowSun, 23 Oct 2011 00:35:27 +0400 2011, 00:35:27
15

Оператор eval сообщает оболочке принимать аргументы eval как команду и запускать их через командную строку. Это полезно в ситуации, как показано ниже:

В вашем скрипте, если вы определяете команду в переменной, а позже вы хотите использовать эту команду, вы должны использовать eval:

/home/user1 > a="ls | more"
/home/user1 > $a
bash: command not found: ls | more
/home/user1 > # Above command didn't work as ls tried to list file with name pipe (|) and more. But these files are not there
/home/user1 > eval $a
file.txt
mailids
remote_cmd.sh
sample.txt
tmp
/home/user1 >
ответил Nikhil Gupta 23 rdEurope/Moscowp30Europe/Moscow09bEurope/MoscowTue, 23 Sep 2014 10:21:20 +0400 2014, 10:21:20
9

eval - это функция большинства интерпретируемых языков (TCL, python, ruby ...) не только раковины. Он используется для динамического анализа кода.

В оболочках он реализован как встроенная команда оболочки.

В принципе, eval принимает строку как аргумент и оценивает /интерпретирует код в нем. В оболочках eval может принимать несколько аргументов, но eval просто объединяет их, чтобы сформировать строку для оценки.

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

Как

varname=$1 varvalue=$2
eval "$varname=\$varvalue" # evaluate a string like "foo=$varvalue"
                           # which in Bourne-like shell language
                           # is a variable assignment.

Но это также опасно, так как важно дезинфицировать динамические (извне предоставленные) части того, что передается в eval, по той причине, что оно интерпретируется как код оболочки.

Например, выше, если $1 является evil-command; var, eval завершит оценку команды evil-command; var=$varvalue, а затем выполните команду evil-command.

Злость eval часто чрезмерно преувеличена.

Хорошо, это опасно, но, по крайней мере, мы знаем, что это опасно.

Многие другие команды будут оценивать код оболочки в своих аргументах, если не дезинфицированы, например (в зависимости от оболочки), [ aka test, export, printf, GNU sed, awk и, конечно, sh /bash code> /perl и всех интерпретаторов ...

Примеры (здесь, используя uname как evil-command и $a), как внешние предоставленные неанитизированные данные):

$ a='$(uname>&2)' sh -c 'eval "echo $a"'
Linux

$ a='x[0$(uname>&2)]' mksh -c 'export "$a=$b"'
Linux
$ a='x[0$(uname>&2)]' ksh93 -c 'printf "%d\n" "$a"'
Linux
0
$ a='x[0$(uname>&2)]' ksh93 -c '[ "$a" -gt 0 ]'
Linux
$ a=$'bar/g;e uname>&2\n;s//'; echo foo | sed "s/foo/$a/g"
Linux
bar
$ a='";system("uname");"'; awk "BEGIN{print \"$a\"}"

Linux
$ a=';uname'; sh -c "echo $a"

Linux

Те команды sed, export ... можно считать более опасными, поскольку, хотя очевидно, что eval "$var" приведет к контенту из $var, который будет оцениваться как код оболочки, это не так очевидно с помощью sed "s/foo/$var/" или export "$var=value" или [ "$var" -gt 0 ]. Опасность одна и та же, но она скрыта в других командах.

ответил Stéphane Chazelas 18 FriEurope/Moscow2015-12-18T13:49:07+03:00Europe/Moscow12bEurope/MoscowFri, 18 Dec 2015 13:49:07 +0300 2015, 13:49:07
8

Что такое eval?

eval - это команда оболочки, которая обычно реализуется как встроенная.

В POSIX он указан как часть из 2.14. В утилитах " на странице « eval » .
Что означает встроенное средство:

  

Термин «встроенный» подразумевает, что оболочка может выполнять утилиту напрямую и не нуждается в ее поиске.

Что он делает?

Проще говоря: делает синтаксический анализ строки дважды .

Как это сделать?

Оболочка имеет последовательность шагов, которые следует для «обработки» строки. Вы можете посмотреть на это изображение и поймите, что eval - единственная линия, которая поднимается вверх, назад к шагу 1, слева. Из описание POSIX :

  

2.1 Введение оболочки

     
  1. Оболочка читает свой ввод ....
  2.   
  3. Оболочка прерывает ввод в токены: слова и операторы
  4.   
  5. Оболочка анализирует входные данные в простые и составные команды.
  6.   
  7. Оболочка выполняет различные расширения (отдельно) ...
  8.   
  9. Оболочка выполняет перенаправление и удаляет операторы перенаправления и их операнды из списка параметров.
  10.   
  11. Среда выполняет функцию, встроенный, исполняемый файл или скрипт ...
  12.   
  13. Оболочка, по желанию, ожидает завершения команды и сбора статуса выхода.
  14.   

На шаге 6 будет выполнен встроенный файл.
На шаге 6 eval заставляет обработанную строку отправлять на шаг 1.
Это единственное условие, при котором возвращается последовательность выполнения.

  

Вот почему я говорю: с eval строка ввода анализируется дважды .

Эффекты синтаксического анализа дважды.

Первый.

И самый важный эффект для понимания. Это одно из последствий, когда первая строка подвергается семи шагам оболочки, показанным выше, цитирует . Внутри этапа 4 (разложения) существует также последовательность шагов для выполнения всех расширения , последний из которых Удаление цитаты :

  

Удаление ссылок всегда должно выполняться последним.

Таким образом, всегда удаляется один уровень цитирования.

Второй.

Как следствие этого первого эффекта, дополнительные /разные части линии становятся подверженными разбору оболочки и всем остальным шагам.

Пример.

Косвенность.

Это позволяет выполнять косвенные расширения:

 a=b b=c    ;    eval echo \$$a            ### shall produce "c"

Почему? Потому что в первом цикле цитируется первый $.
Таким образом, он игнорируется для разложений оболочкой.
Следующий $ с именем a расширяется для создания «b».
Затем удаляется один уровень цитирования, что делает первый код $ неучтенным.
Конец первого цикла.

Тогда во втором цикле оболочка будет читать строка $b.
Затем расширен до «c»
И задан в качестве аргумента для echo.

Чтобы «увидеть», что eval будет производить в первом цикле (для оценки снова), используйте эхо. Или любая команда /сценарий /программа, которая четко показывает аргументы:

 $ a=b b=c
$ eval echo \$$a;
c

Замените eval на эхо, чтобы «видеть», что происходит:

 $ echo echo \$$a
echo $b

Также можно показать все «части» строки с:

 $ printf '<%s> ' echo \$$a
<echo> <$b>

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

Коррекция.

Надо сказать, что: в приведенном выше коде есть ошибка, видите ли вы ?.
Легко: некоторые кавычки отсутствуют.

Как? вы можете спросить. Простой, давайте изменим переменные (а не код):

 $ a=b b="hi     jk"
$ eval echo \$$a
hi jk

Смотрите пробелы?
Это связано с тем, что значение внутри $b было разделено оболочкой.

Если это вас не убедит, попробуйте следующее:

 $ a=b b="hi  *  jk"
$ eval echo \$$a              ### warning this will expand to the list  
                              ### of all files in the present directory.

Почему?

Отсутствующие кавычки. Чтобы он работал правильно (добавьте внутренние "$a" и внешние \" цитаты).
Попробуйте это (совершенно безопасно):

 $ a=b b="hi      *       jk"
$ eval echo \" \$"$a" \"
hi      *       jk

О руководстве:

  

Для этого нет справочной страницы.

Нет, для этого нет независимой справочной страницы. Поиск руководства с помощью man -f eval или даже apropos eval не содержит записи.

Он включен внутри man bash. Как и любой встроенный.
Найдите «SHELL BUILTIN COMMANDS», а затем «eval».

Более простой способ получить помощь: В bash вы можете сделать help eval, чтобы увидеть справку для встроенного.

Почему eval называется злом?

Потому что это динамический код для кодирования.

Другими словами: он преобразует список своих аргументов (и /или расширений таких аргументов) в выполненную строку. Если по какой-либо причине аргумент был установлен злоумышленником, вы будете выполнять код злоумышленника.

Или даже проще, с eval вы сообщаете, кто бы ни определил значение одного или нескольких аргументов:

  

C'mon, сидите здесь и вводите любую командную строку, я буду выполнять ее с моими полномочиями.

Это опасно? Должно быть ясно для всех, кто это.

Правило безопасности для eval должно быть:
   Выполняйте eval только для переменных, для которых вам присвоено значение.

Подробнее читайте подробнее .

ответил 19 SatEurope/Moscow2015-12-19T07:28:13+03:00Europe/Moscow12bEurope/MoscowSat, 19 Dec 2015 07:28:13 +0300 2015, 07:28:13
0

#!/bin/bash VAR1=25 VAR2='$VAR1' VAR3='$VAR2' echo "$VAR3" eval echo "$VAR3" eval eval echo "$VAR3"

Вывод сценария выше: $VAR2 $VAR1 25

ответил LoMaPh 26 FebruaryEurope/MoscowbMon, 26 Feb 2018 12:06:08 +0300000000pmMon, 26 Feb 2018 12:06:08 +030018 2018, 12:06:08

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132