2011-01-12 19 views
9

Sự khác nhau giữa hai ví dụ này là gì?Sự khác nhau giữa việc ghi vào STDOUT và một tập tin được mở thành "/ dev/tty" là gì?

#!/usr/bin/perl 
use warnings; 
use 5.012; 
my $str = "\x{263a}"; 


open my $tty, '>:encoding(utf8)', '/dev/tty' or die $!; 
say $tty $str; 
close $tty; 

open $tty, '>:bytes', '/dev/tty' or die $!; 
say $tty $str; 
close $tty; 

# ------------------------------------------------------- 

binmode STDOUT, ':encoding(utf8)' or die $!; 
say $str; 

binmode STDOUT, ':bytes' or die $!; 
say $str; 
+2

Một trong số chúng ghi vào/dev/tty, một trong số chúng ghi vào STDOUT. Đó có phải là điều bạn muốn biết không? –

+0

@JB - nó không phải là một sự khác biệt tầm thường đối với những người không quen thuộc với Unix – DVK

+0

@DVK Bạn nói đúng. Tôi đã bị nhầm lẫn bởi định hướng Perl của câu hỏi khi ý chính của nó là Unix. Cảm ơn sự khai sáng! –

Trả lời

12

Sự khác biệt là bạn đang viết đến hai biệt và (từ Perl và điểm của chương trình của bạn) độc lập xử lý tập tin.

  • Người đầu tiên là một xử lý tập tin mở vào một tập tin "thiết bị" đặc biệt trên Unixy OS đó là "một từ đồng nghĩa với các thiết bị đầu cuối kiểm soát của một quá trình, nếu có" (trích dẫn từ this Linux document). Xin lưu ý rằng mặc dù nó thường được coi là "màn hình" nhưng không nhất thiết phải là (ví dụ: thiết bị đầu cuối đó có thể được liên kết với tệp thiết bị của cổng nối tiếp); và nó có thể không tồn tại hoặc không thể mở được.

  • Tệp thứ hai là tệp được xử lý được liên kết theo mặc định với bộ mô tả tệp # 1 cho quy trình.

Họ có thể dường như giống hệt nhau ở cái nhìn đầu tiên do thực tế rằng, trong một tình huống điển hình, một vỏ Unix sẽ theo mặc định liên kết tập tin của nó mô tả # 1 (và do đó một trong mỗi quá trình nó sẽ khởi động không có chuyển hướng) với /dev/tty.

Cả hai không có điểm chung từ quan điểm Perl, KHÁC so với thực tế là hai kết quả này thường được kết hợp theo mặc định do cách trình vỏ Unix hoạt động.

Hành vi chức năng của hai đoạn mã được trích dẫn thường SEEM giống hệt nhau do mặc định này, nhưng đó chỉ là "do tình cờ".

Trong số chênh lệch thực tế:

  • /dev/tty không nhất thiết phải tồn tại trên phi Unixy OS. Do đó, rất dễ sử dụng để sử dụng tty. Tương đương Windows là CON: IIRC.

  • STDOUT của một chương trình có thể được liên kết (được chuyển hướng lại) cho bất kỳ ai được gọi là chương trình. Có thể được liên kết với một tệp, có thể là một đường dẫn đến STDIN của một quy trình khác.


Bạn có thể kiểm tra xem STDOUT của bạn được kết nối với một tty bằng -t operator:

if (-t STDOUT) { say 'STDOUT is connected to a tty' } 

Như sang một bên khác, xin vui lòng lưu ý rằng bạn có thể chắc chắn rằng STDOUT bạn ghi vào /dev/tty bằng cách đóng một cách thủ công tệp STDOUT và mở lại nó để trỏ đến /dev/tty:

close STDOUT or die $!; 
open STDOUT '>:encoding(utf8)', '/dev/tty' or die $!; 
+2

Cũng lưu ý rằng có rất nhiều trường hợp không thể sử dụng '/ dev/tty' (vì không có thiết bị đầu cuối điều khiển) - một ví dụ phổ biến là một lệnh được gọi thông qua ssh như' ssh somehost somecommand' - ssh sẽ, bởi mặc định, treo lên STDIN, STDOUT và STDERR, nhưng không tạo ra một thiết bị đầu cuối thực tế. – bdonlan

+0

@bdolan - chính xác (do đó, ", nếu có" được thêm vào trong định nghĩa tôi trích dẫn). Hoặc, ví dụ đơn giản hơn, trên Windows :) – DVK

+0

@JB - cảm ơn chỉnh sửa '-t'! Cũng giống như một sang một bên, IIRC nó không thể phân biệt giữa '/ dev/tty' hoặc bất kỳ thiết bị đầu cuối khác. – DVK

4

Ngoài những gì DVK nói, bạn có thể thấy sự khác biệt đơn giản bằng cách nói

perl -le 'open $o, ">:encoding(utf8)", "/dev/tty"; print "STDOUT"; print $o "/dev/tty"' > /dev/null 

Các ghi vào STDOUT đi vào /dev/null, nhưng ghi vào $o đi vào màn hình.

+0

+1 Ví dụ điển hình về những gì DVK nói. – sebthebert

4

Chương trình được khởi chạy từ một trình tương tác thường ghi đầu ra tiêu chuẩn vào một thiết bị đầu cuối, sẽ hiển thị /dev/ttySTDOUT làm cùng một đích. Nhưng có một số trường hợp trong đó đầu ra là STDOUT có thể được ghi vào một số điểm đến khác.

STDOUT có thể được chuyển đến một file riêng biệt:

perl someprogram.pl > a/file 
perl someprogram.pl >> a/file 

STDOUT có thể được chuyển đến đầu vào của một chương trình khác

perl someprogram.pl | /usr/bin/mailx -s "Program Output" [email protected] 

Ngoài ra, chương trình có thể được phóng đi từ một vỏ không tương tác , giống như một công việc cron hoặc từ một số daemon khác đang chạy trên hệ thống của bạn. Môi trường cho các chương trình này sẽ không có quyền truy cập vào thiết bị /dev/ttySTDOUT trong các chương trình này sẽ được định tuyến ở một nơi khác (hoặc không nơi nào).

Các vấn đề liên quan