В чем разница между записью в STDOUT и файловым дескриптором, открытым в "/ dev / tty"? - PullRequest
9 голосов
/ 12 января 2011

В чем различия между этими двумя примерами?

#!/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;

Ответы [ 3 ]

13 голосов
/ 12 января 2011

Разница в том, что вы пишете в два различных и (с точки зрения Perl и вашей программы) независимых дескриптора файла.

  • Первый - это дескриптор файла, открытый для специального файла «устройства» в ОС Unixy, который является «синонимом управляющего терминала процесса», , если есть »(цитата из этот документ Linux ). Обратите внимание, что хотя его обычно называют «экраном», это не обязательно (например, этот терминал может быть связан с файлом устройства последовательного порта); и он может не существовать или быть недоступным для открытия.

  • Второй файл - это обработанный файл, связанный по умолчанию с дескриптором файла # 1 для процесса.

Они могут казаться идентичными на первый взгляд из-за того факта, что в типичной ситуации оболочка Unix по умолчанию ассоциирует свой файловый дескриптор # 1 (и, таким образом, один из каждого запускаемого процесса без перенаправлений) с /dev/tty.

Эти два понятия не имеют ничего общего с точки зрения Perl , ДРУГОЕ, чем тот факт, что эти два обычно связаны по умолчанию из-за работы оболочек Unix.

Функциональное поведение двух цитируемых фрагментов кода часто выглядит идентично из-за этого значения по умолчанию, но это просто "случайно".

Среди практических отличий:

  • /dev/tty не обязательно существует в не-Unixy ОС. Поэтому использовать tty крайне непереносимо. Эквивалент Windows - CON: IIRC.

  • STDOUT программы может быть привязано (перенаправлено) к НИЧЕМ любому, кто вызвал программу. Может быть связан с файлом, может быть каналом к ​​STDIN другого процесса.


Вы можете проверить, подключен ли ваш STDOUT к tty, используя оператор -t :

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

Обратите внимание, что вы МОЖЕТЕ убедиться, что ваш STDOUT записывает в /dev/tty, явно закрыв файловый дескриптор STDOUT и снова открыв его, чтобы указать /dev/tty:

close STDOUT or die $!;
open STDOUT '>:encoding(utf8)', '/dev/tty' or die $!;
4 голосов
/ 12 января 2011

Программа, запускаемая из интерактивной оболочки, обычно записывает стандартный вывод в терминал, который отображает /dev/tty и STDOUT в качестве одного и того же пункта назначения.Но есть несколько обстоятельств, когда вывод в STDOUT может быть записан в другое место назначения.

STDOUT может быть направлено в отдельный файл:

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

STDOUT может бытьнаправляется на вход другой программы

perl someprogram.pl | /usr/bin/mailx -s "Program Output" foo@bar.com

Кроме того, программа может быть запущена из неинтерактивной оболочки, например, из задания cron, или из какого-либо другого демона, работающего в вашей системе.Среды для этих программ не будут иметь доступа к устройству /dev/tty, и STDOUT в этих программах будет маршрутизироваться где-то еще (или в никуда).

4 голосов
/ 12 января 2011

В дополнение к тому, что сказал ДВК, вы можете увидеть простую разницу, сказав

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

Запись в STDOUT идет в /dev/null, а запись в $o идет на экран.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...