Pregunta

He aquí un escenario.Usted tiene una gran cantidad de secuencias de comandos heredados, todos con una biblioteca común.Dijo secuencias de comandos de uso 'imprimir' para la declaración de la salida de diagnóstico.No se admitirán cambios en las secuencias de comandos - se extienden a lo largo y ancho, tiene sus aprobaciones, y desde hace mucho han dejado el fructíferos valles de supervisión y control.

Ahora, una nueva necesidad que se ha llegado:el registro debe ahora ser añadido a la biblioteca.Esto debe hacerse de forma automática y transparente, sin que los usuarios de la biblioteca estándar de la necesidad de cambiar sus guiones.Biblioteca común de los métodos pueden simplemente tener el registro de llamadas agregado;esa es la parte fácil.La parte más difícil radica en el hecho de que la salida de diagnóstico a partir de estas secuencias se muestran siempre el uso de la 'impresión' de la declaración.Esta salida de diagnóstico deben ser almacenados, pero igual de importante, procesados.

Como ejemplo de este proceso, la biblioteca sólo debe registrar las líneas impresas que contienen las palabras 'advertencia', 'error', 'aviso', o 'atención'.El de abajo Extremadamente Trivial e ideó el Código de Ejemplo (tm) de grabar algunos de dichos salida:

sub CheckPrintOutput
{
    my @output = @_; # args passed to print eventually find their way here.
    foreach my $value (@output) {
         Log->log($value) if $value =~ /warning|error|notice|attention/i;
    }
}

(Me gustaría evitar problemas como que 'lo que en realidad deberían estar registrado', 'imprimir no deben ser utilizados para el diagnóstico', 'perl chupa', o 'este ejemplo tiene los defectos de x, y y z'...esto se simplifica en gran medida por razones de brevedad y claridad.)

El problema básico se reduce a la captura y procesamiento de datos que se pasan a la impresión (o cualquier perl builtin, a lo largo de esas líneas de razonamiento).Es posible?Hay alguna forma de hacerlo de forma limpia?Hay módulos de registro que tiene ganchos para dejar de hacerlo?O es algo que debe ser evitado como la peste, y me dan hasta en la captura y procesamiento de la salida impresa?

Adicionales:Esto se debe ejecutar de la cruz-plataforma de windows y *nix por igual.El proceso de la ejecución de los scripts deben seguir siendo los mismos, así como la salida de la secuencia de comandos.

Adicionales adicionales:Una interesante propuesta que se ha hecho en los comentarios de codelogic la respuesta:

Puede subclase http://perldoc.perl.org/IO/Handle.html y crear su propio identificador de archivo que va a hacer el registro de trabajo.– Kamil Kisiel

Esto podría hacerlo, con dos salvedades:

1) yo necesitaría una manera de exportar esta funcionalidad para cualquier persona que utiliza la biblioteca común.Tendría que aplicar automáticamente a STDOUT y probablemente STDERR demasiado.

2) IO::Handle la documentación dice que no se puede crear subclases de él, y mis intentos han sido infructuosos.Hay algo en especial que sea necesario hacer sublclassing IO::Handle de trabajo?El estándar de uso 'base 'IO::Handle" y, a continuación, reemplazar el nuevo/los métodos de impresión parecen no hacer nada.

Última edición:Se ve como IO::Handle es un callejón sin salida, pero el Empate::Mango puede hacerlo.Gracias por todas las sugerencias;son todos realmente buena.Voy a darle el Empate::Identificador de la ruta de un intento.Si causa problemas voy a estar de vuelta!

Addendum:Tenga en cuenta que después de trabajar con esto un poco, he encontrado que Tie::Mango de trabajo, si no hacer nada complicado.Si usted usa alguna de las características de IO::Handle con su atado STDOUT o STDERR, que es básicamente un crapshoot de ponerlos en funcionamiento de forma fiable, no podía encontrar una manera de conseguir la autoflush método de IO::Handle a trabajar en mi atado de manejar.Si me habilitado autoflush antes de que me até el mango que iba a funcionar.Si que funciona para usted, el Empate::Identificador de la ruta puede ser aceptable.

¿Fue útil?

Solución

Hay un número de construido-ins que usted puede anular (ver perlsub).Sin embargo, print es uno de los complementos que no funciona de esta manera.Las dificultades de interés print se detallan en este perlmonk del hilo.

Sin embargo, usted puede

  1. Crear un paquete
  2. Ate un mango
  3. Seleccione este identificador.

Ahora, un par de personas que han dado el marco básico, pero funciona un poco como esto:

package IO::Override;
use base qw<Tie::Handle>;
use Symbol qw<geniosym>;

sub TIEHANDLE { return bless geniosym, __PACKAGE__ }

sub PRINT { 
    shift;
    # You can do pretty much anything you want here. 
    # And it's printing to what was STDOUT at the start.
    # 
    print $OLD_STDOUT join( '', 'NOTICE: ', @_ );
}

tie *PRINTOUT, 'IO::Override';
our $OLD_STDOUT = select( *PRINTOUT );

Puede reemplazar printf de la misma manera:

sub PRINTF { 
    shift;
    # You can do pretty much anything you want here. 
    # And it's printing to what was STDOUT at the start.
    # 
    my $format = shift;
    print $OLD_STDOUT join( '', 'NOTICE: ', sprintf( $format, @_ ));
}

Ver Empate::Mango todo lo que puede invalidar de STDOUT del comportamiento.

Otros consejos

Usted puede utilizar Perl seleccione para redirigir la salida estándar (STDOUT).

open my $fh, ">log.txt";
print "test1\n";
my $current_fh = select $fh;
print "test2\n";
select $current_fh;
print "test3\n";

El identificador del archivo puede ser cualquier cosa, incluso un tubo a otro proceso que después de los procesos de sus mensajes de registro.

PerlIO::t en el PerlIO::Util modulo parece que le permite " t " el resultado de un identificador de archivo a múltiples destinos (por ejemplo,registro de procesador y STDOUT).

Un montón de opciones.El uso de select() para cambiar el filehandle que la impresión por defecto.O lazo STDOUT.O volver a ella.O aplicar un IO de la capa a la misma.

Esta no es la respuesta a su problema, pero usted debería ser capaz de adoptar la lógica para su propio uso.Si no, tal vez alguien le resultará útil.

La captura de malformaciones de los encabezados antes de que sucedan...

package PsychicSTDOUT;
use strict;

my $c = 0;
my $malformed_header = 0;
open(TRUE_STDOUT, '>', '/dev/stdout');
tie *STDOUT, __PACKAGE__, (*STDOUT);

sub TIEHANDLE {
    my $class = shift;
    my $handles = [@_];
    bless $handles, $class;
    return $handles;
}

sub PRINT {
    my $class = shift;
    if (!$c++ && @_[0] !~ /^content-type/i) {
        my (undef, $file, $line) = caller;
        print STDERR "Missing content-type in $file at line $line!!\n";
        $malformed_header = 1;
    }
    return 0 if ($malformed_header);
    return print TRUE_STDOUT @_;
}
1;

uso:

use PsychicSTDOUT;
print "content-type: text/html\n\n"; #try commenting out this line
print "<html>\n";
print "</html>\n";

Se puede ejecutar la secuencia de comandos de un contenedor de secuencia de comandos que captura el guión original de la salida estándar (stdout) y escribe el resultado en alguna parte sensible.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top