tty 출력을 갖는 변수 명령으로 stdin 및 stdout을 파이핑 할 때 zsh가 터미널에 입력 할 수 없음


11

시스템 정보 :

macOS Sierra 10.12.6
zsh 5.4.2 (x86_64-apple-darwin16.7.0)
GNU bash, version 4.4.12(1)-release (x86_64-apple-darwin16.3.0)

내가 만든 간단한 예제를 찾으려면 맨 아래 의 예제 로 스크롤하십시오 .

참고 : 나는 큰 zsh사용자가 아닙니다 .


및 의 fzf키 바인딩을 보고있었습니다 .bashzsh

둘 다 어떻게 변수 명령을 실행하는지 주목하십시오 $(__fzfcmd). __fzfcmd기본적 fzf으로 stdout 으로 출력 되고 매개 변수 대체 fzf는 출력 결과로 나오는 명령 ( ) 만 실행 합니다.

bash와 zsh스크립트의 한 가지 차이점 bash은 출력을 추가로 파이프 $(__fzfcmd)하지만 zsh배열 내에서 캡처한다는 것입니다. 내 생각에 때문에 문제입니다 zsh때 더 파이프의 출력 fzf이되지 입력 할 수있는 fzf프로세스가에 파이프 fzf모든 표준 입력을하지 않습니다. 당신의 유일한 선택은 ^Z또는 ^C입니다. ^C어떤 이유로 프로세스를 배경으로 보인다. 또는 어쩌면 그들은 배열에서 그것을 원했을 때 그것을 실행할zle vi-fetch-history 수 있었을 것 입니다. 이 bash버전은 키 바인딩에서 마술을 수행합니다."\e^": history-expand-line

지금 fzf은 중요하지 않습니다. tty이 문제를 일으키기 위해 매개 변수 대체에 의해 호출되는 프로그램을 필요로하는 것처럼 보입니다 . 간단한 예를 보여 드리겠습니다.

tty이 문제를 일으킬 수있는 다른 명령은 다음과 같습니다 zsh.

  • vipe (파이프 중간에서 편집기 실행)
  • 'vim -' (vidin은 vidin과 비슷하지만 stdout으로 출력되지는 않습니다.)

아래의 예에서 나타나는 모든 경우 교체 vipe와 vim -별도 설치하지 않으려면을. vim -편집기 내용을 표준 출력으로 출력하지 않는다는 것을 기억하십시오 vipe.

예 :

1) echo 1 | vipe | cat            # works in both bash and zsh
2) echo 1 | $(echo vipe) | cat    # works in bash only. zsh problem with no output until I hit `^C`:
   ^C
   zsh: done                    echo 1 | 
   zsh: suspended (tty output)  $(echo vipe) | 
   zsh: interrupt               cat
   # seems like the process is backgrounded. I can still see it in jobs command

3) cat <(echo 1 | $(echo vipe))   # zsh and bash has the problem. I'm guessing because
                                  # the file isn't finished writing and cat is
                                  # blocking vipe's tty output
                                  # both their `^C` output is just:
   ^C # nothing special, as expected

4) cat < <(echo 1 | $(echo vipe)) # works in both bash and zsh
5) echo 1 | $(echo vipe) > >(cat) # works in both bash and zsh

# The following don't have and input pipe to vipe.
# Type something then send EOF with ^D
6) vipe | cat                     # works for both
7) $(echo vipe) | cat             # works for both

지금, 나는 대부분의 이유를 궁금 해서요 2)에 대한 문제가 zsh있지만하지 않는 bash이유 4)및 5)수정에 대한 문제 zsh.

zsh이 문제에 대한 요구 사항은 내가 제목에 넣은 것과 정확히 일치하는 것 같습니다.

  • 입력 파이프
  • tty출력 이있는 변수 / 매개 변수 대체에 의해 실행되는 명령
  • 출력 파이프

최신 정보

zsh이 문제가 발생하지 않는 다른 해결 방법을 추가했습니다 5). 그것은으로 직접 4)리디렉션하는 대신 프로세스 대체 를 사용하여 리디렉션되는 파일로 리디렉션 합니다.stdoutstinstdin


1
출력 결과에서 ps알 수 있듯이 이러한 경우 껍질이 얼거나 붙어 있지 않습니다 . 그들은 단순히 정상적인 방식으로 자식 프로세스를 기다리고 있습니다. 그리고 자식 프로세스가 일시 중지되거나 종료되면 정상적인 방식으로 입력하라는 메시지가 표시됩니다. 질문 제목과 본문에는 암시 적 거짓 전제가 포함됩니다. "왜 껍질이 얼어 붙습니까?" 쉘이 실제로 얼지 않는 경우에는 대답 할 수없는로드 된 질문 입니다. 이 암시 적 전제를 제거하는 데 더 좋은 질문이 있습니다.
— JdeBP

좋아, 바꿀 수있어 프로세스가 더 이상 CPU에서 명령을 실행할 수 없다는 의미에서 실제로 동결되지는 않습니다. 당신은 그냥 기다리고 있다는 것이 맞습니다. 그러나 '고착되지'않습니까? 입력을 기다리는 중입니다. 입력 할 수 없습니다. 이것을 간결하게 설명하기에 더 좋은 용어는 무엇입니까? 중단에 대한이 설명과 일치하지 않습니다when either a computer program or system ceases to respond to inputs
— dosentmatter

1
쉘이 입력을 기다리지 않습니다. 아이들을 기다리고 있습니다. 이 질문은 어떻게되는지 간단히 설명하는 것이 좋습니다 . "my shell is frozen"과 같은 가설과 추론을 작성하지 말고 추론에 대해 물어보십시오. 무슨 설명하고 그것에 대해 질문 : 특수 문자 터미널 입력 시퀀스 (즉, 일반적으로 포 그라운드 작업을 중단하거나 인터럽트하거나 작업을 종료하거나 터미널에서 프로세스 독서에 EOF 표시를 보낼 것) 영향을주지 않습니다. 무슨 일이야? 왜? . 이것은 데비안 리눅스와 FreeBSD / TrueOS에서 복제 할 수 있습니다.
— JdeBP

1
나는 한 zsh을 개발 메일 링리스트에 버그를보고 . 지금, 당신은 그것을 서브 (echo | $(echo vipe) | cat)
— 쉘로

1
공정 대체 백그라운드에서 시작되었는지 사실은 내가 생각하는 문서화 된 (또는 적어도라고도 함)입니다
— 스테판 Chazelas가를

답변:


0

귀하의 문제는 귀하의 확장을 부적절하게 인용하는 것으로 귀결됩니다.

zsh : 14 확장 에서 인용

괄호로 묶은 명령 앞에 $(...)' ...' 와 같은 달러 기호가 있거나 ' ' 와 같은 억음 악센트로 인용 된 명령 은 표준 출력으로 바뀌고 마지막 줄 바꿈이 삭제됩니다. 대체가 큰 따옴표로 묶이지 않은 경우 IFS 매개 변수를 사용하여 출력이 단어로 나뉩니다. 치환은 $(cat foo)동등하지만 의해 빠르게 대체 될 수있다 $(<foo). 두 경우 모두 GLOB_SUBST 옵션이 설정되면 출력이 파일 이름 생성에 적합합니다.

귀하의 질문에있는 예제 # 2는 다음과 같은 이유로 무한 에코가 NULL임을 유의하십시오.

대체가 큰 따옴표로 묶이지 않은 경우 IFS 매개 변수를 사용하여 출력이 단어로 나뉩니다.

즉, echo기본 분리 문자가 SPACE이므로 에코가 완료되지 않으므로 쉘은 무한정 기다립니다 . TLDP : 내부 변수를 참조하십시오 . 이것은 cat명령을 위해 매달린 파이프를 남깁니다 .

직감적으로 출력 리디렉션으로 인해 4와 5가 작동한다고 생각합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.