2012-07-24 28 views
6

Estoy tratando de configurar tuberías de forma arbitraria desde Perl, de forma muy similar a como lo haría un shell.ejecutando "less" desde la tubería perl

Esto tiene el efecto deseado, es como "eco foo | sed s/oo/ar /":

#!/usr/bin/perl 
use strict; 

use IO::Handle; 

$| = 1; 

my ($first_prog, $second_prog) = ([qw(echo foo)], [qw(sed s/oo/ar/)]); 
#$second_prog = ["less"]; 

pipe(my $second_prog_input, my $first_prog_output) 
    or die "problem setting up pipe: $!\n"; 

if (fork) { 
    STDOUT->fdopen(fileno($first_prog_output), 'w') or die; 
    exec(@$first_prog) or die; 
} 
else { 
    STDIN->fdopen(fileno($second_prog_input), 'r') or die; 
    exec(@$second_prog) or 
     die "couldn't exec: $!: command was @$first_prog\n"; 
} 

Sin embargo, cuando hago el segundo argumento "menos", mi terminal parpadea, y yo no veo la salida en el buscapersonas Aparte del breve flash, no hay signos de que se esté ejecutando en absoluto.

Ahora algo que no entiendo en absoluto es que el siguiente no se comportan como "eco foo | menos":

pipe(my $first_prog_output, STDIN) or die "problem setting up pipe: $!\n"; 

my ($first_prog, $second_prog) = ([qw(echo foo)], ["less"]); 

open($first_prog_output, "-|", @$first_prog) or 
    die "$!: command was @$first_prog\n"; 

exec(@$second_prog) or 
    die "couldn't exec: $!: command was @$first_prog\n"; 

Pero no entiendo en absoluto lo que la llamada a la tubería() es obra. El primer argumento se supone que es un "lector", y el segundo es un "escritor". ¿Cómo es STDIN un "escritor"?

Estoy muy confundido por todo esto, y creo que puede haber algo fundamental acerca de la API subyacente de Unix que me falta o que he olvidado.

Respuesta

6

Se trata de un problema de tiempo interesante:

  • horquillas Shell, crea un grupo de procesos, establece el primer plano grupo de terminales a la misma, y ​​los ejecutivos de perl.
  • perl horquillas y ejecutivos less.
  • perl ejecutivos echo.
  • echo sale, shell cree que el trabajo está hecho y se establece como el grupo de proceso de primer plano de la terminal una vez más.
  • less intenta adquirir terminal. No está en el grupo de procesos de primer plano de la terminal. less falla.

La solución más simple: el cambio fork a !fork (o equivalentemente, cambiar su if y else bloques). De esta manera, la etapa final de la tubería define la vida útil del trabajo. (Si observa atentamente, el shell bifurca y los procesos de los ejecutivos en este mismo orden cuando ejecuta una tubería, también.)