쉘에서 파일을 실행할 때 정확히 어떻게됩니까?


32

그래서 나는 이것에 대해 잘 이해하고 있다고 생각했지만 테스트를 실행했는데 (내가 누군가와 동의하지 않은 대화에 대한 응답으로) 내 이해에 결함이 있음을 발견했습니다 ...

가능한 한 자세하게 쉘에서 파일을 실행할 때 정확히 어떤 일이 발생합니까? 내 말은 ./somefile some arguments쉘에 입력하고 return 키를 누른 somefile다음 cwd에 있고에 대한 읽기 + 실행 권한이 somefile있는 경우 후드에서 어떻게됩니까?

나는 그 대답이 다음과 같다고 생각 했다.

  1. exec은 경로를 전달하여 syscall을 만듭니다.somefile
  2. 커널은 파일 의 매직 번호 를 검사 somefile하고 프로세서가 처리 할 수있는 형식인지 확인합니다.
  3. 매직 번호가 파일이 프로세서가 실행할 수있는 형식임을 나타내는 경우
    1. 새 프로세스가 작성됩니다 (프로세스 테이블에 항목이 있음).
    2. somefile메모리에 읽히거나 매핑됩니다. 스택이 생성되고 실행 이 매개 변수의 배열 (a , ) somefileARGV초기화 된 코드의 진입 점으로 이동합니다.char**["some","arguments"]
  4. 매직 넘버가 shebang 인 경우 exec()위와 같이 새 프로세스 를 생성하지만 사용 된 실행 파일은 shebang이 참조하는 인터프리터 (예 : /bin/bash또는 /bin/perl) somefile로 전달됩니다.STDIN
  5. 파일에 유효한 마법 번호가 없으면 "잘못된 파일 (잘못된 마법 번호) : Exec 형식 오류"와 같은 오류가 발생합니다.

그러나 누군가 파일이 일반 텍스트 인 경우 쉘은 명령을 실행하려고한다고 말합니다 (입력 한 것처럼 bash somefile). 나는 이것을 믿지 않았지만 방금 시도했지만 정확했습니다. 그래서 나는 실제로 여기서 일어나는 일에 대해 약간의 오해를 가지고 있으며 그 역학을 이해하고 싶습니다.

쉘에서 파일을 실행할 때 정확히 어떻게됩니까? (자세한 내용은 합리적입니다 ...)


깊이있는 이해를 위해 소스 코드 를 살펴볼 수있는 완벽한 대안은 없습니다 .
와일드 카드

1
@Wildcard 그것이 바로 지금하고있는 일입니다. 실제로 :-) 가능하다면, 나는 내 자신의 질문에 대답 할 것입니다
Josh

1
source somefile./somefile하지만 새로운 프로세스와는 다릅니다 .
thrig

@ thrig 예, 동의합니다. 그러나 파일에 마법 번호가 없으면 ./somefilebash가 명령을 실행하게 될 것이라고 생각 somefile하지 않았습니다. 나는 그것이 단지 오류를 표시 할 것이라고 생각했고, 대신 그것은 효과적으로 나타납니다source somefile
Josh

다시 틀 렸습니다 somefile. 텍스트 파일 인 경우 실행하려고하면 새 쉘이 생성된다는 것을 확인할 수 있습니다. echo $$소스와 소스를 실행하면 파일 이 다르게 동작합니다.
Josh

답변:


31

Linux에서 "프로그램 실행 방법"에 대한 결정적인 대답은 LWN.net 에서 놀랍게도 프로그램 실행 방법프로그램 실행 방법 이라는 제목 의 기사입니다 : ELF 바이너리 . 첫 번째 기사는 스크립트를 간략하게 설명합니다. (엄밀히 말하면 결정적인 대답은 소스 코드에 있지만,이 기사는 더 쉽게 읽고 소스 코드에 대한 링크를 제공합니다.)

약간의 실험에 따르면 거의 제대로 된 것으로 나타 났으며 간단한 명령 목록이 포함 된 파일의 실행을 쉘없이 처리해야한다는 것을 보여줍니다. 을 execve (2) 맨 테스트 프로그램의 소스 코드를 포함하고,는 execve; 우리는 이것을 사용하여 쉘없이 어떤 일이 발생하는지 볼 것입니다. 먼저 다음을 testscr1포함 하는 테스트 스크립트를 작성하십시오.

#!/bin/sh

pstree

그리고 하나만 testscr2포함하는

pstree

둘 다 실행 가능하게 만들고 둘 다 쉘에서 실행되는지 확인하십시오.

chmod u+x testscr[12]
./testscr1 | less
./testscr2 | less

이제 다음을 사용하여 다시 시도하십시오 execve(현재 디렉토리에 빌드했다고 가정).

./execve ./testscr1
./execve ./testscr2

testscr1여전히 실행되지만 testscr2생산

execve: Exec format error

이것은 쉘이 testscr2다르게 처리 함을 보여줍니다 . 스크립트 자체를 처리하지는 않지만 여전히 스크립트를 사용 /bin/sh합니다. 이것은 다음으로 배관 testscr2하여 확인할 수 있습니다 less.

./testscr2 | less -ppstree

내 시스템에서 나는

    |-gnome-terminal--+-4*[zsh]
    |                 |-zsh-+-less
    |                 |     `-sh---pstree

보다시피, 내가 zsh시작한 less셸과 시작된 스크립트를 실행하는 데 사용되는 셸 sh( dash시스템에 있음)이 pstree있습니다. 에서 zsh이 처리됩니다 zexecve에서 Src/exec.c: 쉘 사용하는 execve(2)명령을 실행하려고하고, 실패 할 경우, 그에 따라 (커널도했을 것이다)를 처리, 그것이 오두막이있는 경우 볼 수있는 파일을 읽고, 그 경우 파일 sh에서 0 바이트를 읽지 않는 한 파일을 실행하려고 시도 하지 않습니다.

        for (t0 = 0; t0 != ct; t0++)
            if (!execvebuf[t0])
                break;
        if (t0 == ct) {
            argv[-1] = "sh";
            winch_unblock();
            execve("/bin/sh", argv - 1, newenvp);
        }

bashtaliezin이execute_cmd.c 지적한대로 유용한 의견으로 구현 된 동일한 행동 을합니다 .

어딘가에 디스크 파일에 정의 된 간단한 명령을 실행하십시오.

  1. fork ()
  2. 파이프 연결
  3. 명령을 찾아
  4. 방향 전환을하다
  5. execve ()
  6. 경우 execve실패한 파일이 실행 모드가 설정되어있는 경우, 참조하십시오. 그렇다면 디렉토리가 아닌 경우 내용을 쉘 스크립트로 실행하십시오.

POSIX는 함수라고 하는 exec(3)함수 세트를 정의하며이 execve(2)함수도 랩핑 하고 제공합니다. 자세한 내용은 muru 의 답변을 참조하십시오. 리눅스에서는 적어도 이러한 함수들은 커널이 아닌 C 라이브러리에 의해 구현됩니다.


이것은 환상적이며 내가 찾고있는 세부 사항을 가지고 있습니다. 감사합니다!
Josh

12

부분적으로 이것은 exec사용되는 특정 제품군 기능 에 따라 다릅니다 . execve로, 스티븐 키트는 구체적으로 보여 주었다 만 적절한 오두막로 시작하는 올바른 바이너리 형식의 파일 또는 스크립트를 실행합니다.

그러나 , execlpexecvp한 단계를 이동하십시오 오두막이 정확하지 않은 경우 파일이 함께 실행되는 /bin/sh리눅스에서. 보낸 사람 man 3 exec:

Special semantics for execlp() and execvp()
   The execlp(), execvp(), and execvpe() functions duplicate the actions
   of the shell in searching for an executable file if the specified
   filename does not contain a slash (/) character.
   …

   If the header of a file isn't recognized (the attempted execve(2)
   failed with the error ENOEXEC), these functions will execute the
   shell (/bin/sh) with the path of the file as its first argument.  (If
   this attempt fails, no further searching is done.)

이것은 POSIX (강조 광산)에서 다소 지원됩니다 .

표준 개발자가 지적한 혼란의 잠재적 원인 중 하나는 프로세스 이미지 파일의 내용이 exec 함수 계열의 동작에 어떤 영향을 미치는지에 대한 것입니다. 다음은 취해진 조치에 대한 설명입니다.

  1. 프로세스 이미지 파일이이 시스템에 대해 유효한 실행 파일 (실행 가능하고 유효하며 적절한 권한이있는 형식) 인 경우 시스템은 파일을 실행합니다.

  2. 프로세스 이미지 파일에 적절한 권한이 있고 실행 가능하지만이 시스템에는 유효하지 않은 형식 (예 : 다른 아키텍처의 인식 된 바이너리) 인 경우 이는 오류이며 errno는 [EINVAL] (나중의 RATIONALE 참조)로 설정됩니다 [EINVAL]에서).

  3. 프로세스 이미지 파일에 적절한 권한이 있지만 달리 인식되지 않은 경우 :

    1. 이것이 execlp () 또는 execvp ()에 대한 호출 인 경우 프로세스 이미지 파일이 쉘 스크립트라고 가정하고 명령 인터프리터를 호출합니다.

    2. 이것이 execlp () 또는 execvp ()에 대한 호출이 아닌 경우 오류가 발생하고 errno가 [ENOEXEC]로 설정됩니다.

명령 인터프리터를 얻는 방법을 지정하지는 않지만 오류가 발생하도록 지정하지는 않습니다. 따라서 Linux 개발자는 이러한 파일을 실행할 수있었습니다 /bin/sh(또는 이것은 이미 일반적인 관행이었고 방금 따라갔습니다).

FWIW에 대한 FreeBSD 맨 페이지exec(3) 도 비슷한 동작을 언급합니다.

 Some of these functions have special semantics.

 The functions execlp(), execvp(), and execvP() will duplicate the actions
 of the shell in searching for an executable file if the specified file
 name does not contain a slash ``/'' character. 
 …
 If the header of a file is not recognized (the attempted execve()
 returned ENOEXEC), these functions will execute the shell with the path
 of the file as its first argument.  (If this attempt fails, no further
 searching is done.)

그러나 AFAICT 는 환경을보다 세밀하게 제어하기 위해 일반적인 쉘을 사용 execlp하거나 execvp직접 사용하지는 않습니다 . 모두를 사용하여 동일한 논리를 구현합니다 execve.


3
또한 리눅스에서 적어도 그를 추가 할 것, execl, execlp, execle, execv, execvpexecvpe받는 모든 프론트 엔드이다 execve콜은; 전자는 C 라이브러리에서 제공되는 커널은 약 알고있는 execve(그리고 execveat현재).
Stephen Kitt

@StephenKitt 이것이 왜 man7.org의 섹션 2에서 해당 기능에 대한 맨 페이지를 찾을 수 없는지 설명합니다.
muru

6

이것은 bash파일의 소스에서 주석으로 Stephen Kitt 답변에 추가 될 수 있습니다 execute_cmd.c.

어딘가에 디스크 파일에 정의 된 간단한 명령을 실행하십시오.

1. fork ()
2. connect pipes
3. look up the command
4. do redirections
5. execve ()
6. If the execve failed, see if the file has executable mode set.  

그렇다면 디렉토리가 아닌 경우 내용을 쉘 스크립트로 실행하십시오.


0

셸 스크립트로 실행되며 소스 가 아닙니다 (예 : 실행 된 파일에 설정된 변수는 외부에 영향을 미치지 않음). 아마도 하나의 쉘과 하나의 실행 가능한 형식 이 있었을 때 안개 낀 과거의 흔적 일 것 입니다. 실행 파일이 아니라 셸 스크립트 여야합니다.


2
당신은 내 질문을 오해했습니다. 어떤 일이 발생 구체적으로? 최소한 Shebang을 확인하는 것이 무엇인지 이해해야 exec()합니까 , 아니면 껍질입니까? 훨씬 더 내부를 원합니다
Josh
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.