zsh không thể nhập vào terminal khi đặt stdin và stdout bằng lệnh biến có đầu ra tty


11

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à zshngười dùng lớn .


Tôi đã nhìn vào các fzfkeybindings cho bashzsh.

Lưu ý cách cả hai chạy một lệnh biến $(__fzfcmd). __fzfcmdtheo mặc định đầu ra fzfcho 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 bashzshtập lệnh là bashcái tiếp tục dẫn đầu ra của đầu ra $(__fzfcmd)nhưng zshchỉ bắt nó bên trong một mảng. Tôi đoán là do có vấn đề zshkhi bạn tiếp tục dẫn đầu ra của fzfnơi bạn không thể nhập vào fzfvà quá trình được dẫn đến bởi fzfkhông nhận được bất kỳ stdin nào. Sự lựa chọn duy nhất của bạn là ^Zhoặc ^C. ^Cdườ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-historytrên nó . Các bashphiê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ờ fzfkhô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 ttycó 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 vipebằ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ế vipenà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 zshnhưng không phải cho bashvà tại sao 4)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 zshvấn đề này 5). Nó tương tự 4)nhưng thay vì chuyển hướng stdouttrực tiếp vào stin, tôi chuyển hướng nó thành một tệp chuyển hướng stdinsử dụng thay thế quy trình.


1
Như đầu ra của pssẽ 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.
JdeBP

Ok, tôi có thể thay đổi nó. Nó không thực sự bị đóng băng theo nghĩa là quá trình không thể chạy các hướng dẫn trên CPU nữa. Bạn đúng rằng nó chỉ đang chờ đợi. Nhưng nó không bị 'kẹt'? Nó đang chờ đầu vào Tôi không thể cung cấp nó. Một thuật ngữ tốt hơn để mô tả chính xác này là gì? Nó không phù hợp với mô tả này của hang when either a computer program or system ceases to respond to inputs
dosentmatter 19/12/17

1
Shell không chờ đầu vào. Nó đang đợi con của nó. Câu hỏi này sẽ được đặt tốt hơn chỉ đơn giản là mô tả những gì xảy ra . Đừng hình thành các giả thuyết và suy luận như "vỏ của tôi bị đóng băng" và sau đó hỏi về các suy luận. Mô tả những gì xảy ra và hỏi về điều đó: Các chuỗi đầu vào của ký tự đặc biệt (thường sẽ tạm ngưng công việc nền trước, hoặc làm gián đoạn hoặc bỏ công việc hoặc gửi chỉ thị EOF đến quá trình đọc từ thiết bị đầu cuối) không có hiệu lực. Chuyện gì đang xảy ra vậy? Tại sao? . Điều này có thể sao chép trên Debian Linux và FreeBSD / TrueOS, nhân tiện,
JdeBP

1
Tôi đã báo cáo lỗi trong danh sách gửi thư phát triển zsh . Hiện tại, bạn sẽ có thể làm việc xung quanh nó bằng cách gói nó trong một mạng con(echo | $(echo vipe) | cat)
Stéphane Chazelas 23/03/18

1
Thực tế là sự thay thế quá trình được bắt đầu trong nền được ghi lại theo tôi nghĩ (hoặc ít nhất được biết đến)
Stéphane Chazelas

Câu trả lời:


0

Tôi tin rằng vấn đề của bạn có thể dẫn đến việc trích dẫn không chính xác những mở rộng của bạn.

Trích dẫn từ zsh: 14 Mở rộng

Một lệnh được đặt trong dấu ngoặc đơn đứng trước ký hiệu đô la, như $(...), hoặc được trích dẫn bằng dấu trọng âm, như ' ...', được thay thế bằng đầu ra tiêu chuẩn của nó, với bất kỳ dòng mới nào bị xóa. Nếu sự thay thế không được đặt trong dấu ngoặc kép, đầu ra được chia thành các từ bằng tham số IFS. Sự thay thế $(cat foo)có thể được thay thế bằng tương đương nhưng nhanh hơn $(<foo). Trong cả hai trường hợp, nếu tùy chọn GLOB_SUBST được đặt, đầu ra đủ điều kiện để tạo tên tệp.

Lưu ý rằng Ví dụ # 2 trong câu hỏi của bạn dẫn đến tiếng vang vô hạn của NULL, do:

Nếu sự thay thế không được đặt trong dấu ngoặc kép, đầu ra được chia thành các từ bằng tham số IFS.

Nói cách khác, shell chờ đợi vô hạn echo, bởi vì dấu phân cách mặc định là SPACE, tiếng vang không bao giờ hoàn thành. Xem TLDP: Biến nội bộ . Điều này để lại một ống treo cho catlệnh.

Như một linh cảm, tôi tin rằng 4 và 5 hoạt động do chuyển hướng đầu ra.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.