eval과 exec의 차이점은 무엇입니까?


답변:


124

evalexec완전히 다른 짐승이다. (둘 다 명령을 실행하지만 쉘에서 수행하는 모든 작업을 수행한다는 사실을 제외하고)

$ help exec
exec: exec [-cl] [-a name] [command [arguments ...]] [redirection ...]
    Replace the shell with the given command.

무엇 exec cmd않습니다, 단지 실행과 정확히 동일 cmd대신 별도의 프로세스로 실행되고의 현재 쉘이 명령으로 대체되는 것을 제외하고. 내부적으로 say /bin/ls를 실행 fork()하면 하위 프로세스를 생성하기 위해 호출 한 다음 exec()하위에서 실행 /bin/ls합니다. exec /bin/ls한편 것입니다 하지 포크, 그러나 다만 쉘을 대체합니다.

비교:

$ bash -c 'echo $$ ; ls -l /proc/self ; echo foo'
7218
lrwxrwxrwx 1 root root 0 Jun 30 16:49 /proc/self -> 7219
foo

$ bash -c 'echo $$ ; exec ls -l /proc/self ; echo foo'
7217
lrwxrwxrwx 1 root root 0 Jun 30 16:49 /proc/self -> 7217

echo $$내가 시작한 쉘의 PID를 인쇄하고, 리스팅 /proc/selfls쉘에서 실행 된 PID를 제공합니다 . 일반적으로 프로세스 ID는 다르지만 exec쉘이 있고 ls프로세스 ID가 동일합니다. 또한 exec쉘이 교체되었으므로 다음 명령 이 실행되지 않았습니다.


반면에 :

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

eval현재 쉘에서 명령으로 인수를 실행합니다. 다시 말해서 eval foo bar, 그냥와 동일합니다 foo bar. 그러나 변수는 실행하기 전에 확장되므로 쉘 변수에 저장된 명령을 실행할 수 있습니다.

$ unset bar
$ cmd="bar=foo"
$ eval "$cmd"
$ echo "$bar"
foo

그것은 것입니다 하지 변수가 현재 쉘에 설정되어 있으므로, 자식 프로세스를 만들 수 있습니다. (물론 eval /bin/ls평범한 노인과 같은 방식으로 자식 프로세스를 만듭니다 /bin/ls.)

또는 쉘 명령을 출력하는 명령이있을 수 있습니다. Running ssh-agent은 백그라운드에서 에이전트를 시작하고 현재 셸에서 설정하고 자식 프로세스 ( ssh실행할 명령)에서 사용할 수있는 많은 변수 할당을 출력합니다 . 따라서 다음 ssh-agent과 같이 시작할 수 있습니다.

eval $(ssh-agent)

그리고 현재 쉘은 다른 명령이 상속 할 변수를 얻습니다.


물론 변수에 cmd와 같은 내용이 포함되어 있으면 rm -rf $HOMErunning eval "$cmd"은 원하지 않는 일입니다. 그래서 문자열 내부 명령 대체처럼 심지어 일들이 처리 될 사람이해야 정말 입력이 할 수 있는지 확인 eval을 사용하기 전에 안전합니다.

종종 eval실수로 코드와 데이터를 잘못 혼합하는 것을 피하고 피할 수 있습니다.


@ilkkachu, 좋은 답변입니다. 감사!
Willian Paixao

eval 사용법에 대한 자세한 내용은 여기를 참조하십시오 : stackoverflow.com/a/46944004/2079103
clearlight

1
@ clearlight, 글쎄, 그것은 이 답변에도 처음부터 사용하지 않는eval 것에 대한 일반적인 면책 조항을 추가하도록 상기시킵니다 . 간접적으로 수정 변수와 같은 물건을 통해 많은 포탄으로 수행 할 수 있습니다 declare/ typeset/ nameref추천하고 확장 ${!var}, 그래서 내가 대신 그 사용하는 것이 eval정말 그것을 피할했다 않는합니다.
ilkkachu

27

exec새로운 프로세스를 만들지 않습니다. 그것은 대체하는 새로운 명령을 사용하여 현재 프로세스를. 명령 행에서이 작업을 수행하면 셸 세션이 효과적으로 종료됩니다 (그리고 로그 아웃하거나 터미널 창을 닫을 수도 있습니다).

예 :

ksh% bash
bash-4.2$ exec /bin/echo hello
hello
ksh% 

여기에 있습니다 ksh(일반 쉘). 나는 bashbash를 시작 하고 시작한다 exec /bin/echo. 프로세스가로 교체 되었으므로 ksh나중에 다시 탈퇴 한 것을 확인할 수 있습니다 .bash/bin/echo


ksh b / c 프로세스로 되돌아 간 얼굴의 음 ..

14

TL; DR

exec명령이 지정되지 않은 경우 현재 쉘 프로세스를 새 것으로 대체하고 스트림 경로 재 지정 / 파일 디스크립터를 처리하는 데 사용됩니다. eval문자열을 명령으로 평가하는 데 사용됩니다. 둘 다 런타임에 알려진 인수로 명령을 빌드하고 실행하는 데 사용될 수 있지만 exec명령을 실행하는 것 외에도 현재 쉘의 프로세스를 대체합니다.

exec buil-in

통사론:

exec [-cl] [-a name] [command [arguments]]

이 내장 명령이 지정된 경우 매뉴얼에 따라

... 쉘을 대체합니다. 새로운 프로세스가 생성되지 않습니다. 인수는 명령에 대한 인수가됩니다.

다시 말해, bashPID 1234 로 실행 중이고 exec top -u root해당 쉘 내 에서 실행 중이 면 top명령에 PID 1234가 있고 쉘 프로세스를 대체합니다.

이것은 어디에 유용합니까? 래퍼 스크립트라고합니다. 이러한 스크립트는 인수 세트를 작성하거나 환경에 전달할 변수에 대한 특정 결정을 내린 후 exec지정된 명령으로 대체하고 래퍼 스크립트가 작성하는 것과 동일한 인수를 제공하는 데 사용합니다.

매뉴얼에 명시된 내용은 다음과 같습니다.

명령을 지정하지 않으면 모든 재 지정이 현재 쉘에서 적용됩니다.

이를 통해 현재 쉘 출력 스트림에서 파일로 무엇이든 리디렉션 할 수 있습니다. 이것은 stdout명령 을 보지 않고 싶을 때 로깅 또는 필터링 목적으로 유용 할 수 있습니다 stderr. 예를 들면 다음과 같습니다.

bash-4.3$ exec 3>&1
bash-4.3$ exec > test_redirect.txt
bash-4.3$ date
bash-4.3$ echo "HELLO WORLD"
bash-4.3$ exec >&3
bash-4.3$ cat test_redirect.txt 
2017 05 20 星期六 05:01:51 MDT
HELLO WORLD

이 동작은 쉘 스크립트로그인하고 , 스트림을 별도의 파일이나 프로세스로 리디렉션 하고, 파일 디스크립터가있는 기타 재미있는 것들 에 편리합니다.

bash버전 4.3 이상의 소스 코드 레벨에서 exec기본 제공은에 정의되어 builtins/exec.def있습니다. 수신 된 명령을 구문 분석하고 파일이 있으면 파일에 shell_execve()정의 된 기능 에 전달 execute_cmd.c합니다.

간단히 말해서 execC 프로그래밍 언어로 된 명령 계열이 shell_execve()있으며 기본적으로 다음과 같은 래퍼 함수입니다 execve.

/* Call execve (), handling interpreting shell scripts, and handling
   exec failures. */
int
shell_execve (command, args, env)
     char *command;
     char **args, **env;
{

eval 내장

bash 4.3 매뉴얼 상태 (내가 강조한 내용) :

인수는 읽고 단일 명령으로 함께 연결됩니다. 그런 다음이 명령을 에서 읽고 실행 하며 종료 상태는 eval 값으로 리턴됩니다.

프로세스 교체가 발생하지 않습니다. 기능 exec을 시뮬레이션하는 것이 목표 인 것과 달리 내장 execve()기능 eval은 마치 사용자가 명령 행에 인수를 입력 한 것처럼 인수를 "평가"하는 역할 만합니다. 따라서 새로운 프로세스가 생성됩니다.

이것이 유용한 곳은 어디입니까? Gilles 가이 답변에서 지적했듯이 "... eval은 자주 사용되지 않습니다. 일부 쉘에서 가장 일반적인 용도는 런타임까지 이름을 알 수없는 변수의 값을 얻는 것입니다." 개인적으로, 나는 우분투에서 사용자가 현재 사용하고있는 특정 작업 공간을 기반으로 명령을 실행 / 평가 해야하는 두 스크립트에서 사용했습니다.

소스 코드 레벨에서 정의되고 builtins/eval.def구문 분석 된 입력 문자열을 evalstring()함수에 전달합니다 .

무엇보다도, eval변수에 할당 있는 동안은, 현재 쉘 실행 환경에 남아 exec할 수 없습니다 :

$ eval x=42
$ echo $x
42
$ exec x=42
bash: exec: x=42: not found

@ ctrl-alt-delor 그 부분을 편집 했으므로 감사합니다. 논리적으로 새로운 프로세스를 생성하지만 PID는 단지 현재 쉘과 동일하게 유지됩니다. 앞으로는 특히 7 단어 문구와 같은 사소한 문제가있는 경우 의견을 남기고 downvote 대신 답변을 편집하는 것이 좋습니다. 답변을 편집하고 수정하는 데 훨씬 적은 시간이 소요되며 훨씬 유용합니다.
Sergiy Kolodyazhnyy

5
새로운 자식 프로세스를 생성하고 인수를 실행하고 종료 상태를 반환합니다.

어? 요점은 eval자식 프로세스를 만들지 않는다는 것입니다. 만약 내가한다면

eval "cd /tmp"

쉘에서, 현재 쉘은 디렉토리를 변경했을 것입니다. 또한 exec새로운 자식 프로세스를 만들지 않고 주어진 실행 파일에 대한 현재 실행 파일 (즉, 셸)을 변경합니다. 프로세스 ID (및 열린 파일 및 기타 항목)는 동일하게 유지됩니다. 에 반대로 eval,는 exec하지 않는 호출 쉘에 반환하지 않습니다 exec자체가 실패로 인해 찾거나 실행 파일을로드하거나 인수 확장 문제에 죽을 수없는 존재로.

eval기본적으로 인수 후 인수를 문자열로 해석합니다. 즉, 와일드 카드 확장 및 인수 분할의 추가 계층을 수행합니다. exec그런 일은하지 않습니다.


1
"eval과 exec는 모두 Bash (1)의 내장 명령이며 명령을 실행하여 새 하위 프로세스를 작성하고 인수를 실행하고 종료 상태를 리턴합니다"라는 원래 질문입니다. 잘못된 추정을 편집했습니다.
찰스 스튜어트

-1

평가

이 작품들 :

$ echo hi
hi

$ eval "echo hi"
hi

$ exec echo hi
hi

그러나 다음과 같은 것은 아닙니다.

$ exec "echo hi"
bash: exec: echo hi: not found

$ "echo hi"
bash: echo hi: command not found

공정 이미지 교체

이 예제 exec는 호출 프로세스의 이미지를 바꾸는 방법을 보여줍니다 .

# Get PID of current shell
sh$ echo $$
1234

# Enter a subshell with PID 5678
sh$ sh

# Check PID of subshell
sh-subshell$ echo $$
5678

# Run exec
sh-subshell$ exec echo $$
5678

# We are back in our original shell!
sh$ echo $$
1234

공지 사항 exec echo $$서브 쉘의 PID에 달렸다! 또한, 완성 된 후에 우리는 원래 sh$껍질 로 돌아 왔습니다 .

반면에 공정 이미지를 대체 eval하지 않습니다 . 오히려 일반적으로 쉘 자체에서와 같이 주어진 명령을 실행합니다. (물론, 프로세스가 생성되어야하는 명령을 실행하면 ... 그냥 그렇게합니다!)

sh$ echo $$
1234

sh$ sh

sh-subshell$ echo $$
5678

sh-subshell$ eval echo $$
5678

# We are still in the subshell!
sh-subshell$ echo $$
5678

다른 예제들이 나 같은 미약 한 마음을 충분히 이해하기 쉬운 방법으로 설명하지 않았기 때문에이 답변을 게시했습니다.
Mateen Ulhaq

잘못된 단어 선택 : 프로세스 대체는 여기서 설명 하는 것과 무관 한 기존 개념 입니다.
muru

@muru "프로세스 교체"가 더 낫습니까? 올바른 용어가 무엇인지 잘 모르겠습니다. 맨 페이지에서 "프로세스 이미지 교체"라고합니다.
Mateen Ulhaq

흠, 던노 (그러나 "프로세스 이미지 교체"라는 음성이 들리면 다음과 같이 생각합니다. exec)
muru
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.