¿Cuál es la diferencia entre los backticks, el sistema y el ejecutivo de Perl?

237

¿Alguien puede ayudarme? En Perl, ¿cuál es la diferencia entre:

exec "command";

y

system("command");

y

print `command`;

¿Hay otras formas de ejecutar comandos de shell también?

rlbond
fuente
8
Casi un duplicado exacto de stackoverflow.com/questions/797127/… , excepto que este tiene exec y el otro tiene tuberías.
Michael Myers

Respuestas:

268

ejecutivo

ejecuta un comando y nunca regresa . Es como una returndeclaración en una función.

Si no se encuentra el comando, execdevuelve falso. Nunca devuelve verdadero, porque si se encuentra el comando, nunca regresa en absoluto. También hay ningún punto en la devolución STDOUT, STDERRo el estado de salida del comando. Puede encontrar documentación al respecto perlfunc, porque es una función.

sistema

ejecuta un comando y su script Perl continúa después de que el comando ha finalizado.

El valor de retorno es el estado de salida del comando. Puede encontrar documentación al respecto en perlfunc.

backticks

like systemejecuta un comando y su script perl continúa después de que el comando ha finalizado.

Al contrario que systemel valor de retorno es STDOUTdel comando. qx//es equivalente a backticks. Puede encontrar documentación al respecto perlop, porque a diferencia systemy execes un operador.


Otras maneras

Lo que falta en lo anterior es una forma de ejecutar un comando de forma asincrónica. Eso significa que su script perl y su comando se ejecutan simultáneamente. Esto se puede lograr con open. Le permite leer STDOUT/ STDERRescribir en STDINsu comando. Sin embargo, depende de la plataforma.

También hay varios módulos que pueden facilitar esta tarea. Hay IPC::Open2y IPC::Open3y IPC::Run, así como Win32::Process::Createsi estás en Windows.

Ludwig Weinzierl
fuente
1
Creo que te refieres a s / perlcunc / perlfunc / ... también la documentación de perlipc se profundiza en la apertura de tuberías.
ephemient
77
perlcunc, tal vez este será mi nuevo apodo ;-)
Ludwig Weinzierl
8
Para el registro, backticks y qx [] también pueblan $? (el valor de retorno del sistema operativo).
jjohn
167

En el uso general I system, open, IPC::Open2, o IPC::Open3dependiendo de lo que yo quiero hacer. El qx//operador, aunque simple, es demasiado restrictivo en su funcionalidad para ser muy útil fuera de los hacks rápidos. Me parece openmucho más útil.

system: ejecuta un comando y espera a que regrese

Úselo systemcuando desee ejecutar un comando, no le importe su salida y no quiera que el script Perl haga nada hasta que finalice el comando.

#doesn't spawn a shell, arguments are passed as they are
system("command", "arg1", "arg2", "arg3");

o

#spawns a shell, arguments are interpreted by the shell, use only if you
#want the shell to do globbing (e.g. *.txt) for you or you want to redirect
#output
system("command arg1 arg2 arg3");

qx//o `` : ejecuta un comando y captura su STDOUT

Úselo qx//cuando desee ejecutar un comando, capture lo que escribe en STDOUT y no quiera que el script Perl haga nada hasta que finalice el comando.

#arguments are always processed by the shell

#in list context it returns the output as a list of lines
my @lines = qx/command arg1 arg2 arg3/;

#in scalar context it returns the output as one string
my $output = qx/command arg1 arg2 arg3/;

exec: reemplaza el proceso actual con otro proceso.

Úselo execjunto con forkcuando desee ejecutar un comando, no le importe su salida y no quiera esperar a que regrese. systemes realmente justo

sub my_system {
    die "could not fork\n" unless defined(my $pid = fork);
    return waitpid $pid, 0 if $pid; #parent waits for child
    exec @_; #replace child with new process
}

También puede leer los manuales waitpidy perlipc.

open: ejecuta un proceso y crea una tubería a su STDIN o STDERR

Úselo opencuando desee escribir datos en el STDIN de un proceso o leer datos del STDOUT de un proceso (pero no ambos al mismo tiempo).

#read from a gzip file as if it were a normal file
open my $read_fh, "-|", "gzip", "-d", $filename
    or die "could not open $filename: $!";

#write to a gzip compressed file as if were a normal file
open my $write_fh, "|-", "gzip", $filename
    or die "could not open $filename: $!";

IPC :: Open2 : ejecuta un proceso y crea una tubería a STDIN y STDOUT

Úselo IPC::Open2cuando necesite leer y escribir en STDIN y STDOUT de un proceso.

use IPC::Open2;

open2 my $out, my $in, "/usr/bin/bc"
    or die "could not run bc";

print $in "5+6\n";

my $answer = <$out>;

IPC :: Open3 : ejecuta un proceso y crea una tubería a STDIN, STDOUT y STDERR

utilícelo IPC::Open3cuando necesite capturar los tres identificadores de archivo estándar del proceso. Escribiría un ejemplo, pero funciona principalmente de la misma manera que IPC :: Open2, pero con un orden ligeramente diferente a los argumentos y un tercer identificador de archivo.

Chas Owens
fuente
Respuesta muy informativa y actualizada. Gracias @ chas-owens
Jassi
IPC :: Open3 tiene un nivel demasiado bajo para la mayoría de los usos. IPC :: Run3 e IPC :: Run suelen ser mucho más apropiados.
ikegami
17

Permítanme citar primero los manuales:

perldoc exec () :

La función exec ejecuta un comando del sistema y nunca regresa ; use el sistema en lugar del exec si desea que regrese

sistema perldoc () :

Hace exactamente lo mismo que exec LIST, excepto que primero se realiza una bifurcación y el proceso padre espera a que se complete el proceso hijo.

A diferencia de exec y system , los backticks no le dan el valor de retorno sino el STDOUT recopilado.

perldoc `String` :

Una cadena que (posiblemente) se interpola y luego se ejecuta como un comando del sistema con / bin / sh o su equivalente. Se respetarán los comodines de Shell, las tuberías y las redirecciones. Se devuelve la salida estándar recopilada del comando ; El error estándar no se ve afectado.


Alternativas:

En escenarios más complejos, donde desea obtener STDOUT, STDERR o el código de retorno, puede usar módulos estándar bien conocidos como IPC :: Open2 e IPC :: Open3 .

Ejemplo:

use IPC::Open2;
my $pid = open2(\*CHLD_OUT, \*CHLD_IN, 'some', 'cmd', 'and', 'args');
waitpid( $pid, 0 );
my $child_exit_status = $? >> 8;

Finalmente, IPC :: Run from the CPAN también vale la pena mirar ...

Benedikt Waldvogel
fuente
3
Esta es una respuesta grosera. Debes tratar de ser útil sin la ira.
Shane C. Mason
1
Creo que solo estaba haciendo referencia al viejo RTFM: P
v3.
no fue grosero en realidad;) eliminó la palabra f sin embargo, para evitar cualquier malentendido ...
Benedikt Waldvogel
2
Ciertamente no lo interpreté como grosero. Brusque, tal vez, pero esta no es una pregunta muy inteligente que requiere una respuesta reflexiva.
ephemient
11

¿Cuál es la diferencia entre los backticks de Perl ( `) system, y exec?

exec -> exec "command"; ,
system -> system("command"); and 
backticks -> print `command`;

exec

execejecuta un comando y nunca reanuda el script de Perl. Es para un script como una returndeclaración es para una función.

Si no se encuentra el comando, execdevuelve falso. Nunca devuelve verdadero, porque si se encuentra el comando, nunca regresa en absoluto. También hay ningún punto en la devolución STDOUT, STDERRo el estado de salida del comando. Puede encontrar documentación al respecto en perlfunc , porque es una función.

P.ej:

#!/usr/bin/perl
print "Need to start exec command";
my $data2 = exec('ls');
print "Now END exec command";
print "Hello $data2\n\n";

En el código anterior, hay tres printdeclaraciones, pero al execabandonar el script, solo se ejecuta la primera declaración de impresión. Además, la execsalida del comando no se asigna a ninguna variable.

Aquí, solo obtienes el resultado de la primera printinstrucción y de ejecutar el lscomando en la salida estándar.

system

systemejecuta un comando y su script Perl se reanuda una vez que el comando ha finalizado. El valor de retorno es el estado de salida del comando. Puede encontrar documentación al respecto en perlfunc .

P.ej:

#!/usr/bin/perl
print "Need to start system command";
my $data2 = system('ls');
print "Now END system command";
print "Hello $data2\n\n";

En el código anterior, hay tres printdeclaraciones. A medida que se reanuda el script después del systemcomando, se ejecutan las tres declaraciones de impresión.

Además, system se asigna el resultado de la ejecución data2, pero el valor asignado es 0(el código de salida de ls).

Aquí, obtienes el resultado de la primera printinstrucción, luego la del lscomando, seguido de los resultados de las dos printdeclaraciones finales en la salida estándar.

backticks ( `)

Por ejemplo system, al encerrar un comando en backticks se ejecuta ese comando y su script Perl se reanuda una vez que el comando ha finalizado. En contraste con system, el valor de retorno es STDOUTdel comando. qx//es equivalente a backticks. Puede encontrar documentación al respecto en perlop , porque a diferencia del sistema y exec, es un operador.

P.ej:

#!/usr/bin/perl
print "Need to start backticks command";
my $data2 = `ls`;
print "Now END system command";
print "Hello $data2\n\n";

En el código anterior, hay tres printdeclaraciones y las tres se están ejecutando. La salida de lsno se va a estandarizar directamente, sino que se asigna a la variable data2y luego se imprime mediante la declaración de impresión final.

linuxtestside
fuente
La mejor explicación con el ejemplo. Muchas gracias.
Arslan Anwar
2

La diferencia entre 'exec' y 'system' es que exec reemplaza su programa actual con 'command' y NUNCA regresa a su programa. sistema, por otro lado, bifurca y ejecuta 'comando' y le devuelve el estado de salida de 'comando' cuando termina de ejecutarse. La marca de retroceso ejecuta 'comando' y luego devuelve una cadena que representa su salida estándar (lo que sea que se haya impreso en la pantalla)

También puede usar popen para ejecutar comandos de shell y creo que hay un módulo de shell: 'use shell' que le brinda acceso transparente a los comandos de shell típicos.

Espero que eso te lo aclare.

Shane C. Mason
fuente
¿Quizás te refieres a use Shell;( search.cpan.org/dist/Shell/Shell.pm )? No está ampliamente instalado, y tampoco es aplicable a la pregunta, creo ...
ephemient
1
La última parte de su pregunta fue "¿hay otras formas de ejecutar comandos de shell también?" Shell es otra forma de ejecutar comandos de shell.
Shane C. Mason
2
Los documentos expresan específicamente "Este paquete se incluye como un caso de ejemplo, ilustrando algunas características de Perl. No debe usarse para programas de producción. Aunque proporciona una interfaz simple para obtener la salida estándar de comandos arbitrarios, puede haber mejores formas de lograr lo que necesitas ".
Chas. Owens
2
Una vez más, respondió a su pregunta de '¿hay otras maneras'
Shane C. Mason
Las formas malas y no compatibles no deben darse sin advertencias de que son malas y no compatibles.
Chas. Owens