Shell: 파이프와 티를 사용할 때 "중복 프로세스"가 발생하는 이유는 무엇입니까?

Shell: 파이프와 티를 사용할 때 "중복 프로세스"가 발생하는 이유는 무엇입니까?

저는 bash 프로세스에 대해 잘 알지 못하는데 파이프와 tee.

아래에서는 스크립트 경로가 로 대체됩니다 $FOLDER.

  • $FOLDER/DBB/myparent.ksh:

    echo "BEGIN $$ this is the parent process"
    $FOLDER/DBB/myChild.ksh
    echo "END $$ this is the parent process"
    
  • $FOLDER/DBB/mychild.ksh:

    function toto {
      echo " this is $$ child process "
      sleep 10
    }
    {
      echo " $$ go1 "
      toto 
      ptree $$
      echo " $$ go2 "
    } | tee myLog$$.log
    
  • 을(를 ) 시작하면 myParent.ksh다음과 같은 프로세스 트리가 표시됩니다.

    28417 /usr/lib/ssh/sshd -R
      28531 -ksh
        41387 /bin/bash myParent.ksh
          41390 /bin/bash $FOLDER/DBB/myChild.ksh
            41391 /bin/bash $FOLDER/DBB/myChild.ksh
              41393 sleep 10
            41392 tee myLog41390.log
    
  • 콘솔 출력:

    BEGIN 52665 this is the parent process
    in myChild.ksh
     52680 go1
     this is 52680 child process
    20192 zsched
      21104 /usr/lib/ssh/sshd
        27882 /usr/lib/ssh/sshd -R
          28417 /usr/lib/ssh/sshd -R
            28531 -ksh
              52665 /bin/bash myParent.ksh
                52680 /bin/bash $FOLDER/DBB/myChild.ksh
                  52688 /bin/bash $FOLDER/DBB/myChild.ksh
                    61896 ptree 52680
                  52692 tee myLog52680.log
     52680 go2
    END 52665 this is the parent process
    

왜 2개인가요 $FOLDER/DBB/myChild.ksh?

답변1

셸 스크립트에는 접미사가 붙지 .ksh만 프로세스 트리에서는 해당 스크립트가 실제로 bash셸에 의해 실행됨을 나타냅니다.

내 Debian 11 man ksh(실제로는 mkshMirBSD Korn 쉘)에서는 다음과 같이 말합니다:

파이프의 모든 명령은 별도의 하위 쉘에서 실행됩니다. 이는 POSIX에서 허용되지만 마지막 명령을 제외한 모든 명령이 하위 쉘에서 실행되는 AT&T UNIX ksh의 두 가지 변형과 다릅니다. 의미와 해결 방법을 위한 기능입니다.

그리고 man bash말했다:

파이프라인의 각 명령은 별도의 프로세스(즉, 하위 셸에서)로 실행됩니다. [...] lastpipe내장 기능을 사용하여 이 옵션을 활성화 하면 shopt(아래 설명 참조 shopt) 파이프의 마지막 요소가 쉘 프로세스에 의해 실행될 수 있습니다.

따라서 초기에 프로세스 #41390이 실행을 시작하는 프로세스입니다 myChild.ksh. 파이프가 보일 때:

{
  echo " $$ go1 "
  toto 
  ptree $$
  echo " $$ go2 "
} | tee myLog$$.log

$$파이프를 확장한 다음 {#41391의 복합 명령에 대한 하위 쉘 프로세스를 포크합니다 }.

프로세스 #41392는 내부가 아닌 명령을 실행하고 이를 최적화로 처리해야 하는 하위 쉘일 수도 있고 exec()상위 프로세스 #41390에 의해 tee직접 fork()명령 + 'd 될 수도 있습니다. exec()두 경우 모두 동일한 결과를 낳습니다. #41392는 보이는 명령줄을 변경하는 exec()작업을 수행하게 됩니다.exec()ptree

반면, 서브셸 #41391에는 실행할 명령이 여러 개 있으므로 프로세스 #41391은 서브셸로서의 정체성을 유지합니다. 실행해야 하는 마지막 명령은 echo셸 내부 명령이므로 하위 셸 프로세스로서의 수명이 종료됩니다. 그리고 파이프라인 실행을 준비할 때 상위 #41390이 $$이미 s를 확장했으므로 하위 셸 #41391의 PID는 출력에 표시되지 않습니다.

관련 정보