Trucos UNIX: ¿Como escoger dinámicamente el interprete de Perl?

Imaginese lo siguiente: Usted tiene que correr un script en Perl en varios servidores diferentes (Solaris, Linux) y la ruta de Perl es distinta en cada uno (/usr/bin, /usr/local/bin); Peor aún: no puede confiar en el contenido de $PATH ya que usted sabe que el binario de Perl en cierta ubicación (por ejemplo /opt/perl o /usr/local/perl) tiene cierta funcionalidad habilitada, como threads.
¿Como hacer? Lo primero que viene a la mente es hacer un wrapper y llamar al script desde un shell como Bash, pasandole los argumentos originales. De allí podemos detectar donde está el binario de Perl deseado para luego ejecutarlo así:
#!/bin/bashPero, ¿Hay una manera más eficiente de hacer esto?. Sip, podemos hacer que el script se vuelva a ejecutar a si mismo, pero utilizado a Perl y reemplazando el proceso que lo llamo (usando exec):
if [ -x /usr/local/bin/perl ]; then
/usr/local/bin/perl$@
elif [ -x /opt/bin/perl ]; then
/opt/bin/perl$@
else
printf "[ERROR]: Perl not found!"
exit 192
fi
1:#!/bin/bashLas claves aqui son:
2:
3:if [ -x /usr/bin/perl ]; then
4: exec /usr/bin/perl -x $0 $@
5:elif [ -x /usr/local/bin/perl ]; then
6: exec /usr/local/bin/perl -x $0 $@
7:else
8: printf "[ERROR]: Perl not found!"
9: exit 192
10:fi
11:
12:#!/usr/bin/perl
13:
14:use strict;
15:
16:printf "Hello %s\n", $ENV{USER};
17:
18:__END__
19:
20:=head1 NAME
21:
22:call_perl.plx - Shows how to call Perl from another scripting languaje, like bash
23:
24:=head1 DESCRIPTION
25:
26:The key here is to use exec in Bash and the '-x' flag with Perl
27:
28:=head1 SEE ALSO
29:
30:The manpage for Perl Run (man perlrun)
31:
32:=head1 AUTHOR
33:
34:Jose Vicente Nunez Zuleta (josevnz@sourceforge.net)
35:
36:=head1 BLOG
37:
38:KodeGeek - http://kodegeek.com
39:
40:=cut
- Llamar a Perl con 'exec' desde Bash. Eso reemplaza al proceso actual con el interprete de Perl
- Perl llama al codigo fuente usando -x. Esta bandera ignora cualquier basura hasta que se consiga el "magic cookie", en este caso "!#/usr/bin/perl".
Buscar en Technorati: perl



3 Comentarios:
... en Ruby el truco es idéntico
De hecho, fue copiado de Perl. Lo siguiente es del man page de ruby:
-x[directory]
Tells Ruby that the script is embedded in a message. Leading garbage will be discarded until the first that starts with ‘#!’’ and contains the string, ‘‘ruby’’.Any meaningful switches on that line will applied. The end of script must be specified with either EOF, "^D" ("control-D"), "^Z" ("control-Z"), or reserved word __END__. If the directory name is specified, Ruby will switch to that directory before executing script.
Saludos
La solucion tradicional a este tipo de problemas, donde no estas seguro de la ubicacion del script, es emplear 'env'.
La gran mayoria de los ambientes unix y similares tienen el comando /usr/bin/env, que ademas de permitirte alterar las variables de ambiente, acepta un comando (con parametros) a ser ejecutado con las variables modificadas.
Esto funciona incluso si no especificas variables. Y el comando es buscado en el "path".
Asi que en lugar de "#!/usr/bin/perl", o "#!/usr/local/bin/perl" o "#!/opt/perl/bin/perl", simplemente te aseguras que el directorio apropiado este en el path y usas "#!/usr/bin/env perl"
Sebastian,
Tiene razón en lo de usar env. Sin embargo en mi ejemplo yo mencionaba que si tu ya tenias un requierimiento especifico, como el usar Perl con threads u otro modulo entonces especificar la ruta se hace obligatorio, ya que quizas el PATH te va a a devolver primero a un Perl que no quieres. Al final se pueden combinar ambas soluciones (más soga para ahorcarse dijo alguien por allí).
Baquiano: Buen tip el de Ruby, no sabia que podia.
Publicar un comentario en la entrada
Enlaces a este articulo:
Crear un enlace
<< Regresar