내 책에서(소벨의Linux 실용 가이드, 4e) 텍스트는 다음과 같습니다.
대괄호 제어 연산자를 사용하여 명령을 그룹화할 수 있습니다. 이 기술을 사용하면 셸은 각 그룹에 대해 하위 셸이라는 자체 복사본을 만듭니다. 각 명령 세트를 목록으로 처리하고 각 명령을 실행하기 위한 새로운 프로세스를 생성합니다.
오해하고 싶지 않아 여기에 질문을 하게 되었습니다. 서브쉘 생성 여부~ 해야 하다이러한() 그룹 명령을 사용해야 합니까, 아니면 동일한 하위 판매에서 특정 명령이 실행되도록 하기 위한 방법입니까?
예를 들어 보겠습니다. 명령(에서 실행 가능 PATH
) a
과 가 있다고 가정합니다 b
. 명령 프롬프트에 다음을 입력하면 어떤 차이가 있습니까?
a ; b
(a ; b)
(a) ; (b)
답변1
a
평등 foo=xyz
하고 b
평등 하자 echo $foo
. 아니면 오히려 함수로 정의해 보겠습니다.
a() { foo=xyz; }
b() { echo $foo; }
그런 다음 표시되는 각 변형을 시도해 보겠습니다. 각 경우 foo
첫 번째로 초기화하고 abc
끝에 값을 인쇄합니다. foo
오른쪽 출력:
foo=abc; a ; b; echo $foo
=>xyz
,xyz
foo=abc; (a ; b); echo $foo
=>xyz
,abc
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
에서 실행 되며 서브쉘 또는 기본 쉘 환경에서 실행될 수 있습니다.bar
doo
예를 들어
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
이진 실행 파일도 이러한 하위 쉘에서 시작됩니다.할 수 있다차이점을 발견하고 다르게 행동하십시오.