Sự không nhất quán của chuyển hướng stderr giữa tcsh và các shell khác


8

Tôi đang gặp vấn đề với chuyển hướng trong tcsh.

Hãy xem xét các lệnh sau: vi --versionvi --xxx. Và giả sử điều này là trên một máy có vihỗ trợ --versiontùy chọn. Tùy chọn --xxxnày không hợp lệ và do đó vimsẽ hiển thị nội dung nào đó qua stderr.

Theo lý do đó, sử dụng 2> /dev/nullvới cả hai lệnh này sẽ cung cấp đầu ra cho trường hợp hợp lệ và không có đầu ra nào cho trường hợp không hợp lệ.

Và đó những gì tôi thấy trong bash, zsh, ksh và dash.

$ vi --xxx 2> /dev/null
$ vi --version 2> /dev/null
VIM - Vi IMproved 7.4 (2013 Aug 10, compiled Oct 20 2014 16:09:17)
...

Tuy nhiên, khi tôi thử điều này trong tcsh, nó cho tôi không có đầu ra trong cả hai trường hợp.

$ vi --xxx 2> /dev/null
$ vi --version 2> /dev/null
(there is no output here)

Chuyện gì đang xảy ra ở đây? Tôi đang chuyển hướng stderrkhông chính xác?

Đây là đầu ra của tcsh --version:

tcsh 6.18.01 (Astron) 2012-02-14 (i686-intel-linux) options wide,nls,dl,al,kan,rh,nd,color,filec

Câu trả lời:


12

Sự không nhất quán này trong thực tế là lý do đầu tiên trong danh sách các lý do tại sao lập trình csh được coi là có hại .

Hoặc nếu bạn chỉ muốn vứt bỏ stderr và để stdout một mình thì sao? Thao tác khá đơn giản, nhỉ?

cmd 2>/dev/null

Hoạt động trong vỏ Bourne. Trong csh, bạn chỉ có thể thực hiện một nỗ lực đáng thương như thế này:

(cmd > /dev/tty) >& /dev/null

Nhưng ai nói rằng stdout là tty của tôi? Vì vậy, nó sai. Thao tác đơn giản này KHÔNG THỂ ĐƯỢC LÀM trong csh.


(khám phá) ! Tôi đã hy vọng điều đó sẽ không xảy ra.
Sildoreth

6
Hoặcsh -c 'cmd 2> /dev/null'
Stéphane Chazelas

1
@ StéphaneChazelas đó là gian lận! :-)
Celada

lý do đầu tiên trong những lý do cuối cùng Đây có phải là một tài liệu tham khảo trong Kinh thánh hay là một lỗi đánh máy cho danh sách của Cameron không?
Emil Jeřábek

@ EmilJeřábek chắc chắn là một lỗi đánh máy! Cảm ơn đã chỉ ra điều đó. Thực tế, tôi thậm chí không có được tài liệu tham khảo Kinh thánh. Có lẽ bởi vì tôi không phải là Cơ đốc giáo, tôi đoán vậy.
Celada

4

2>không phải là một toán tử trong tcsh, bạn đang sử dụng >toán tử và chuyển 2làm đối số cho vi. Điều này có vẻ ổn vì cả hai --xxx--versionthoát vi.

Từ tcsh(1):

   > name
   >! name
   >& name
   >&! name
           The file name is used as standard output.  If the file does not
           exist then it is created; if the file exists, it is  truncated,
           its previous contents being lost.

           If  the shell variable noclobber is set, then the file must not
           exist or be a character  special  file  (e.g.,  a  terminal  or
           `/dev/null')  or an error results.  This helps prevent acciden‐
           tal destruction of files.  In this case the `!'  forms  can  be
           used to suppress this check.

           The  forms  involving  `&' route the diagnostic output into the
           specified file  as  well  as  the  standard  output.   name  is
           expanded in the same way as `<' input filenames are.

Vì vậy, bạn có thể sử dụng >&để chuyển hướng cả thiết bị xuất chuẩn và thiết bị xuất chuẩn ( "đầu ra chẩn đoán" ). Không có cách "rõ ràng" để chỉ chuyển hướng stderr, và đây là một thiếu sót lâu dài của vỏ C, một cách giải quyết nổi tiếng là:

(vi --xxx > /dev/tty) >& /dev/null

Công trình này bằng cách chuyển hướng stdout để /dev/tty(đó là tty hiện hành) trong một subshell (dấu ngoặc đang làm tương tự như trong vỏ bourne), và đầu ra của subshell (đó là chỉ stderr kể từ khi chúng tôi chuyển hướng stdout) được chuyển đến /dev/null(nhưng điều này có thể là bất cứ điều gì, như một tập tin).

Tôi không biết mục tiêu của bạn là gì, nhưng trong trường hợp bạn không thể chắc chắn người dùng đang sử dụng loại vỏ nào, tôi thấy rằng tốt nhất là nên đặt mục tiêu đó một cách rõ ràng; có nhiều vỏ hơn "bourne và csh", chẳng hạn như cá, và cũng có thể có sự không tương thích nhẹ giữa các vỏ Bourne khác nhau và / hoặc một số cấu trúc có thể "xảy ra" để hoạt động trong một vỏ và không ...


Lưu ý rằng điều đó sh -c 'cmd 2> /dev/null'xảy ra trong tất cả các vỏ của các họ Bourne, csh, RC và cá (trên các hệ thống có shvỏ giống như Bourne).
Stéphane Chazelas

@ StéphaneChazelas Vâng, thường hoạt động đối với (rất) các lệnh đơn giản, nhưng nó nhanh chóng trở nên phức tạp do trích dẫn các vấn đề và mọi người thường mắc lỗi ở đây.
Martin Tournoij

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.