Thông tin hệ thống:
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)
Di chuyển đến VÍ TRÍ ở phía dưới nếu bạn chỉ muốn tìm hiểu các ví dụ đơn giản mà tôi đã thực hiện.
LƯU Ý: Tôi không phải là zsh
người dùng lớn .
Tôi đã nhìn vào các fzf
keybindings cho bash
và zsh
.
Lưu ý cách cả hai chạy một lệnh biến $(__fzfcmd)
. __fzfcmd
theo mặc định đầu ra fzf
cho thiết bị xuất chuẩn và thay thế tham số chỉ chạy lệnh ( fzf
) kết quả từ đầu ra.
Một điểm khác biệt giữa tập lệnh bash
và zsh
tập lệnh là bash
cái tiếp tục dẫn đầu ra của đầu ra $(__fzfcmd)
nhưng zsh
chỉ bắt nó bên trong một mảng. Tôi đoán là do có vấn đề zsh
khi bạn tiếp tục dẫn đầu ra của fzf
nơi bạn không thể nhập vào fzf
và quá trình được dẫn đến bởi fzf
không nhận được bất kỳ stdin nào. Sự lựa chọn duy nhất của bạn là ^Z
hoặc ^C
. ^C
dường như để làm nền cho quá trình này Hoặc có lẽ họ chỉ muốn nó trong một mảng để họ có thể chạy zle vi-fetch-history
trên nó . Các bash
phiên bản hiện một số phép thuật trong khóa ràng buộc với"\e^": history-expand-line
Bây giờ fzf
không quan trọng. Có vẻ như bạn chỉ cần một chương trình xuất ra tty
để được gọi bằng cách thay thế tham số để gây ra vấn đề này. Vì vậy, tôi sẽ chỉ ra một số ví dụ đơn giản hơn.
Dưới đây là một số lệnh khác xuất ra tty
có thể gây ra sự cố này trong zsh
:
- vipe (chạy trình soạn thảo ở giữa một đường ống)
'vim -'
(làm cho vim đọc từ stdin. tương tự như vipe nhưng sẽ không xuất ra stdout)
Trong các ví dụ dưới đây, thay thế mọi lần xuất hiện vipe
bằng vim -
nếu bạn không muốn thực hiện cài đặt riêng. Chỉ cần nhớ rằng vim -
sẽ không xuất nội dung trình soạn thảo ra thiết bị xuất chuẩn như thế vipe
nào.
VÍ DỤ:
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
Bây giờ, tôi chủ yếu tự hỏi tại sao 2)
có một vấn đề cho zsh
nhưng không phải cho bash
và tại sao 4)
và 5)
khắc phục vấn đề cho zsh
.
Các yêu cầu zsh
để có vấn đề này dường như chính xác là những gì tôi đặt trong tiêu đề:
- ống đầu vào
- lệnh chạy bằng thay thế biến / tham số có
tty
đầu ra - ống đầu ra
CẬP NHẬT
Tôi đã thêm một cách giải quyết khác mà không gây ra zsh
vấn đề này 5)
. Nó tương tự 4)
nhưng thay vì chuyển hướng stdout
trực tiếp vào stin
, tôi chuyển hướng nó thành một tệp chuyển hướng stdin
sử dụng thay thế quy trình.
when either a computer program or system ceases to respond to inputs
(echo | $(echo vipe) | cat)
ps
sẽ cho bạn biết, không có trường hợp nào trong số này là vỏ bị đóng băng hoặc bị kẹt. Họ chỉ đơn giản là chờ đợi các quá trình con theo cách thông thường; và họ thực sự sẽ lặp lại để nhắc nhở đầu vào theo cách thông thường một khi các quá trình con đó bị đình chỉ hoặc chấm dứt. Tiêu đề và cơ thể câu hỏi của bạn bao gồm một tiền đề sai ngầm định. "Tại sao vỏ của tôi đóng băng?" là một câu hỏi được tải không thể trả lời khi vỏ của bạn không thực sự đóng băng ở nơi đầu tiên. Bạn sẽ có một câu hỏi tốt hơn để loại bỏ tiền đề sai lầm ngầm này.