리디렉션 연산자는 항상 파일 설명자를 병렬로 여나요?

리디렉션 연산자는 항상 파일 설명자를 병렬로 여나요?

1. 발췌 #1을 고려해보세요:

$ cat test.txt > test.txt
cat: test.txt: input file is output file

입력 파일 설명자가 test.txt를 가리키 도록 cat한 다음 출력 파일 설명자를 test.txt로 설정하려고 하면 위의 오류가 발생합니다. 리디렉션 연산자는 여기에 알려진 것 같으니 cat계속해서 출력 파일 설명자를 test.txt로 설정해 보세요.

2. 발췌 #2를 고려해보세요:

$ cat 1.txt
1:CAT
2:dog
$ sed 's/cat/CAT/g' test.txt
1:CAT
2:dog
$ sed 's/cat/CAT/g' test.txt > test.txt
$ cat test.txt # Note that test.txt is now empty
$

여기서는 파일 출력 설명자가 설정된 sed읽기 모드에서 열리는 test.txt(마지막 매개변수)를 볼 수 있습니다 . test.txt또한 연산자는 '>'파일 읽기를 시작하기 전에 파일 내용을 덮어씁니다.sed

파이프라인의 명령이 병렬로 실행된다는 것을 알고 있지만 리디렉션 연산자의 작동 방식에 대한 정보는 접하지 못했습니다. 모든 지원 링크가 도움이 될 것입니다.

답변1

jordanm이 지적한 문서 외에도 귀하의 질문에 명시된 오해를 바로잡고 싶습니다. 수행된 절차는아니요리디렉션을 처리합니다. 심지어 그들을 거의 알지도 못합니다.쉘은 리디렉션을 처리합니다.

프로그램이 시작되면 stdin(#0), stdout(#1) 및 stderr(#2)의 세 가지 파일이 열립니다. 쉘 프롬프트에서 프로그램을 실행하면 이러한 프로그램이 터미널 장치에 연결되므로 프로그램은 사용자가 입력한 내용(stdin)을 읽고 출력(stdout)과 오류(stderr)를 터미널에 인쇄합니다.

예 를 들어, cat터미널에서 이것을 실행했습니다 . 어떤 파일을 열었는지 확인할 수 있습니다 .tty/dev/pts/31lsof

$ lsof -a -p `pidof cat` -d0,1,2
COMMAND   PID    USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
cat     21257 anthony    0u   CHR 136,31      0t0   34 /dev/pts/31
cat     21257 anthony    1u   CHR 136,31      0t0   34 /dev/pts/31
cat     21257 anthony    2u   CHR 136,31      0t0   34 /dev/pts/31

실제로 터미널이 세 가지 모두에 열려 있음을 알 수 있습니다. 이제 cat < /dev/zero > /dev/null 2>/dev/full세 가지 모두를 리디렉션하는 다소 어리석은 고양이 호출을 시도해 보겠습니다 .

COMMAND   PID    USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
cat     21838 anthony    0r   CHR    1,5      0t0 1030 /dev/zero
cat     21838 anthony    1w   CHR    1,3      0t0 1028 /dev/null
cat     21838 anthony    2w   CHR    1,7      0t0 1031 /dev/full

쉘은 세 개의 장치를 터미널 대신 stdin, stdout 및 stderr로 전달하여 이러한 리디렉션을 구현합니다. 쉘은 파이프를 유사하게 구현합니다. 시도해 봅시다 cat | dd > /dev/null(실제로 다소 어리석은 파이프입니다):

COMMAND   PID    USER   FD   TYPE DEVICE SIZE/OFF     NODE NAME
cat     22507 anthony    0u   CHR 136,31      0t0       34 /dev/pts/31
cat     22507 anthony    1w  FIFO    0,8      0t0 56081395 pipe
cat     22507 anthony    2u   CHR 136,31      0t0       34 /dev/pts/31

COMMAND   PID    USER   FD   TYPE DEVICE SIZE/OFF     NODE NAME
dd      22508 anthony    0r  FIFO    0,8      0t0 56081395 pipe
dd      22508 anthony    1u   CHR 136,31      0t0       34 /dev/null
dd      22508 anthony    2u   CHR 136,31      0t0       34 /dev/pts/31

쉘이 어떻게 파이프를 열고 이를 사용하여 stdout을 catstdin에 연결하는지 확인하십시오 dd. 그리고 그것이 ddstdout을 /dev/null.

실행 중인 명령은 리디렉션에 대해 실제로 알지 못합니다. 그들은 단지 평소처럼 stdin, stdout, stderr을 사용합니다. 이들은 모두 터미널일 수도 있고, 파일, 장치 또는 다른 프로그램으로의 파이프로 리디렉션될 수도 있습니다. 또는 쉘이 지원하는 경우 네트워크 소켓도 가능합니다.

가장 복잡한 파이프라도 실제로는 프로그램을 실행하기 전에 이 세 개의 파일 핸들을 연결하는 방법에 대한 쉘에 대한 지침일 뿐입니다.

(참고: 일부 프로그램은 터미널에 연결된 프로그램 중 하나를 사용하여 다르게 작동하지만 일반적으로 대화식 사용에서 더 사용자에게 친숙합니다. 예를 들어 ls표준 출력이 하나가 아닌 경우 단일 열 출력으로 전환하고 컬러 터미널이 없는 경우 - 일반적으로 원하는 다른 프로그램에 전달하려고 합니다. 일부 프로그램은 stdin이 터미널이 아닌 경우 프롬프트를 다르게 처리합니다.)

답변2

리디렉션 발생첫 번째껍질에. 귀하의 예에서 :

cat test.txt > test.txt

가장 먼저 일어나는 일은 test.txt파일을 자르는 bash opens 입니다. 이제 비어 있으며 이전에 cat매개변수로 실행되었습니다.test.txt

Bash 맨페이지의 리디렉션 섹션에서:

셸에서 해석되는 특수 기호를 사용하여 명령을 실행하기 전에 명령의 입력과 출력을 리디렉션할 수 있습니다. 리디렉션을 사용하여 현재 셸의 실행 환경에서 파일을 열고 닫을 수도 있습니다. 다음 리디렉션 연산자는 간단한 명령 앞이나 명령 내의 어느 위치에나 나타날 수 있거나 명령 뒤에 올 수 있습니다. 리디렉션은 표시된 순서대로 왼쪽에서 오른쪽으로 처리됩니다.

POSIX 사양에는 이것이 처음에 발생해야 함을 나타내는 내용이 없지만 이를 수행하지 않는 쉘은 없습니다.

관련 정보