2011-01-12 8 views
9

Quali sono le differenze tra questi due esempi?Qual è la differenza tra la scrittura in STDOUT e un filehandle aperto a "/ dev/tty"?

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

Uno di questi scrive in/dev/tty, uno di questi viene scritto in STDOUT. Era quello che volevi sapere? –

+0

@ JB - non è una distinzione banale per le persone che non conoscono molto con Unix – DVK

+0

@DVK Hai ragione. Ero confuso dall'orientamento Perl della domanda quando l'essenza di esso era Unix. Grazie per l'illuminazione! –

risposta

12

La differenza è che si sta scrivendo a due distinti e (da Perl e di punto di vista del programma) handle di file indipendenti.

  • Il primo è un handle di file aperto ad uno speciale file "periferica" ​​a Unixy sistema operativo che è "sinonimo di terminale di controllo di un processo, eventuali" (citazione da this Linux document). Si noti che sebbene sia comunemente considerato come "schermo", non deve essere (ad esempio, quel terminale potrebbe essere collegato al file di dispositivo di una porta seriale); e potrebbe non esistere o non essere apribile.

  • Il secondo è un file gestito per impostazione predefinita con descrittore di file n. 1 per il processo.

Possono sembrano essere identici a prima vista a causa del fatto che, in una situazione tipica, una shell Unix per default associare il suo descrittore di file # 1 (e quindi uno di ogni processo si lancia senza redirect) con /dev/tty.

I due non hanno nulla in comune dal punto di vista Perl, A parte il fatto che questi due generalmente finiscono associati per impostazione predefinita a causa del modo in cui funzionano le shell Unix.

Il comportamento funzionale dei due pezzi citati di codice spesso SEMBRA identico a causa di questo valore predefinito, ma è solo "per caso".

Tra differenze pratiche:

  • /dev/tty non esiste necessariamente non Unixy sistemi operativi. Pertanto è altamente non portatile utilizzare tty. L'equivalente di Windows è CON: IIRC.

  • STDOUT di un programma può essere associato (reindirizzato) a QUALSIASI COSA da chiunque abbia chiamato il programma. Potrebbe essere associato a un file, potrebbe essere una pipe per STDIN di un altro processo.


è possibile controllare se il vostro STDOUT è collegato a un tty utilizzando la -t operator:

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

Come un altro a parte, si prega di notare che è possibile fare in modo che il vostro STDOUT scrive a /dev/tty chiudendo esplicitamente il filehandle STDOUT e riaprendolo in modo che punti a /dev/tty:

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

Si noti inoltre che ci sono molti casi in cui '/ dev/tty' non può essere usato affatto (poiché non esiste un terminale di controllo) - un esempio comune è un comando invocato tramite ssh come' ssh somehost somecommand' - ssh will, by di default, aggancia STDIN, STDOUT e STDERR, ma non crea un vero terminale. – bdonlan

+0

@bdolan - corretto (quindi il ", se presente" aggiunto nella definizione che ho citato). Oppure, per un esempio più semplice, su Windows :) – DVK

+0

@JB - grazie per '-t' edit! Come per inciso, IIRC non è in grado di distinguere tra '/ dev/tty' o qualsiasi altro dispositivo terminale. – DVK

4

In aggiunta a quanto detto DVK, si può vedere la semplice differenza dicendo

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

La scrittura a STDOUT va a /dev/null, ma la scrittura per $o va alla schermata.

+0

+1 Bel esempio di cosa ha detto DVK. – sebthebert

4

Un programma lanciato da una shell interattiva normalmente scrive output standard su un terminale, il che renderebbe /dev/tty e STDOUT come la stessa destinazione. Ma ci sono diverse circostanze in cui l'output a STDOUT potrebbe essere scritto in un'altra destinazione.

STDOUT possono essere indirizzati in un file separato:

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

STDOUT possono essere indirizzati con l'ingresso di un altro programma

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

Inoltre, il programma potrebbe essere lanciato da una shell non interattiva , come un cron job o da qualche altro daemon in esecuzione sul tuo sistema. Gli ambienti per questi programmi non avranno accesso a un dispositivo /dev/tty e STDOUT in questi programmi saranno indirizzati da qualche altra parte (o da nessuna parte).