Sistem Informasi:
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)
Gulir ke CONTOH di bagian bawah jika Anda hanya ingin menggali contoh sederhana yang saya buat.
CATATAN: Saya bukan zsh
pengguna besar .
Saya mencari di fzf
keybindings untuk bash
dan zsh
.
Perhatikan bagaimana keduanya menjalankan perintah variabel $(__fzfcmd)
. __fzfcmd
secara default output fzf
ke stdout dan substitusi parameter hanya menjalankan perintah ( fzf
) yang dihasilkan dari output.
Satu perbedaan antara skrip bash
dan zsh
adalah skrip yang bash
lebih lanjut mem-pipe output $(__fzfcmd)
tetapi zsh
hanya menangkapnya di dalam array. Dugaan saya adalah karena masalah zsh
ketika Anda lebih lanjut mem-pipkan output di fzf
mana Anda tidak dapat input ke fzf
dan proses piped by fzf
tidak mendapatkan stdin. Satu-satunya pilihan Anda adalah ^Z
atau ^C
. ^C
Sepertinya latar belakang proses karena beberapa alasan. Atau mungkin mereka hanya ingin dalam array sehingga mereka bisa bisa berjalan zle vi-fetch-history
di atasnya . The bash
Versi melakukan sihir di kunci mengikat dengan"\e^": history-expand-line
Sekarang fzf
tidak penting. Sepertinya Anda hanya perlu program yang menampilkan ke tty
untuk dipanggil oleh substitusi parameter untuk menyebabkan masalah ini. Jadi saya akan menunjukkan beberapa contoh sederhana.
Berikut adalah beberapa perintah lain yang menghasilkan tty
yang dapat menyebabkan masalah ini di zsh
:
- vipe (jalankan editor di tengah-tengah pipa)
'vim -'
(membuat vim dibaca dari stdin. mirip dengan vipe tetapi tidak akan menampilkan ke stdout)
Dalam contoh di bawah ini, ganti setiap kejadian vipe
dengan vim -
jika Anda tidak ingin melakukan pemasangan terpisah. Ingat saja bahwa vim -
tidak akan menampilkan konten editor ke stdout seperti vipe
halnya.
CONTOH:
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
Sekarang, saya sebagian besar bertanya-tanya mengapa 2)
ada masalah untuk zsh
tetapi tidak untuk bash
dan mengapa 4)
dan 5)
memperbaiki masalah untuk zsh
.
Persyaratan untuk zsh
memiliki masalah ini tampaknya persis seperti yang saya cantumkan pada judul:
- pipa input
- perintah dijalankan oleh substitusi variabel / parameter yang memiliki
tty
output - pipa keluaran
MEMPERBARUI
Saya menambahkan solusi lain yang tidak menyebabkan zsh
masalah ini 5)
,. Ini mirip dengan 4)
tetapi alih-alih mengarahkan stdout
langsung ke stin
, saya mengarahkan kembali ke file yang mengarahkan kembali stdin
menggunakan proses substitusi.
ps
Anda, dalam semua kasus ini tidak ada cangkang yang beku atau macet. Mereka hanya menunggu proses anak dengan cara normal; dan mereka memang akan kembali ke meminta input dengan cara normal setelah proses anak ditangguhkan atau dihentikan. Judul dan badan pertanyaan Anda termasuk premis palsu implisit. "Mengapa cangkangku membeku?" adalah pertanyaan yang tidak dapat dijawab ketika shell Anda tidak benar - benar membeku. Anda akan memiliki pertanyaan yang lebih baik untuk menghapus premis palsu implisit ini.when either a computer program or system ceases to respond to inputs
(echo | $(echo vipe) | cat)
Jawaban:
Saya percaya masalah Anda bermuara pada mengutip ekspansi Anda secara tidak benar.
Mengutip dari zsh: 14 Ekspansi
Perhatikan bahwa Contoh # 2 dalam pertanyaan Anda menghasilkan gema NULL yang tak terbatas, karena:
Dengan kata lain shell tanpa batas menunggu
echo
, karena pembatas default adalah SPACE, gema tidak pernah selesai. Lihat TLDP: Variabel Internal . Ini meninggalkan pipa yang menggantung untukcat
perintah.Sebagai dugaan, saya percaya 4 dan 5 berfungsi karena pengalihan output.
sumber