stdin
문자열을 수집한 다음 완료되면 다시 연결하는 프로그램을 원한다고 가정해 보겠습니다 .
다음 트릭을 사용하면 이 작업을 수행할 수 있다는 것을 알고 있습니다.
(echo id; cat) | sh
좋은 결과. stdin
사용중이라 닫히지 않습니다 cat
. 그러나 출력은 지저분합니다.
더 깊이 파고보니 그것이 누락된 것을 발견했습니다 tty
.
내 이해가 정확하다면 sh
파이프라인에 구멍이 없는 것입니다 tty
.
내가 찾은 비결은 expect
.
그냥 파일에 넣으세요:
spawn sh
reattach
그런 다음 cat
통제력을 회복하면 다음을 수행하십시오.
expect exp.sh
tty
이것은 내가 필요한 모든 것을 할 수 있게 해주기 때문에 좋습니다 : ssh
, tmux
등등...
내가 왜 그런지 이해하지 못하는 유일한 것은 내가 입력한 모든 내용을 터미널에서 다시 볼 수 있다는 것입니다.
예:
(echo whoami; cat) | sh
moon
expect exp.sh
spawn sh
sh-3.2$ whoami
whoami
moon
whoami
로그인하기 전에 출력의 마지막 줄을 기록해 두십시오 .
누군가 나에게 이유를 설명해 줄 수 있습니까? 그것은 직접적으로 연결되어 있기 때문에 분명히 stdout
from의 속성 이 아닙니다 . 예, 어리석더라도 다음을 시도했습니다. 그런 다음 아무 일도 일어나지 않았습니다.cat
sh
(echo id; cat > /dev/null) | sh
그러면 키보드로 입력한 내용이 표시되지 않습니다 tty
/속성?pty
답변1
{ echo 'exec <&3 3<&-; id' | sh -si; } 3<&0
대부분의 구현에서 작동하는 것 같습니다 sh
. 우리는 대화형 쉘에 요청하고 -i
(그렇지 않으면 일부 쉘은 터미널 장치가 아니기 때문에 stdin을 비활성화합니다) 쉘의 stdin을 파이프로 시작한 다음 이전에 exec <&3
설명자에 .stdin으로 저장한 원본(외부) 파일로 변경하도록 지시합니다. 삼 3<&0
.
우리는 이것을한다앞으로실행 중이지만 id
여전히 동일한 명령을 사용 중입니다.철사, 표준 입력 id
도 복원됩니다. 표준 입력을 읽지 않기 때문에 중요하지 않지만 id
편집기나 셸과 같은 대화형 명령이 됩니다.
당신이 입력한 내용을 내가 본 이유는 무엇입니까 (echo id | cat) | sh
? 귀하의 구현은 sh
매우 오래된 버전이며 bash
대화형 모드에서 실행 중인 것 같습니다. -i
사용한 것처럼 프롬프트가 표시되는 것을 볼 수 있습니다 .
그런 다음 자체 라인 편집기를 구현하지만 tty 장치의 자체 라인 편집기를 비활성화할 수 있는 방법이 없습니다(표준 입력이 tty 장치가 아닌 파이프이기 때문에). 따라서 tty 장치를 통해 입력한 내용에 대한 에코를 얻게 됩니다. 줄 규칙이 표시되고 Enter를 누르자마자 cat
파이프에서 즉시 작성된 후행 개행 문자를 포함하여 줄 버퍼의 모든 내용이 즉시 표시되고 bash
자체 줄 편집기의 일부로 bash
출력됩니다 .echo
당신이 그렇게한다면 나는 의심합니다 :
stty -icanon -echo; (echo id; cat) | sh; stty sane
bash
더 나은 동작을 얻을 수 있으며, 입력한 모든 문자를 직접 수신하므로 readline 줄 편집 기능을 사용할 수도 있습니다 .
사용자가 대화형 셸을 사용하기 전에 명령을 자동으로 실행하기 위한 추가 옵션은 다음을 참조하세요.