bash의 "eval"명령은 무엇입니까?


176

eval명령으로 무엇을 할 수 있습니까? 왜 유용한가요? bash에 내장 함수가 있습니까? man페이지 가 없습니다 ..


28
명령type command어떤 유형인지 알기 위해 사용 합니다 . ( 이 경우)type eval
rozcietrzewiacz

9
"eval은 쉘 내장"
Nuno Rafael Figueiredo

3
help eval쉘에서 "man"페이지를 얻으려면
m-ric

eval은 bash-builtin이며 bash의 맨 페이지에 문서화되어 있습니다. "man bash"를 입력하고 eval에 대한 적절한 섹션을 검색하십시오. 이것은 다른 배쉬 내장에도 적용됩니다.
Dirk Thannhäuser

답변:


132

evalPOSIX의 일부입니다. 쉘 내장이 될 수있는 인터페이스입니다.

"POSIX 프로그래머 매뉴얼"에 설명되어 있습니다 : http://www.unix.com/man-page/posix/1posix/eval/

eval - construct command by concatenating arguments

그것은 인수를 취하고 그것의 명령을 구성 할 것이고, 이것은 쉘에 의해 실행될 것입니다. 다음은 맨 페이지의 예입니다.

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문자열로 구성된 define을 정의 하십시오 '$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


4
쉘 용어에서 eval함수가 아닌 내장 기능입니다. 실제로 내장 언어는 언어로 정의되지 않은 함수와 비슷하게 동작하지만이라고 불리는 함수를 정의하기에 충분히 왜곡되면 분명하지 않습니다 eval.
Gilles

thx, 고정 :-)
echox

4
eval과 backticks의 차이점은 무엇입니까?
JohnyTex

5
백틱은 또 다른 전체 셸을 실행하기위한 약어로, 스크립트 내에서 다른 자식 bash / sh 프로세스가 실행됩니다.
Aaron R.

echo $ y (3 단계)가 $ foo 대신 foo (10)을 다시 가져 오는 이유는 무엇입니까? (즉 문자열 $ + foo의 값 대신 foo의 값)?
JohnDoea

60

예, evalbash 내부 명령이므로 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. andcoz@...:~> $( echo VAR=value )
    bash: VAR=value: command not found
    andcoz@...:~> echo $VAR
    <empty line>

    쉘은 실행을 시도 echo하고 VAR=value두 개의 별도의 명령으로. 두 번째 문자열에 대한 오류가 발생합니다. 과제는 여전히 유효하지 않습니다.

  2. andcoz@...:~> eval $( echo VAR=value )
    andcoz@...:~> echo $VAR
    value
    쉘 병합 (연접) 두 문자열 echoVAR=value, 해당 규칙에 따라이 하나의 단위를 분석하고 실행한다.

마지막 eval으로, 매우 위험한 명령이 될 수 있습니다. eval보안 문제를 피하기 위해 명령 에 대한 입력 내용을 주의 깊게 점검해야합니다.


18

eval별도의 외부 명령이 아니라 쉘 내장 기능이기 때문에 맨 페이지가 없으며 쉘 내부에서만 사용되고 쉘 ( 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강력한 명령이므로이 명령을 사용하려면 가능한 보안 위험 을 제거해야합니다 .


16

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 >

3
예제 4 행의 주석이 잘못되었습니다. "bash가라는 명령을 찾으려고해서 명령이 작동하지 않았습니다 ls | more. 즉, 단일 명령 이름은 공백과 파이프 기호를 포함하여 9 개의 문자로 구성되었습니다. .
CFI

그가보고 한 것과 똑같은 행동을합니다. bash --version == GNU bash, 버전 3.2.57 (1)-릴리스 (x86_64-apple-darwin18)
Alexander Bird

10

평가 란 무엇입니까?

eval은 일반적으로 내장으로 구현되는 쉘 명령입니다.

POSIX 에서는 "eval" 항목 에 "2.14. 특별 내장 유틸리티"의 일부로 나열되어 있습니다.
내장의 의미는 다음과 같습니다.

"내장"이라는 용어는 쉘이 유틸리티를 직접 실행할 수 있으며 검색 할 필요가 없음을 의미합니다.

무엇을합니까?

간단히 말해서 : 입력 행을 두 번 구문 분석 합니다.

어떻게합니까?

쉘에는 라인을 "처리"하기 위해 따르는 일련의 단계가 있습니다. 당신은 수있는 이 이미지보고 및 평가가 진행 유일한 라인, 다시 왼쪽에, 1 단계는 것을 알고 있습니다. 에서 POSIX의 설명 :

2.1 쉘 소개

  1. 쉘은 입력을 읽습니다 ....
  2. 쉘은 입력을 토큰으로 나눕니다 : 단어와 연산자
  3. 쉘은 입력을 단순하고 복합적인 명령으로 구문 분석합니다.
  4. 쉘은 다양한 확장을 수행합니다 (별도) ...
  5. 쉘은 경로 재 지정을 수행하고 매개 변수 목록에서 경로 재 지정 연산자 및 해당 피연산자를 제거합니다.
  6. 쉘은 함수, 내장, 실행 파일 또는 스크립트를 실행합니다 ...
  7. 쉘은 선택적으로 명령이 완료 될 때까지 대기하고 종료 상태를 수집합니다.

6 단계에서 내장 기능이 실행됩니다.
단계 6에서, 평가는 처리 된 라인이 단계 1로 다시 전송되게한다.
이것은 실행 순서가 되돌아가는 유일한 조건이다.

이것이 내가 말하는 이유입니다 : eval을 사용하면 입력 줄이 두 번 구문 분석 됩니다 .

두 번의 파싱 효과.

첫번째.

그리고 가장 중요한 영향을 이해합니다. 위에 표시된 7 개의 쉘 단계가 행에 처음으로 적용되는 경우의 결과가 인용 됩니다. 4 단계 (확장) 안에는 모든 확장을 수행 하는 일련의 단계가 있으며 마지막 단계인용 제거입니다 .

따옴표 제거는 항상 마지막에 수행해야합니다.

따라서 항상 한 수준의 인용이 제거됩니다.

둘째.

그 첫 번째 효과의 결과로 라인의 추가 / 다른 부분이 쉘 파싱 및 기타 모든 단계에 노출됩니다.

예.

우회.

이를 통해 간접 확장을 실행할 수 있습니다.

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

왜? 첫 번째 루프에서 첫 번째 루프 $가 인용 되기 때문입니다 .
따라서 쉘에 의한 확장에서는 무시됩니다. 이름이 a 인
다음 $은 "b"를 생성하도록 확장됩니다.
그런 다음 한 수준의 인용이 제거되어 첫 번째 $인용이 인용되지 않습니다.
첫 번째 루프 끝

그런 다음 두 번째 루프 $b에서 쉘이 문자열 을 읽습니다.
그런 다음 "c"로 확장하고에
대한 인수로 제공됩니다 echo.

첫 번째 루프에서 어떤 eval이 생성되는지 "확인"하려면 (다시 평가) echo를 사용하십시오. 또는 인수를 명확하게 보여주는 명령 / 스크립트 / 프로그램 :

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

무슨 일이 일어나고 있는지 "참조"하기 위해 eval을 echo로 바꿉니다.

$ 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을 사용하면 누구에게 하나 이상의 인수의 가치를 정의했는지 알려줍니다.

C'mon, 여기 앉아서 명령 줄을 입력하면, 나는 그것을 내 힘으로 실행할 것이다.

위험한가요? 모든 사람에게 명확해야합니다.

평가에 대한 안전 규칙은 다음과 같아야
만되는 변수를 평가 실행 당신이 이 값의 주었다.

읽기 여기에 자세한 내용을 .


10

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쉘 코드로 해석되는 이유 때문에 전달되는 것의 동적 (외부 적으로 제공되는) 부분을 위생 처리하는 것이 중요하기 때문에 위험 합니다.

예를 들어 위의 $1is evil-command; var인 경우 쉘 코드를 eval평가 evil-command; var=$varvalue한 다음 실행합니다 evil-command.

의 악 eval은 종종 과장된 것입니다.

알았어, 위험하지만 적어도 우리는 그것이 위험하다는 것을 안다.

(쉘에 따라)처럼, 소독하지 않을 경우 다른 명령의 많은 인수에 쉘 코드를 평가합니다 [일명 test, export, printf, GNU sed, awk, 물론 sh/ bash/ perl모든 통역 ...

예로는 (여기에 사용 uname은 AS evil-command$a같은 외부 unsanitized 데이터 제공)

$ 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 ]. 위험성은 동일하지만 다른 명령에는 숨겨져 있습니다.


@BinaryZebra는 sed같은 eval때문에, 변수에 포함 된 문자열이 전달되는, 모두를위한, 그 캐릭터 라인의 내용은 쉘 코드로 평가되고 끝나는 sed만큼 위험 eval그게 무슨 말인지입니다. seduname(uname이 지금까지 실행되지 않았습니다)를 포함하는 문자열로 전달 되고을 호출 sed하여 uname 명령이 실행됩니다. 평가판처럼. 에서 sed 's/foo/$a/g', 비위생 데이터를 (으)로 전달 sed하지 않습니다. 이것이 우리가 여기서 말하는 것이 아닙니다.
Stéphane Chazelas

2

이 예는 약간의 빛을 비출 수 있습니다.

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

위의 스크립트 출력 :

$VAR2
$VAR1
25

귀하의 기여에 감사드립니다. 그러나 재미있는 그대로 사용하여 (약간 다른) 예제 목록을 컴파일하는 데 관심이 없습니다 eval. eval기존 답변에서 다루지 않은 기능의 기본적이고 중요한 측면이 있다고 생각하십니까 ? 그렇다면 설명 하고 예를 사용하여 설명을 설명하십시오. 의견에 응답하지 마십시오.  명확하고 완전하게 답변을 편집 하십시오.
Scott
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.