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는 출력 결과로 나오는 명령 ( ) 만 실행 합니다.

bashzsh스크립트의 한 가지 차이점 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으로 출력되지는 않습니다.)

아래의 예에서 나타나는 모든 경우 교체 vipevim -별도 설치하지 않으려면을. 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.