Làm thế nào để ống stdout trong khi giữ nó trên màn hình? (và không phải cho một tập tin đầu ra)


234

Tôi muốn đầu ra tiêu chuẩn của một chương trình trong khi giữ nó trên màn hình.

Với một ví dụ đơn giản ( echosử dụng ở đây chỉ nhằm mục đích minh họa):

$ echo 'ee' | foo
ee <- đầu ra tôi muốn xem

Tôi biết tee có thể sao chép thiết bị xuất chuẩn vào tập tin nhưng đó không phải là điều tôi muốn.
$ echo 'ee' | tee output.txt | foo

Tôi đã thử
$ echo 'ee' | tee /dev/stdout | foonhưng nó không hoạt động vì đầu ra tee /dev/stdoutđược dẫn đếnfoo


6
echo 'ee' | tee /dev/stderrTuy nhiên, xin lưu ý rằng nó hoạt động, vì vậy nếu yêu cầu "trên màn hình" của bạn được thỏa mãn bởi stderr, điều đó sẽ được thực hiện.
nh2

Câu trả lời:


344

Đây là một giải pháp hoạt động trên bất kỳ triển khai Unix / Linux nào, giả sử nó quan tâm đến việc tuân theo POSIXtiêu chuẩn. Nó hoạt động trên một số môi trường không phải là Unix như cygwinquá.

echo 'ee' | tee /dev/tty | foo

Tham khảo: Thông số kỹ thuật cơ sở nhóm mở Vấn đề 7 IEEE Std 1003.1, Phiên bản 2013, §10.1 :

/ dev / tty

Liên kết với nhóm quy trình của quá trình đó, nếu có. Nó rất hữu ích cho các chương trình hoặc thủ tục shell muốn chắc chắn viết tin nhắn đến hoặc đọc dữ liệu từ thiết bị đầu cuối cho dù đầu ra đã được chuyển hướng như thế nào. Nó cũng có thể được sử dụng cho các ứng dụng yêu cầu tên của tệp cho đầu ra, khi muốn nhập đầu ra và rất mệt mỏi để tìm ra thiết bị đầu cuối nào đang được sử dụng. Trong mỗi quy trình, một từ đồng nghĩa cho thiết bị đầu cuối kiểm soát

Một số môi trường như Google Colab đã được báo cáo là không thực hiện /dev/ttytrong khi vẫn có ttylệnh của họ trả lại một thiết bị có thể sử dụng. Đây là một cách giải quyết:

tty=$(tty)
echo 'ee' | tee $tty | foo

hoặc với vỏ Bourne cổ đại:

tty=`tty`
echo 'ee' | tee $tty | foo

5
@static_rtti Tại sao bạn lại bỏ qua năm này qua năm khác tôi trả lời bình luận của bạn?
jlliagre

1
@PaulBissex /dev/ttylà một thiết bị Unix bắt buộc. Bạn đang chạy trong nhà tù BSD?
jlliagre

1
@PaulBissex Đó là lỗi triển khai hoặc cấu hình. Là / dev gắn kết? Điều gì cho thấy "ls -l / dev / tty / dev / tty * / dev"? Xem lists.freebsd.org/pipermail/freebsd-bugs/2012-November/... forums.freebsd.org/threads/...
jlliagre

1
Và bạn có thể xếp tầng teenhư thế này: cat some.log | tee /dev/tty | tee -a other.log | grep -i 'foo' >> foo.logđến 1) đưa tất cả vào bàn điều khiển, 2) đưa tất cả vào một tệp khác, 3) đưa các foodòng vào một tệp khác.
Jesse Chisholm

1
Google Colab không có /dev/tty, nhưng đầu ra của ttycó thể sử dụng được.
Tom Hale

69

Một thứ khác để thử là:

echo 'ee' | tee >(foo)

Đây >(foo)là một sự thay thế quá trình .


1
Nếu tôi muốn chuyển đầu ra của foo sang thanh khác thì sao?
Jack Tang

3
@JackTang - Tôi nghĩ rằng bất kỳ đường ống tiếp theo nào trên đầu ra của foosẽ phải là một phần của quá trình thay thế. Dưới đây là một ví dụ:echo 'ee' | tee file.txt >(wc -c | tr -d ' ')
Nick Chammas

1
Đây là giải pháp cho tôi trên FreeBSD (không / dev / tty)
Paul Bissex

9
@Nick Chammas, Để duy trì một đường ống bình thường, bạn có thể trao đổi kết quả đầu ra của tee : echo 'ee' | tee >(cat) | foo | bar.
Vaelus

18

Quyền truy cập vào "/ dev / stdout" bị từ chối trên một số hệ thống, nhưng quyền truy cập vào thiết bị đầu cuối người dùng được cung cấp bởi "/ dev / tty". Sử dụng "wc" cho "foo", các ví dụ trên hoạt động tốt (trên linux, OSX, v.v.) như:

% echo 'Hi' | tee /dev/tty | wc Hi 1 1 3

Để thêm số đếm ở cuối danh sách các tệp phù hợp, tôi sử dụng một số thứ như:
% ls [A-J]* | tee /dev/tty | wc -l

Để tránh phải nhớ tất cả những điều này, tôi xác định bí danh:
% alias t tee /dev/tty
% alias wcl wc -l

để tôi có thể nói một cách đơn giản:
% ls [A-J]* | t | wcl


POSTSCRIPT: Đối với tập trẻ hơn, người có thể phát âm theo cách phát âm của nó là "giật gân", tôi có thể thêm rằng "tty" đã từng là chữ viết tắt phổ biến cho thiết bị đầu cuối "teletype", sử dụng một cuộn giấy màu vàng và có các phím tròn thường bị mắc kẹt.


17

Thử:

$ echo 'ee' | tee /dev/stderr | foo

Nếu sử dụng stderr là một lựa chọn, tất nhiên.


8

trước tiên, bạn cần tìm ra thiết bị đầu cuối được liên kết với màn hình của bạn (hoặc bất kỳ màn hình nào bạn muốn đầu ra hiển thị trên đó):

tty

sau đó bạn có thể phát đầu ra tới thiết bị đầu cuối đó và chuyển bản sao khác qua chương trình foo của bạn:

echo ee | tee /dev/pty/2 | foo

1
oneliner: t = $ (tty) echo ee | tee $ t | foo | quán bar
Jack Tang

5
@JackTang Điều đó thực sự tốt hơn nhưng tvô dụng. Bạn có thể sử dụng echo ee | tee $(tty) | foonhưng nó vẫn có một lệnh vô dụng ( tty), với thực tế /dev/ttychỉ hoạt động.
jlliagre
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.