システム情報:
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
ユーザーではありません。
どちらも変数コマンドを実行する方法に注意してください$(__fzfcmd)
。__fzfcmd
デフォルトでfzf
はstdoutに出力し、パラメーター置換fzf
は出力から得られたコマンド()を実行するだけです。
間の一つの違いbash
とzsh
スクリプトがあることbash
つの更なるパイプの出力は$(__fzfcmd)
なく、zsh
単に配列の内部に取り込みます。私の推測では、入力できない場所zsh
の出力をさらにパイプfzf
するfzf
と、パイプされたプロセスがfzf
stdinを取得できないという問題が発生したためです。あなたの唯一の選択は、^Z
または^C
です。^C
なんらかの理由でプロセスの背景になっているようです。または、多分彼らはそれを実行zle vi-fetch-history
することができるように配列でそれを望んだだけです。bash
バージョンは、との結合キーにいくつかの魔法を行います"\e^": history-expand-line
今fzf
は重要ではありません。tty
この問題を発生させるには、パラメータ置換によって呼び出されるに出力するプログラムが必要なだけのようです。そこで、いくつかの簡単な例を示します。
でtty
この問題を引き起こす可能性のあるに出力される他のいくつかのコマンドを次に示しますzsh
。
- vipe(パイプの途中でエディターを実行)
'vim -'
(vimをstdinから読み取ります。vipeと同様ですが、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)
いますが、にstdout
直接リダイレクトする代わりに、プロセス置換stin
をstdin
使用してリダイレクトするファイルにリダイレクトします。
when either a computer program or system ceases to respond to inputs
(echo | $(echo vipe) | cat)
ps
わかるように、これらのいずれの場合も、シェルはフリーズまたはスタックしていません。彼らは単に通常の方法で子プロセスを待っています。そして、それらの子プロセスが一時停止または終了すると、通常の方法で入力を求めるプロンプトにループバックします。質問のタイトルと本文に暗黙の誤った前提が含まれています。「なぜシェルがフリーズするのですか?」シェルが最初に実際にフリーズしていない場合、答えのないロードされた質問です。この暗黙の誤った前提を取り除くためのより良い質問があるでしょう。