Publicado 2019-10-25.
Palabras clave: perl debian
Durante el desarrollo, test y deploy de aplicaciones es conveniente poder replicar el mismo entorno en los diferentes pc's y servidores con los que se trabaje. Además, es doblemente conveniente el poder realizar la configuración del entorno de forma offline, ya que esto disminuye el tiempo utilizado en descarga de archivos y también se mitiga el riesgo de no poder crear el entorno en caso de que sea imposible descargar alguna dependencia por falta de disponibilidad de algún servidor *.
En el caso de Perl, las herramientas que se utilizarán para replicar un entorno serán las siguientes:
perlbrew: permite gestionar entornos y descargar distintas utilidades.
Entre las ventajas se encuentran:
Autoinstalarse desde un archivo descargado previamente utilizando el
comando self-install
.
Instalar (compilar) versiones de Perl a partir de tarballs descargados
previamente con el comando install
.
Nota: en Debian se necesita tener instalado en el sistema el
paquete build-essentials
para poder compilar perl.
Nota: se necesita tener instalado patchperl, el cual parchea versiones viejas de perl para poder compilarlas en sistemas operativos nuevos.
Nota: hay versiones de perlbrew que no permiten instalar Perl desde un tarball de forma offline. La versión 0.87 que se utilizará no tiene dicho problema.
Crear librerías las cuales permiten tener más de un conjunto distinto de módulos instalados para una misma versión de perl.
Por otro lado, como desventajas se tienen:
install-patchperl
. Como alternativa a dicho
comando se puede descargar manualmente el archivo, modificarlo, copiarlo
al directorio destino y darle permisos de ejecución siguiendo los pasos
indicados en el código fuente del
comando install-patchperl
. Los pasos quedarían como sigue:
wget -q -O patchperl 'https://raw.githubusercontent.com/gugod/patchperl-packing/master/patchperl'
cat patchperl \
| sed '1 s,#!.*,#!/usr/bin/perl,' \
> $PERLBREW_ROOT/bin/patchperl
chmod +x $PERLBREW_ROOT/bin/patchperl
install-cpanm
. Igual que en el caso de patchperl
,
inspeccionando el código fuente del
comando install-cpanm
vemos que se puede instalar el programa cpanm
de la siguiente forma:
wget -q -O cpanm 'https://raw.githubusercontent.com/miyagawa/cpanminus/master/cpanm'
cp cpanm $PERLBREW_ROOT/bin/
chmod +x $PERLBREW_ROOT/bin/cpanm
cpanminus: permite instalar módulos de Perl desde CPAN
(Comprehensive Perl Archive Network).
La principal ventaja que utilizaremos del comando cpanm
es que permite
definir un directorio caché donde almacenar y donde buscar módulos para
instalar.
Lamentablemente no hay forma de especificar las versiones de las
dependencias entre módulos como hacer Carton.
Se utilizará únicamente para instalar Carton.
Carton: gestor de dependencias de módulos Perl, será la herramienta utilizada a la hora de instalar los distintos módulos ya que registra las versiones de todos los módulos instalados en el entorno.
Los dos comandos que nos interesarán particularmente serán:
bundle
: permite almacenar los tarball de los módulos especificados en
el archivo cpanfile.snapshot
en el directorio vendor/cache
.
install --cached
(en DEPLOYMENT MODE): instala las versiones de los
módulos especificados en el archivo cpanfile.snapshot
utilizando los
tarball del directorio vendor/cache
sin acceder a los mirror de
CPAN.
Nota: en la documentación de Carton
se
indica que es posible almacenar los modulos que utiliza un proyecto de
forma tal que puedan ser instalados directamente por cpanm
(evitando
tener que instalar Carton
). No se utilizará dicha opción.
Se comenzara describiendo como crear un entorno y luego como replicarlo de forma
offline, utilizando para ello el contenido del directorio vendor
, el cual
podrá copiarse entre los equipos en los que se desee replicar el entorno.
Como aplicación de ejemplo se utilizará una aplicación realizada con Dancer2 a la que llamaremos dancer2-demo, más exactamente la que aparece en la página web como ejemplo, que será ejecutada por la versión 5.28.2 de perl y que constará de los siguientes archivos:
app.pl
: aplicación de ejemplo:
#!/usr/bin/env perl
use Dancer2;
get '/' => sub {
"Hello World!"
};
dance;
cpanfile
: dependencias de la aplicación a instalar utilizando Carton:
requires "Dancer2", "0.208001";
cpanfile.snapshot
: archivo generado por Carton al momento de instalar
las dependencias de la aplicación. Se debe guardar ya que contiene los
módulos que fueron instalados junto a sus versiones.
vendor
: directorio en el que se almacenarán las dependencias de la
aplicación para realizar un deploy en forma offline que será creado
durante la etapa de creación del entorno. Se recomienda excluir del
repositorio y manejar por separado.
El motivo de la aplicación de ejemplo es tener un ejemplo concreto para realizar
la creación y replicación de un entorno. Se elijió una aplicación hecha en
Dancer2 ya que tiene un número interesante de dependencias, la
implementación es bastante corta y puede probarse fácilmente utilizando wget
o
curl
desde linea de comandos.
A continuación se listarán los pasos seguidos para crear un entorno con la versión 5.28.2 de perl.
La estructura de directorios será la siguiente:
$PERLBREW_ROOT: archivos relacionados a perlbrew, es donde se instalan las
distintas versiones de perl y sus dependencias
$WORKDIR: directorio de la aplicación en desarrollo
+- vendor: directorio donde se almacenarán los archivos de forma offline
+- perlbrew: archivos relacionados a la instalación de perlbrew
+- cpanm: archivos utilizados por cpanm para descargar Carton
+- cache: archivos de módulos guardados por `carton bundle`
Establecer variables de entorno. Se utilizará la variable de entorno
PERLBREW_ROOT
para indicar donde se instalará la versión de perl a
utilizar.
Por defecto su valor es $HOME/perl5/perlbrew
.
Para evitar conflictos en el caso de que perlbrew
ya se encuentre instalado en el sistema se agrega al principio del
PATH
la ruta al programa donde se instalar perlbrew
.
Por último, la variable WORKDIR
será utilizada para indicar el directorio
de trabajo donde se encuentra la aplicación que contiene el directorio
vendor
que es donde se
almacenarán los archivos para recrear el entorno de manera offline:
export PERLBREW_ROOT=${PERLBREW_ROOT:-$HOME/perl5/perlbrew}
export PATH="$PERLBREW_ROOT/bin:$PATH"
export WORKDIR=$HOME/dancer2-demo
Creación de directorios de cache. Estos se utilizarán para almacenar los fuentes de los programas y librerías que luego sea necesario instalar para replicar el entorno. Se utilizará la siguiente estructura de directorios:
mkdir -p $WORKDIR/vendor/{perlbrew,cpanm,cache} || :
Descarga e instalación de perlbrew:
wget -P $WORKDIR/vendor/perlbrew https://raw.githubusercontent.com/gugod/App-perlbrew/release-0.87/perlbrew
perl $WORKDIR/vendor/perlbrew/perlbrew self-install
Nota: aquí no hay que olvidar agregar la linea
source $PERLBREW_ROOT/etc/bashrc
en el archivo ~/.profile
como indica la
salida del comando self-install
. Para ya habilitar el shell que se está
utilizando ejecutar en la consola source $PERLBREW_ROOT/etc/bashrc
.
Descarga y copia en el caché de una versión particular de perl. Como
versión a instalar se utiliza alguna de las devueltas por el comando
perlbrew available
el cual lista las versiones disponibles de perl.
perlbrew download perl-5.28.2
cp $PERLBREW_ROOT/dists/perl-5.28.2.tar.* $WORKDIR/vendor/perlbrew/
Nota: se utiliza globbing ya que las versiones de perl están comprimidas en más de un formato (.tar.gz/.tar.xz; ver http://www.cpan.org/authors/id/S/SH/SHAY/).
Instalar patchperl
. Como se indicó previamente en las contras de usar
perlbrew, ya se indicó que no es conveniente utilizar el comando
install-patchperl
. En su lugar se instalará manualmente:
wget -q -P $WORKDIR/vendor/perlbrew 'https://raw.githubusercontent.com/gugod/patchperl-packing/a9fc33a47253bca890c68905fcb79ad0305c5c5e/patchperl'
cat $WORKDIR/vendor/perlbrew/patchperl \
| sed '1 s,#!.*,#!/usr/bin/perl,' > $PERLBREW_ROOT/bin/patchperl
chmod +x $PERLBREW_ROOT/bin/patchperl
Nota: aquí se supone que existe un interprete de perl instalado en el
sistema en el directorio /usr/bin/perl
. Si la ruta fuera otra se deben
modificar los comandos anteriores.
Nota: ya que patchperl
no tiene releases o tags, se utilizará un
commit específico.
Instalar versión de perl. Ahora que fué instalado patchperl
podemos
instalar una versión específica de perl:
perlbrew install $WORKDIR/vendor/perlbrew/perl-5.28.2.tar.*
Nota: como está reportado en el issue 658, hay
versiones de perlbrew
en los cuales no funciona el instalar perl usando la
ruta del tarball. Como ejemplo, en la versión 0.86 el comando anterior
falla y en la versión 0.87 funciona.
Nota: para una compilación rápida (sin realizar tests) puede utilizarse
el flag --notest
Crear lib y establecerla por defecto. Esto permite tener más de un conjunto distinto de librerías para una misma versión de perl.
perlbrew lib create perl-5.28.2@dancer2-demo
perlbrew use perl-5.28.2@dancer2-demo
Nota: esto es útil para el caso de estar trabajando en distintas aplicaciones que posean distintas dependencias.
Instalar y configurar cpanm. Como se mencionó anteriormente en la introducción, lo haremos para poder instalar Carton.
Al igual que en el caso del comando install-patchperl
, el comando
install-cpanm
solo funciona con acceso a internet, por lo cual se
ejecutará un comando equivalente pero esta vez utilizando un número de
release en lugar de un commit, ya que cpanm versiona sus releases:
wget -q -P $WORKDIR/vendor/perlbrew 'https://raw.githubusercontent.com/miyagawa/cpanminus/1.7044/cpanm'
cp $WORKDIR/vendor/perlbrew/cpanm $PERLBREW_ROOT/bin
chmod +x $PERLBREW_ROOT/bin/cpanm
Luego hay que establecer la variable de entorno PERL_CPANM_OPT
para
indicarle a cpanm
que guarde en un caché los módulos descargados y que
al momento de instalar un módulo primero lo busque en el caché y luego en
http://www.cpan.org:
export PERL_CPANM_OPT="--cascade-search --save-dists=$WORKDIR/vendor/cpanm --mirror=file://$WORKDIR/vendor/cpanm --mirror=http://www.cpan.org"
Instalar Carton
:
cpanm install Carton
Ya que en la aplicación de ejemplo se tiene un archivo de nombre cpanfile con la lista de módulos a instalar, se instalarán estos utilizando Carton:
carton install
Nota: el comando anterior crea el archivo cpanfile.snapshot
el cual
contiene la lista de todos los módulos instalados junto a su versión.
Para probar que todo fué instalado correctamente se ejecutará la aplicación de ejemplo:
a. carton exec ./app.pl
b. perl -Ilocal/lib/perl5 app.pl
Por último se utiliza el comando bundle
para obtener todas las
dependencias instaladas por carton
en el directorio vendor/cache
:
carton bundle
En este punto ya se puede almacenar el contenido del directorio vendor
e ir
a la siguiente etapa: replicar el entorno.
A continuación se listarán los pasos seguidos para replicar de forma offline
el entorno creado en el punto anterior utilizando los archivos del directorio
vendor
.
Establecer variables de entorno. Al igual que en el paso anterior se establecerán las variables de entorno:
export PERLBREW_ROOT=${PERLBREW_ROOT:-$HOME/perl5/perlbrew}
export PATH="$PERLBREW_ROOT/bin:$PATH"
export WORKDIR=$(pwd)
Instalación y activación de perlbrew:
perl $WORKDIR/vendor/perlbrew/perlbrew self-install
Como se hizo en el punto 3. de la instalación, se debe agregar en el archivo
~/.profile
la linea source $PERLBREW_ROOT/etc/bashrc
.
grep -q $PERLBREW_ROOT/etc/bashrc ~/.profile || cat >> ~/.profile <<END
if [ -e ${PERLBREW_ROOT}/etc/bashrc ]; then
source ${PERLBREW_ROOT}/etc/bashrc
fi
END
Como se hizo anteriormente, se instalará la versión de patchperl
previamente descargada:
cat $WORKDIR/vendor/perlbrew/patchperl \
| sed '1 s,#!.*,#!/usr/bin/perl,' > $PERLBREW_ROOT/bin/patchperl
chmod +x $PERLBREW_ROOT/bin/patchperl
Instalar versión específica de perl. Para ello se utiliza el tarball
previamente descargado que se encuentra en vendor/perlbrew
:
perlbrew install $WORKDIR/vendor/perlbrew/perl-5.28.2.tar.*
Crear lib y establecerla por defecto:
perlbrew lib create perl-5.28.2@dancer2-demo
perlbrew use perl-5.28.2@dancer2-demo
Instalar y configurar cpanm. Igual a como se hizo con
patchperl
, se instala la versión descargada previamente:
cp $WORKDIR/vendor/perlbrew/cpanm $PERLBREW_ROOT/bin
chmod +x $PERLBREW_ROOT/bin/cpanm
Se configurará cpanm
de forma tal de utilizar solamente el caché
previamente creado en vendor/cpanm
:
export PERL_CPANM_OPT="--mirror=file://$WORKDIR/vendor/cpanm"
Instalación de Carton:
cpanm install Carton
Instalación de dependencias en caché utilizando Carton:
carton install --cached
Prueba de la aplicación para determinar que el entorno fué correctamente replicado:
carton exec ./app.pl
Scripts para replicar el entorno
Hay pasos durante la replicación del entorno que lanzan un subshell, por
ejemplo perlbrew use
. Sería necesario para escribir el script ver como
modificar el entorno sin lanzar el subshell.
Evaluación de plenv en lugar de perlbrew
Entre las alternativas a perlbrew se encuentra plenv. Vale la pena evaluar las ventajas y desventajas de utilizar plenv.
Uso de cpanm en lugar de carton en producción
En la documentación de carton, una alternativa a carton install --cached
es:
cpanm -L local --from "$PWD/vendor/cache" --installdeps --notest --quiet .
Esto último puede ser útil en producción para evitar tener que instalar carton, ya que no sería necesario. En los equipos de desarrollo no ayudaría, ya que es posible que se quiera agregar un nuevo módulo y se necesitaría carton para instalar el módulo y las dependencias.