중괄호를 사용하여 Bash 하위 셸 만들기

중괄호를 사용하여 Bash 하위 셸 만들기

에 따르면:

3.2.5.3 그룹화 명령

{}

{ list; }

중괄호 사이에 명령 목록을 배치하면 해당 목록이 현재 셸의 컨텍스트에서 실행됩니다.서브쉘이 생성되지 않습니다..

ps실제 효과를 보기 위해 사용됨

이는 명령줄에서 직접 실행되는 프로세스 파이프라인의 프로세스 계층 구조입니다. 4398은 로그인 쉘의 PID입니다.

sleep 2 | ps -H;
  PID TTY          TIME CMD
   4398 pts/23   00:00:00 bash
   29696 pts/23   00:00:00   sleep
   29697 pts/23   00:00:00   ps

이제 명령줄에서 직접 실행되는 중괄호 사이의 프로세스 파이프라인의 프로세스 계층 구조를 따릅니다. 4398은 로그인 쉘의 PID입니다.위의 계층 구조와 유사하며 모든 것이 현재 쉘 컨텍스트에서 실행된다는 것을 증명합니다.:

{ sleep 2 | ps -H; }
   PID TTY          TIME CMD
    4398 pts/23   00:00:00 bash
    29588 pts/23   00:00:00   sleep
    29589 pts/23   00:00:00   ps

이제 이것은 파이프라인 자체가 중괄호 안에 배치될 때의 프로세스 계층 구조입니다 sleep(따라서 총 두 가지 수준의 중괄호가 있습니다).

{ { sleep 2; } | ps -H; }
  PID TTY          TIME CMD
   4398 pts/23   00:00:00 bash
   29869 pts/23   00:00:00   bash
   29871 pts/23   00:00:00     sleep
   29870 pts/23   00:00:00   ps

문서에 중괄호 사이의 명령이 현재 쉘의 컨텍스트에서 실행된다고 명시되어 있는데 bash세 번째 경우에 실행할 하위 쉘을 만들어야 하는 이유는 무엇입니까?sleep

답변1

파이프에서는 모든 명령이 서로 다른 프로세스(stdout/stdin이 파이프를 통해 연결됨)에서 동시에 실행됩니다.

존재하다

cmd1 | cmd2 | cmd3

세 가지 명령은 모두 서로 다른 프로세스에서 실행되므로 적어도 두 명령은 하위 프로세스에서 실행되어야 합니다. 일부 쉘은 현재 쉘 프로세스에서 그 중 하나를 실행하지만(내장된 경우 read또는 파이프가 스크립트의 마지막 명령인 경우) bash자체 별도 프로세스에서 실행합니다( lastpipe최신 bash버전의 옵션 및 특정 조건에서는 제외). ).

{...}그룹 명령. 그룹이 파이프라인의 일부인 경우 간단한 명령과 같은 별도의 프로세스에서 실행되어야 합니다.

존재하다:

{ a; b "$?"; } | c

a; b "$?"이를 별도의 프로세스로 평가하려면 쉘이 필요하므로 서브쉘이 필요합니다. for b는 그룹에서 실행되는 마지막 명령이므로 for를 분기하지 않음으로써 셸을 최적화할 수 있습니다 . 일부 쉘은 이를 수행할 수 있지만 분명히 그렇지 않습니다 bash.

답변2

중첩된 중괄호는 새 하위 쉘을 호출해야 하는 추가 수준의 범위를 생성한다는 것을 나타내는 것 같습니다. Bash의 두 번째 복사본을 사용하여 출력에서 ​​이 효과를 확인할 수 있습니다 ps -H.

중괄호의 첫 번째 수준에 지정된 프로세스만 원래 Bash 셸의 범위 내에서 실행됩니다. 중첩된 중괄호는 자체 범위 Bash 셸 내에서 작동합니다.

$ { { { sleep 20; } | sleep 20; } | ps -H; }
  PID TTY          TIME CMD
29190 pts/1    00:00:00 bash
 5012 pts/1    00:00:00   bash
 5014 pts/1    00:00:00     bash
 5016 pts/1    00:00:00       sleep
 5015 pts/1    00:00:00     sleep
 5013 pts/1    00:00:00   ps

| ps -H중첩된 중괄호를 볼 수 있도록 믹스에서 꺼내어 ps auxf | less다른 셸에서 실행할 수 있습니다.

saml     29190  0.0  0.0 117056  3004 pts/1    Ss   13:39   0:00  \_ bash
saml      5191  0.0  0.0 117056  2336 pts/1    S+   14:42   0:00  |   \_ bash
saml      5193  0.0  0.0 107892   512 pts/1    S+   14:42   0:00  |   |   \_ sleep 20
saml      5192  0.0  0.0 107892   508 pts/1    S+   14:42   0:00  |   \_ sleep 20
saml      5068  0.2  0.0 116824  3416 pts/6    Ss   14:42   0:00  \_ bash
saml      5195  0.0  0.0 115020  1272 pts/6    R+   14:42   0:00      \_ ps auxf
saml      5196  0.0  0.0 110244   880 pts/6    S+   14:42   0:00      \_ less

하지만 더 많은 것이 있습니다!

파이프를 꺼내서 이 명령 형식을 사용하면 실제로 예상되는 내용을 볼 수 있습니다.

$ { { { sleep 10; } ; { sleep 10; } ; sleep 10; } } | watch "ps -H"

이제 결과 감시 창에서 무슨 일이 일어나고 있는지에 대한 업데이트를 2초마다 수신합니다.

이것은 첫 번째 것입니다 sleep 10:

  PID TTY          TIME CMD
29190 pts/1    00:00:00 bash
 5676 pts/1    00:00:00   bash
 5678 pts/1    00:00:00     sleep
 5677 pts/1    00:00:00   watch
 5681 pts/1    00:00:00     watch
 5682 pts/1    00:00:00       ps

이것은 두 번째입니다 sleep 10.

  PID TTY          TIME CMD
29190 pts/1    00:00:00 bash
 5676 pts/1    00:00:00   bash
 5691 pts/1    00:00:00     sleep
 5677 pts/1    00:00:00   watch
 5694 pts/1    00:00:00     watch
 5695 pts/1    00:00:00       ps

이것은 세 번째입니다 sleep 10.

  PID TTY          TIME CMD
29190 pts/1    00:00:00 bash
 5676 pts/1    00:00:00   bash
 5704 pts/1    00:00:00     sleep
 5677 pts/1    00:00:00   watch
 5710 pts/1    00:00:00     watch
 5711 pts/1    00:00:00       ps

서로 다른 중괄호 중첩 수준에서 호출되었음에도 불구하고 세 가지 절전 모드는 실제로 Bash의 PID 5676 내에 유지됩니다. 그래서 귀하의 문제는 | ps -H.

결론적으로

(예: 파이프)를 사용 | ps -H하면 추가 하위 쉘이 생성되므로 무슨 일이 일어나고 있는지 물어볼 때 해당 방법을 사용하지 마세요.

답변3

나는 테스트 결과를 게시할 것이며, 이를 통해 bash는 다음과 같은 경우 그룹 명령에 대한 하위 쉘을 생성한다는 결론을 내릴 것입니다.오직파이프라인의 일부인 경우 서브셸에서도 호출되는 함수를 호출하는 것과 같습니다.

$ { A=1; { A=2; sleep 2; } ; echo $A; }
2

$ { A=1; { A=2; sleep 2; } | sleep 1; echo $A; }
1

관련 정보