![내장 명령을 사용할 때 쉘이 포크됩니까?](https://linux55.com/image/84624/%EB%82%B4%EC%9E%A5%20%EB%AA%85%EB%A0%B9%EC%9D%84%20%EC%82%AC%EC%9A%A9%ED%95%A0%20%EB%95%8C%20%EC%89%98%EC%9D%B4%20%ED%8F%AC%ED%81%AC%EB%90%A9%EB%8B%88%EA%B9%8C%3F.png)
명령을 실행하면 type type
stdout 결과가 나타납니다.
이제 다음 명령을 시도합니다.
type type > abc.txt
abc.txt
따라서 이 명령이 동일한 프로세스(bash 자체)에서 실행되면 파일 설명자 1이 을 가리 킵니다 abc.txt
. abc.txt
에게 abc.txt
.
그러나 결과는 항상 표준 출력으로 인쇄됩니다. 이것은 쉘 내장이 포크된 프로세스에서 실행되고 있음을 의미합니까?
답변1
일반적으로 명령을 리디렉션하기 위해 쉘이 해야 할 일은 자식 프로세스를 포크하고 자식 프로세스에서만 리디렉션한 다음(부모 파일 설명자는 영향을 받지 않음) 그 안에서 명령을 실행하는 것입니다(부모는 단지 기다리는 동안) 어린이) .
내장 명령(또는 복합 명령 또는 함수...)의 경우 포크나 실행이 없습니다. 그러나 리디렉션된 내장 명령이 종료된 후 파일 설명자는 이전 상태로 되돌아갑니다.
이를 위해 쉘은 리디렉션을 수행하기 전에 리디렉션된 파일 설명자의 복사본을 다른 파일 설명자에 저장하고 해당 파일 설명자를 O_CLOEXEC 플래그로 표시합니다(내장 기능이 eval
또는 같은 명령을 실행하는 경우 command
). 반환하면 쉘은 파일 설명자를 복원합니다.
예를 들어, 다음 명령을 실행하면 다음이 표시됩니다.
strace sh -c 'echo test > /dev/null; :'
표시되는 내용(관련 항목만 포함):
open("/dev/null", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3
: 리디렉션할 파일을 엽니다.fcntl(1, F_DUPFD, 10) = 10
: 원시 stdout을 첫 번째 사용 가능한 fd >= 10(여기서는 10)에 복사합니다.fcntl(10, F_SETFD, FD_CLOEXEC) = 0
:O_CLOEXEC 플래그를 설정합니다.dup2(3, 1) = 1
: 리디렉션된 파일을 표준 출력으로 설정합니다.close(3) = 0
: 더 이상 필요 없어요write(1, "test\n", 5) = 5
:echo는 실행되어 표준 출력에 "test\n"을 씁니다(이제 /dev/null로 리디렉션됨).dup2(10, 1) = 1
: 표준 출력 복원close(10) = 0
: 더 이상 필요하지 않은 fd 10을 닫습니다.
Bourne 셸에서 복합 명령을 리디렉션하면 분기가 발생합니다( then 에 a=0; { a=1; echo "$a"; } >&2; echo "$a"
나와 있음 ). 이 문제를 해결하려면 실제로 위의 작업을 수동으로 수행해야 합니다.1
0
바꾸다
while cmd1; do cmd2; i=`expr "$i" + 1`; done > file
당신은 이것을 해야 합니다:
exec 3>&1 > file
while cmd1 3>&-; do cmd2 3>&-; i=`expr "$i" + 1 3>&-`; done
exec >&3 3>&-
( 3>&-
fd에는 O_CLOEXEC 플래그가 없으므로 각 명령마다 하나씩)
이전 버전의 Bourne 셸에서는 내장 명령을 리디렉션할 수 없었습니다. pdp11을 에뮬레이션하는 Unix V7에서:
$ eval a=1 > /tmp/x
illegal io
$ read a < /etc/passwd
illegal io
답변2
출력 리디렉션
파일 설명자는 표준 출력 스트림을 1
나타냅니다 . stdout
에서 출력 리디렉션을 사용할 때 type type > abc.txt
셸은 쓰기 위해 파일을 열고 터미널 장치가 아닌 열린 파일을 가리키도록 abc.txt
파일 설명자를 수정합니다 .1
그러나 이 리디렉션은 다음 경우에만 작동합니다.현재 명령실행 중이므로 이것이아니요명령이 분기된 프로세스(또는 하위 쉘)에서 실행됨을 의미합니다.
지속적인 리디렉션
리디렉션을 지속하려면 exec
내장 셸을 사용하여 파일 설명자를 수정할 수 있습니다. 예를 들어 연속 명령의 표준 출력을 리디렉션하려면 다음 명령을 실행하세요.
exec >abc.txt
모든 명령 출력이 터미널 장치 대신 파일로 리디렉션되면 쉘 세션을 사용하기 어렵기 때문에 이 명령을 실행할 때 주의하십시오. (파일 설명자)가 가리키는 동일한 장치로 파일 설명자를 리디렉션하여 stdout
파일 설명자를 터미널 출력 장치로 복원 할 수 있습니다.stderr
2
exec >&2
관련 리소스
자세한 내용은 다음을 참조하세요.
답변3
명령이 완료되면 입력 파일이 즉시 닫혀 다른 프로세스에서 쓸 수 있게 되고 파일 설명자가 해제되며 하위 프로세스가 종료됩니다.