서브쉘을 생성하는 쉘에 () 그룹 명령이 필요합니까?

서브쉘을 생성하는 쉘에 () 그룹 명령이 필요합니까?

내 책에서(소벨의Linux 실용 가이드, 4e) 텍스트는 다음과 같습니다.

대괄호 제어 연산자를 사용하여 명령을 그룹화할 수 있습니다. 이 기술을 사용하면 셸은 각 그룹에 대해 하위 셸이라는 자체 복사본을 만듭니다. 각 명령 세트를 목록으로 처리하고 각 명령을 실행하기 위한 새로운 프로세스를 생성합니다.

오해하고 싶지 않아 여기에 질문을 하게 되었습니다. 서브쉘 생성 여부~ 해야 하다이러한() 그룹 명령을 사용해야 합니까, 아니면 동일한 하위 판매에서 특정 명령이 실행되도록 하기 위한 방법입니까?

예를 들어 보겠습니다. 명령(에서 실행 가능 PATH) a과 가 있다고 가정합니다 b. 명령 프롬프트에 다음을 입력하면 어떤 차이가 있습니까?

  1. a ; b

  2. (a ; b)

  3. (a) ; (b)

답변1

a평등 foo=xyz하고 b평등 하자 echo $foo. 아니면 오히려 함수로 정의해 보겠습니다.

a() { foo=xyz; }
b() { echo $foo; }

그런 다음 표시되는 각 변형을 시도해 보겠습니다. 각 경우 foo첫 번째로 초기화하고 abc끝에 값을 인쇄합니다. foo오른쪽 출력:

  1. foo=abc; a ; b; echo $foo=> xyz,xyz
  2. foo=abc; (a ; b); echo $foo=> xyz,abc
  3. foo=abc; (a) ; (b); echo $foo=> abc,abc

따라서 첫 번째 할당은 기본 수준에서 발생하므로 나머지 스크립트에서 볼 수 있습니다. (이러한 함수는 { ..; }그룹화 구성을 사용하므로 기본 셸에서 실행됩니다.) 두 번째에서는 첫 번째 인쇄 출력과 동일한 하위 셸에서 할당이 발생하지만 나머지 스크립트에는 영향을 미치지 않습니다. 세 번째에서는 할당이 첫 번째 하위 셸에서 발생하고 나중에 스크립트가 아닌 해당 하위 셸에서만 표시됩니다.

그런 다음 다시 의 실행 파일에 대해 물으셨는데 PATH어쨌든 셸의 실행 환경에 영향을 주지 않기 때문에 하위 셸에서 실행되는지 여부는 중요하지 않습니다. 즉, ls와 같습니다 (ls). 그러나 쉘 내장의 경우 차이점이 중요합니다. 예를 들어 read(변수 설정) 또는 exit((하위)쉘 종료)을 고려하십시오.


명령 대체도 서브셸에서 실행됩니다. 예를 들어

foo=abc
echo $(foo=xyz; echo $foo)
echo $foo

인쇄 xyz하고 abc.

물론 명령 대체 구문도 괄호를 사용하므로 일정한 대칭이 있습니다. (그렇다면 (( ... ))그것은 완전히 다른 문제입니다.)


셸과 비동기적으로 또는 동시에 명령을 실행하는 모든 작업은 반드시 하위 셸도 시작해야 합니다. 그렇게 하려면 기본 셸 프로세스를 수정할 수 없는 새 프로세스를 생성해야 하기 때문입니다.

일반적인 경우는 파이프입니다. 에서 foo | bar | doo및 둘 다 서브쉘 foo에서 실행 되며 서브쉘 또는 기본 쉘 환경에서 실행될 수 있습니다.bardoo

예를 들어

foo=abc
{ foo=xyz; echo $foo; } | cat
echo $foo

인쇄 xyz, abc.

바라보다:내 변수가 하나의 "읽는 동안" 루프에서는 로컬이지만 겉보기에 유사한 다른 루프에서는 로컬이 아닌 이유는 무엇입니까?

foo &분명히 , <( foo )프로세스 대체( ) 또는 기타 유사한 수단을 사용하여 백그라운드에서 명시적으로 무언가를 실행하는 것도 서브쉘을 시작합니다.


어쨌든 ( .. )서브쉘을 시작하려면 명시적으로 서브쉘을 시작해야 합니다. 다른 사람들에게는 그것이 부작용이라고 말할 수도 있습니다.

답변2

이 세 줄은 서로 다른 일을 합니다.

[me@here foo]$ echo A-$BASHPID ; echo B-$BASHPID
A-534171
B-534171
[me@here foo]$ (echo A-$BASHPID ; echo B-$BASHPID)
A-534798
B-534798
[me@here foo]$ (echo A-$BASHPID) ; (echo B-$BASHPID)
A-534808
B-534809

먼저 현재 셸의 컨텍스트에서 a를 실행한 다음 b를 실행합니다(이 예에서는 pid=534171). 두 번째는 새 하위 쉘(pid=534798)을 생성한 다음 해당 새 하위 쉘에서 a를 실행하고 b를 실행합니다. 세 번째는 새로운 하위 쉘(pid=534808)을 생성하고 그 안에서 실행합니다. 서브쉘이 종료된 후 다른 서브쉘(pid=534809)을 생성하고 해당 서브쉘에서 b를 실행합니다. 이러한 하위 쉘은 일반적으로 원래 쉘에서 전체 환경을 상속하지 않으며(예: 내보내지 않은 쉘 변수, 파일 설명자, 'ERR, DEBUG, RETURN 트랩 처리는 특수한 경우입니다) 하위 쉘 환경의 일부는 명시적으로 변경됩니다(프로세스 IDS, 쉘 역사...). 하위 쉘에서 실행되는 명령은 일반적으로 상위 쉘 환경을 수정할 수 없습니다.

[me@here foo]$ A=foo
[me@here foo]$ A=bar
[me@here foo]$ (A=baz)
[me@here foo]$ echo $A
bar

이진 실행 파일도 이러한 하위 쉘에서 시작됩니다.할 수 있다차이점을 발견하고 다르게 행동하십시오.

관련 정보