ejecutar - ¿Cómo puede el sistema de Perl() imprimir el comando que está ejecutando?
ejecutar perl en linux (6)
En Perl, puede ejecutar comandos del sistema usando system () o `` (barras de respuesta). Incluso puede capturar la salida del comando en una variable. Sin embargo, esto oculta la ejecución del programa en segundo plano para que la persona que ejecuta el script no pueda verlo.
Normalmente esto es útil, pero a veces quiero ver lo que sucede detrás de escena. ¿Cómo se hace para que los comandos ejecutados se impriman en el terminal y la salida de esos programas se imprima en el terminal? Este sería el equivalente .bat
de "@echo on".
Aquí hay una ejecución actualizada que imprimirá los resultados y los devolverá:
sub execute {
my $cmd = shift;
print "$cmd/n";
my $ret = `$cmd`;
print $ret;
return $ret;
}
No conozco ninguna forma predeterminada de hacerlo, pero puede definir una subrutina para que lo haga por usted:
sub execute {
my $cmd = shift;
print "$cmd/n";
system($cmd);
}
my $cmd = $ARGV[0];
execute($cmd);
Y luego verlo en acción:
pbook:~/foo rudd$ perl foo.pl ls
ls
file1 file2 foo.pl
Otra técnica para combinar con los otros mencionados en las respuestas es usar el comando tee
. Por ejemplo:
open(F, "ls | tee /dev/tty |");
while (<F>) {
print length($_), "/n";
}
close(F);
Esto imprimirá los archivos en el directorio actual (como consecuencia de tee /dev/tty
) y también imprimirá la longitud de cada lectura de nombre de archivo.
Use abierto en su lugar. Entonces puedes capturar la salida del comando.
open(LS,"|ls");
print LS;
Hmm, es interesante cómo diferentes personas responden de diferentes maneras. Me parece que mk y Daniel Fone lo interpretaron como queriendo ver / manipular el stdout del comando (ninguna de sus soluciones captura stderr fwiw). Creo que Rudd se acercó. Una vuelta de tuerca que podrías hacer en la respuesta de Rudd es sobreescribir el comando incorporado en el sistema () con tu propia versión para que no tengas que volver a escribir el código existente para usar su comando execute ().
usando su sub execute () desde la publicación de Rudd, podrías tener algo como esto en la parte superior de tu código:
if ($DEBUG) {
*{"CORE::GLOBAL::system"} = /&{"main::execute"};
}
Creo que funcionará, pero tengo que admitir que esto es vudú y ha pasado un tiempo desde que escribí este código. Aquí está el código que escribí hace años para interceptar las llamadas al sistema a nivel local (espacio de nombres de llamadas) o global en el momento de carga del módulo:
# importing into either the calling or global namespace _must_ be
# done from import(). Doing it elsewhere will not have desired results.
delete($opts{handle_system});
if ($do_system) {
if ($do_system eq ''local'') {
*{"$callpkg/::system"} = /&{"$_package/::system"};
} else {
*{"CORE::GLOBAL::system"} = /&{"$_package/::system"};
}
}
Según tengo entendido, system () imprimirá el resultado del comando, pero no lo asignará. P.ej.
[daniel@tux /]$ perl -e ''$ls = system("ls"); print "Result: $ls/n"''
bin dev home lost+found misc net proc sbin srv System tools var
boot etc lib media mnt opt root selinux sys tmp usr
Result: 0
Backticks capturará la salida del comando y no lo imprimirá:
[daniel@tux /]$ perl -e ''$ls = `ls`; print "Result: $ls/n"''
Result: bin
boot
dev
etc
home
lib
etc ...
Actualización: si desea imprimir el nombre del comando siendo system () ''d también, creo que el enfoque de Rudd es bueno. Repetido aquí para la consolidación:
sub execute {
my $cmd = shift;
print "$cmd/n";
system($cmd);
}
my $cmd = $ARGV[0];
execute($cmd);