[unix] 중괄호로 배시 서브 쉘 생성

따르면 , 중괄호 명령 목록을 배치하는 것은 현재 셀 환경에서 실행되는리스트를 야기한다. 서브 쉘이 작성되지 않습니다 .

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입니까?



답변

파이프 라인에서 모든 명령은 서로 다른 프로세스에서 동시에 파이프로 연결된 stdout / stdin과 함께 실행됩니다.

에서

cmd1 | cmd2 | cmd3

세 명령은 모두 다른 프로세스에서 실행되므로 둘 중 적어도 두 개는 하위 프로세스에서 실행되어야합니다. 일부 쉘은 현재 쉘 프로세스에서 빌드 중 하나를 실행하지만 ( read파이프 라인이 스크립트의 마지막 명령 과 같은 경우 또는 파이프 라인이 스크립트의 마지막 명령 인 경우), bash개별 프로세스에서 실행합니다 ( lastpipe최근 bash버전 의 옵션 및 일부 특정 조건 제외) ).

{...}그룹 명령. 해당 그룹이 파이프 라인의 일부인 경우 간단한 명령처럼 별도의 프로세스에서 실행해야합니다.

에서:

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

a; b "$?"별도의 프로세스인지 평가하려면 셸이 필요하므로 하위 셸이 필요합니다. 셸은 b해당 그룹에서 마지막으로 실행되는 명령이므로 포크하지 않아도 최적화 할 수 있습니다. 일부 포탄은 그렇게하지만 분명히하지 않습니다 bash.


답변

중괄호를 중첩하면 새 하위 쉘을 호출해야하는 추가 범위의 범위 지정을 작성하는 것으로 나타납니다. ps -H출력 에서 Bash의 두 번째 사본에서이 효과를 볼 수 있습니다 .

첫 번째 수준의 중괄호에 명시된 프로세스 만 원래 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파이프 (예 : 파이프)를 사용 하면 추가 하위 셸이 발생하므로 진행중인 문제를 조사 할 때 해당 방법을 사용하지 마십시오.


답변

테스트 결과를 게시 할 것인데, bash는 그룹 명령에 대한 하위 쉘을 파이프 라인의 일부 인 경우 에만 호출합니다. 하위 셸에서.

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

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


답변