it-swarm-ko.tech

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

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

210
LanceBaynes

eval는 POSIX의 일부입니다. Shell 내장이 될 수있는 인터페이스입니다.

"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로 구성된 '$foo'를 정의하십시오. 달러 기호는 '$'로 이스케이프해야합니다.
  3. 결과를 확인하려면 echo $y.
  4. 결과는 문자열 '$foo'가됩니다.
  5. 이제 eval로 할당을 반복합니다. 먼저 $x를 문자열 'foo'로 평가합니다. 이제 y=$foo로 평가되는 y=10 문이 있습니다.
  6. echo $y의 결과는 이제 '10' 값입니다.

이것은 여러 언어에서 공통적 인 기능입니다 (예 : 펄과 자바 스크립트. 더 많은 예제를 보려면 perldoc eval을 살펴보십시오. http://perldoc.Perl.org/functions/eval.html

150
echox

예, eval는 bash 내부 명령이므로 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이 없으면, 쉘은 evaluate가 아니라 명령 대체의 결과를 execute하려고 시도합니다.

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>
    

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

  2. [email protected]:~> eval $( echo VAR=value )
    [email protected]:~> echo $VAR
    value
    
    Shell은 두 문자열 echoVAR=value를 병합 (연결)하여이 단일 단위를 적절한 규칙에 따라 구문 분석하여 실행합니다.

마지막으로 eval는 매우 위험한 명령 일 수 있습니다. 보안 문제를 피하려면 eval 명령에 대한 모든 입력을 신중하게 확인해야합니다.

65
andcoz

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는 강력한 명령이므로이를 사용하려면 가능한 보안 위험 을 제거해야합니다.

19
jw013

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 >
18
Nikhil Gupta

평가 란 무엇입니까?

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

POSIX에서는 "eval" 항목에 "2.14. 특수 내장 유틸리티" 부분으로 표시됩니다.
내장의 의미는 다음과 같습니다.

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

무엇을합니까?

간단히 말해서 : 입력 줄을 구문 분석 두 번 만듭니다.

어떻게합니까?

쉘에는 라인을 "처리"하기 위해 따르는 일련의 단계가 있습니다. 이 이미지를보십시오 할 수 있고 eval이 왼쪽의 1 단계로 돌아가는 유일한 행임을 알 수 있습니다. 에서 POSIX 설명 :

2.1 쉘 소개

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

6 단계에서 내장 기능이 실행됩니다.
6 단계에서 eval은 처리 된 라인이 1 단계로 다시 전송되도록합니다.
실행 시퀀스가 ​​돌아가는 유일한 조건입니다.

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

두 번의 파싱 효과.

첫번째.

그리고 가장 중요한 영향을 이해합니다. 행이 위에 표시된 7 개의 쉘 단계에 처음 적용될 때의 결과는 quoting 입니다. 4 단계 (확장) 안에는 모든 확장을 수행하는 단계 순서 도 있으며 마지막은 Quote Removal :

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

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

둘째.

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

예.

우회.

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

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, 여기 앉아서 명령 줄을 입력하면 내 힘으로 실행할 것이다

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

평가의 안전 규칙은 다음과 같아야합니다.
you 가 값을 지정한 변수에 대해서만 eval을 실행하십시오.

읽기 자세한 내용은 여기 .

12
user79743

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에 전달되는 부분의 동적 (외부 적으로 제공되는) 부분을 삭제하는 것이 중요하므로 위험합니다.

예를 들어, 위의 $1evil-command; var이면 evalevil-command; var=$varvalue 셸 코드를 평가 한 다음 evil-command를 실행합니다.

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

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

(쉘에 따라 다름), [ 일명 test, export, printf, GNU sed, awk)과 같이 위생 처리되지 않은 경우 많은 다른 명령이 인수에서 쉘 코드를 평가합니다. 물론 sh/bash/Perl 및 모든 통역사 ...

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

11
Stéphane Chazelas

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

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

위의 스크립트 출력 :

$VAR2
$VAR1
25
5
LoMaPh