2011-01-12 10 views
9

¿Cuáles son las diferencias entre estos dos ejemplos?¿Cuál es la diferencia entre escribir en STDOUT y un identificador de archivo abierto en "/ 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 de ellos escribe en/dev/tty, uno de ellos escribe en STDOUT. ¿Era eso lo que querías saber? –

+0

@JB - no es una distinción trivial para las personas que no están muy familiarizadas con Unix – DVK

+0

@DVK Tienes razón. Estaba confundido por la orientación Perl de la pregunta cuando la esencia era Unix. Gracias por la iluminación! –

Respuesta

12

La diferencia es que usted está escribiendo a dos distinta y (de Perl y el punto de vista de su programa) identificadores de archivos independientes.

  • El primero es un identificador de archivo abierto en un archivo especial "dispositivo" en la Unixy OS que es "un sinónimo de la terminal de control de un proceso, en su caso " (cita de this Linux document). Tenga en cuenta que si bien comúnmente se considera "pantalla", no tiene que ser así (por ejemplo, que la terminal podría estar vinculada al archivo de dispositivo del puerto serie en su lugar); y puede no existir o no ser operable.

  • El segundo es un archivo manejado asociado por defecto con el descriptor de archivo # 1 para el proceso.

Pueden parecen ser idénticos a primera vista, debido al hecho de que, en una situación típica, un shell de Unix de forma predeterminada asociar su archivo descriptor # 1 (y por lo tanto uno de cada proceso se pone en marcha sin redirecciones) con /dev/tty.

Los dos no tienen nada en común desde el punto de vista de Perl, A excepción del hecho de que esos dos comúnmente terminan asociados de forma predeterminada debido a la forma en que funcionan los shells de Unix.

El comportamiento funcional de las dos piezas de código citadas a menudo parecerá idéntico debido a este valor predeterminado, pero eso es simplemente "por accidente".

Entre diferencias prácticas:

  • /dev/tty no necesariamente existe en la no-Unixy sistemas operativos. Por lo tanto, es muy poco portátil para usar tty. El equivalente de Windows es CON: IIRC.

  • STDOUTSTDOUT de un programa puede ser asociado (redirigido) a CUALQUIER COSA por quien haya llamado al programa. Podría estar asociado a un archivo, podría ser un conducto para STDIN de otro proceso.


Puede comprobar si su STDOUT está conectado a un teléfono de texto utilizando el -t operator:

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

Como otro lado, tenga en cuenta que puede asegurarse de que su STDOUT escribe a /dev/tty cerrando explícitamente el identificador de archivo STDOUT y reabriéndolo para que apunte a /dev/tty:

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

Tenga en cuenta también que hay muchos casos en los que '/ dev/tty' no se puede usar en absoluto (ya que no hay un terminal de control) - un ejemplo común es un comando invocado por ssh como' ssh somehost somecommand' - ssh will, por predeterminado, conecta STDIN, STDOUT y STDERR, pero no crea un terminal real. – bdonlan

+0

@bdolan - corregir (por lo tanto, el ", si alguno" agregado en la definición que cité). O, para un ejemplo más simple, en Windows :) – DVK

+0

@JB - gracias por la edición '-t'! Solo como un lado, IIRC no puede distinguir entre '/ dev/tty' o cualquier otro dispositivo terminal. – DVK

4

Además de lo que dijo DVK, se puede ver la diferencia sencilla diciendo

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

La escritura a STDOUT va a /dev/null, pero la escritura a $o va a la pantalla.

+0

+1 Buen ejemplo de lo que dijo DVK. – sebthebert

4

Un programa iniciado desde un shell interactivo normalmente escribe salida estándar en un terminal, lo que representaría /dev/tty y STDOUT como el mismo destino. Pero hay varias circunstancias donde la salida a STDOUT se podría escribir en algún otro destino.

STDOUT puede encaminarse a un archivo separado:

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

STDOUT puede encaminarse a la entrada de otro programa

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

Además, el programa podría ser lanzado desde un shell no interactivo , como un trabajo cron o desde algún otro daemon ejecutándose en su sistema. Los entornos para estos programas no tendrán acceso a un dispositivo /dev/tty, y STDOUT en estos programas se enrutarán a otro lugar (o a ninguna parte).

Cuestiones relacionadas