쉘에서 파일을 실행하면 정확히 무슨 일이 발생합니까?

쉘에서 파일을 실행하면 정확히 무슨 일이 발생합니까?

그래서 나는 이것에 대해 꽤 잘 이해했다고 생각했지만 방금 테스트를 해보니 (내가 동의하지 않는 누군가의 대화에 대한 응답으로) 내 이해에 결함이 있음을 알게되었습니다 ...

최대한 자세히 설명하세요.쉘에서 파일을 실행하면 정확히 무슨 일이 발생합니까? 즉, ./somefile some arguments셸에 다음을 입력하고 Enter 키를 누르면( somefilecwd에 존재하고 읽기+실행 권한이 있음 somefile) 뒤에서 무슨 일이 발생할까요?

아이디어정답은:

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

그러나 파일이 일반 텍스트인 경우 쉘은 (마치 내가 입력한 것처럼) 명령을 실행하려고 시도할 것이라고 들었습니다 bash somefile. 원래는 안 믿었는데, 막상 해보니 그게 맞더라고요. 그래서 나는 여기서 실제로 무슨 일이 일어나고 있는지에 대해 분명히 약간의 오해를 가지고 있으며 메커니즘을 이해하고 싶습니다.

쉘에서 파일을 실행하면 정확히 무슨 일이 발생합니까? (가능한 한 자세하게...)

답변1

"Linux에서 프로그램이 실행되는 방법"에 대한 명확한 대답은 다음 두 기사입니다.greennet.com제목은 놀랍게도,프로그램 작동 방식그리고프로그램 실행 방법: ELF 바이너리. 첫 번째 글에서는 스크립트를 간략하게 소개합니다. (기술적으로 최종 답변은 소스 코드에 있지만 이러한 기사는 읽기 더 쉽고 소스 코드에 대한 링크를 제공합니다.)

일부 실험에서는 거의 올바르게 수행되었으며 간단한 명령 목록(shebang 없이)이 포함된 파일의 실행은 셸에서 처리해야 함을 보여줍니다. 이것실행(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일반적인 쉘이었습니다 . 이는 in에서 처리 됩니다.shdashpstreezshzexecveSrc/exec.c:shell은 명령을 실행하는 데 사용됩니다 execve(2). 실패하면 파일을 읽어 shebang이 있는지 확인하고 그에 따라 처리합니다(커널도 이 작업을 수행함). 실패하면 파일이 있는 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);
        }

bash동일한 동작이 구현되어 있습니다.execute_cmd.c도움이 되는 의견(지시된 바와 같이)탈레진):

일부 디스크 파일에 정의되어 있는 간단한 명령을 실행합니다.

  1. fork ()
  2. 파이프 연결
  3. 찾기 명령
  4. 리디렉션하기
  5. execve ()
  6. 실패 하면 execve파일에 실행 모드가 설정되어 있는지 확인하세요. 그렇다면 디렉토리가 아니고 해당 내용은 쉘 스크립트로 실행됩니다.

POSIX는 다음과 같은 함수 세트를 정의합니다.exec(3)기능, execve(2)이 기능을 래핑하고 제공합니다.무루자세한 내용은 답변해 주세요. Linux에서는 최소한 이러한 기능이 커널이 아닌 C 라이브러리에 의해 구현됩니다.

답변2

이는 어느 정도 exec사용되는 특정 홈 기능에 따라 다릅니다. execve, 처럼스티븐 지터자세히 표시된 것처럼 올바른 바이너리 형식의 파일이나 올바른 shebang으로 시작하는 스크립트만 실행하세요.

하지만, execlp그리고 한 단계 더 나아갑니다. execvpshebang이 잘못된 경우 /bin/shLinux에서 파일을 실행합니다 . ~에서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]로 설정됩니다(이유 참조). 뒤에 ) on [EINVAL]).

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

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

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

이는 명령 해석기를 얻는 방법을 지정하지 않으므로 오류가 발생해야 한다고 지정하지 않습니다. 그래서 나는 Linux 개발자가 그러한 파일이 실행되도록 허용한다고 생각합니다 /bin/sh. (또는 이것은 이미 일반적인 관행이므로 그대로 따릅니다.)

앞으로,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

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.  

그렇다면 디렉토리가 아니고 해당 내용은 쉘 스크립트로 실행됩니다.

답변4

이는 쉘 스크립트로 실행됩니다.아니요소스(예: 실행 파일 내에 설정된 변수는 외부에 영향을 미치지 않습니다.) 아마도 먼 과거의 유물이었을 것입니다.하나쉘과하나실행 가능한 형식. 실행 파일이 아니며 쉘 스크립트여야 합니다.

관련 정보