Volver al blog

TIPS - Repositorios personalizados (myrepo)

linux-penguin-logo

En este artículo mostraré una forma alternativa de preparar un repositorio personalizado para Debian y derivadas que contenga exclusivamente aquellos paquetes que nos interesan (con sus dependencias), lo cual puede ser útil por ejemplo para copiarlos en una memoria USB desde un equipo con acceso pleno a un repositorio con el propósito de utilizarlos en otro equipo que use el mismo sistema operativo, sin tener que copiar obligatoriamente el repositorio completo.

En este caso, no utilizaremos las herramientas tradicionales como apt-mirror, reprepo etc; sino un sencillo script con pocas dependencias, que denominaremos myrepo.
Sin más preámbulos, he aquí el script:


#! /bin/sh
# myrepo version 0.3.8 (2017-12-14) por Hugo Florentino
# Script para construir repositorios personalizados en Debian y derivadas
# (Comprobado en Debian Jessie)
#
# Basado en el proyecto atrepo por Yasiel Ordoñez Abreu

SCRIPTNAME=$(basename "${0}")
SCRIPTVERSION=0.3.8

if [ -z ${LC_ALL} ]; then
  LC_ALL="en_US.UTF-8"
else
  SESSIONLANG=${LC_ALL}
fi

# Detectar dependencias necesarias
if [ $(which dpkg-scanpackages | wc -l) -ne 1 ]; then
  echo "Necesita instalar el paquete dpkg-dev."
  exit 1
fi

if [ $(which lsb_release | wc -l) -ne 1 ]; then
  OSTYPE="$(cat /etc/issue | sed -r 's/\s+\\[nl]//g') ($(uname -m))"
else
  OSTYPE="$(lsb_release -is) GNU/Linux $(lsb_release -rs) ($(uname -m))"
fi

# Detectar versiones necesarias (apt >= 0.8.11)
APTLOWVERSION="0.8.10"
APTVERSION=$(dpkg-query -W apt | cut -f2)
if [ $(echo "${APTLOWVERSION}\n${APTVERSION}" | sort -V | tail -1) \
  = "${APTLOWVERSION}" ]; then
  echo "La versión ${APTVERSION} de apt no soporta el parámetro download."
  exit 2
fi
unset APTVERSION APTLOWVERSION

# Ayuda para la ejecución sin argumentos
if [ $# -lt 1 ]; then
  echo "myrepo ${SCRIPTVERSION} (c) Hugo Florentino"
  echo "Script para hacer repositorios personalizados en Debian y derivadas."
  echo "Licencia: CC BY-SA 4.0\n"
  echo "Como argumentos, use el nombre de uno o más paquetes a incluir."
  echo "Si se le pregunta, proporcione la ruta (absoluta o relativa) donde"
  echo "desee crear el repositorio.\n"
  echo "Si desea utilizar el script varias veces, también puede exportar dicha"
  echo "ruta, por ejemplo de la siguiente manera:\n"
  echo 'export REPOPATH=/var/tmp/mirepo'
  echo "\nEjemplo de uso:\n"
  echo "${SCRIPTNAME} mc less multitail\n"
  exit 3
fi

# Descomente y edite la siguiente línea si desea anclar una ruta fija:
#REPOPATH=/var/tmp/mirepo

if [ -z "${REPOPATH}" ]; then
  echo "Introduzca la ruta de creación del repositorio"
  read INPUT
  if [ -z "${INPUT}" ]; then
    echo "Imposible continuar sin un destino para el repositorio."
    exit 4
  else
    REPOPATH="${INPUT}"
  fi
  unset INPUT
fi

if [ ! -d "${REPOPATH}" ]; then
  echo "La ruta ${REPOPATH} no existe, se intentará crearla."
fi
mkdir -p "${REPOPATH}/binary" > /dev/null 2>&1
if [ $? -ne 0 ]; then
  echo "Imposible crear los directorios necesarios. Reintente con otra ruta."
  exit 5
fi

touch "${REPOPATH}/${SCRIPTNAME}.log"
echo -n > "${REPOPATH}/${SCRIPTNAME}.log"

PKGLIST=$(apt-cache --quiet --no-recommends --no-suggests --no-conflicts \
  --no-breaks --no-replaces --no-enhances --recurse depends $@ \
  | grep -Ev "(<|>)" | sed -r 's/.*\s+(\S+)$/\1/g' | sort -Vu)
if [ -z "${PKGLIST}" ]; then
  echo "Revise que el nombre de todos los paquetes sea correcto." \
    | tee -a "${REPOPATH}/${SCRIPTNAME}.log"
  exit 6
fi

cd "${REPOPATH}/binary"
echo "Iniciando la descarga de paquetes..." \
  | tee -a "${REPOPATH}/${SCRIPTNAME}.log"
apt-get download $(echo "${PKGLIST}" | xargs) \
  | tee -a "${REPOPATH}/${SCRIPTNAME}.log"
if [ $? -ne 0 ]; then
  echo "Ocurrió algún problema al descargar los archivos." \
  | tee -a "${REPOPATH}/${SCRIPTNAME}.log"
  echo "Verifique que tiene acceso al repositorio." \
  | tee -a "${REPOPATH}/${SCRIPTNAME}.log"
  exit 7
else
  DOWNCOUNT=$(expr $(cat "${REPOPATH}/${SCRIPTNAME}.log" | grep -E '^Get:' \
    | wc -l) + 0)
  if [ ${DOWNCOUNT} -eq 0 ]; then
    echo "Los paquetes necesarios ya se encuentran en el repositorio." \
      | tee -a "${REPOPATH}/${SCRIPTNAME}.log"
    exit 8
  fi
  echo "Descarga finalizada (${DOWNCOUNT} paquetes)." \
    | tee -a "${REPOPATH}/${SCRIPTNAME}.log"
  unset DOWNCOUNT
  echo "Generando el archivo Packages ..." \
    | tee -a "${REPOPATH}/${SCRIPTNAME}.log"
  cd ${REPOPATH}
  dpkg-scanpackages "binary" 2>> "${SCRIPTNAME}.log" > "Packages"
  gzip -9c Packages > Packages.gz
  if [ $? -ne 0 ]; then
    echo "Ocurrió un error inesperado al generar el archivo Packages." \
      | tee -a "${REPOPATH}/${SCRIPTNAME}.log"
    exit 9
  else
    PKGLIST=$(cat "${REPOPATH}/Packages" | grep -E '^Package:\s+\S+$' \
      | sed -r 's/.*\s(\S+)$/\1/g')
    PKGNUM=$(find "${REPOPATH}/binary" -type f -iname "*.deb" | wc -l)
    echo "Finalizado. Su repositorio se ubica en ${REPOPATH}\n" \
      | tee -a "${REPOPATH}/${SCRIPTNAME}.log"
    README="${REPOPATH}/leame.txt"
    echo "Lea el archivo ${README} para más detalles.\n"
    echo "Repositorio personalizado de ${OSTYPE}" > "${README}"
    echo "Generado: $(date "+%F (%T)")\n" >> "${README}"
    echo "Para agregar el repositorio a su sistema, como superusuario, cree" \
      >> "${README}"
    echo "el archivo /etc/apt/sources.list.d/mirepo.list con algo como:\n" \
      >> "${README}"
    echo "deb [trusted=yes] file:/media/mirepo /\n" >> "${README}"
    echo "o quizas:\n\ndeb [trusted=yes] http://192.168.0.1/mirepo /\n" >> "${README}" 
    echo "Una vez agregado el origen personalizado, actualizar con:\n" \
      >> "${README}"
    echo "apt-get update\n" \
      >> "${README}"
    echo "o alternativamente:\n" >> "${README}" 
    echo "aptitude update\n\n" \
      >> "${README}"
    PKGSIZE=$(du -sh "${REPOPATH}/binary" | awk '{print $1}')
    echo "Paquetes contenidos en el repositorio (${PKGNUM}, ${PKGSIZE}):\n" \
      >> "${README}"
    echo "${PKGLIST}" >> "${README}"
    unset PKGLIST PKGSIZE PKGNUM README
  fi
fi

if [ -z ${SESSIONLANG} ]; then
  unset LC_ALL
else
  LC_ALL=${SESSIONLANG}
  unset SESSIONLANG
fi

unset REPOPATH OSTYPE SCRIPTVERSION SCRIPTNAME

exit 0

A continuación muestro un ejemplo de uso del script para obtener los paquetes necesarios para instalar mc en Debian Jessie (amd64):

myrepo mc
Introduzca la ruta de creación del repositorio:
/var/tmp/mirepo
Iniciando la descarga de paquetes...
Get:1 http://ftp.debian.org/debian/ jessie/main e2fslibs amd64 1.42.12-2+b1 [186 kB]
Get:2 http://packages.dotdeb.org/ jessie/all libpcre3 amd64 2:8.39-1~dotdeb+8.1 [337 kB]
Get:3 http://ftp.debian.org/debian/ jessie/main gcc-4.9-base amd64 4.9.2-10 [160 kB]
Get:4 http://ftp.debian.org/debian/ jessie/main libgcc1 amd64 1:4.9.2-10 [39.5 kB]
Get:5 http://ftp.debian.org/debian/ jessie/main libglib2.0-0 amd64 2.42.1-1+b1 [2401 kB]
Get:6 http://ftp.debian.org/debian/ jessie/main libc6 amd64 2.19-18+deb8u10 [4665 kB]
Get:7 http://ftp.debian.org/debian/ jessie/main multiarch-support amd64 2.19-18+deb8u10 [181 kB]
Get:8 http://ftp.debian.org/debian/ jessie/main libgpm2 amd64 1.20.4-6.1+b2 [34.0 kB]
Get:9 http://ftp.debian.org/debian/ jessie/main libffi6 amd64 3.1-2+deb8u1 [20.2 kB]
Get:10 http://ftp.debian.org/debian/ jessie/main libgcrypt20 amd64 1.6.3-2+deb8u4 [392 kB]
Get:11 http://ftp.debian.org/debian/ jessie/main libgpg-error0 amd64 1.17-3 [94.9 kB]
Get:12 http://ftp.debian.org/debian/ jessie/main libselinux1 amd64 2.3-2 [89.8 kB]
Get:13 http://ftp.debian.org/debian/ jessie/main libssh2-1 amd64 1.4.3-4.1+deb8u1 [125 kB]
Get:14 http://ftp.debian.org/debian/ jessie/main mc amd64 3:4.8.13-3 [506 kB]
Get:15 http://ftp.debian.org/debian/ jessie/main mc-data all 3:4.8.13-3 [1212 kB]
Get:16 http://ftp.debian.org/debian/ jessie/main libslang2 amd64 2.3.0-2 [491 kB]
Get:17 http://ftp.debian.org/debian/ jessie/main zlib1g amd64 1:1.2.8.dfsg-2+b1 [88.8 kB]
Fetched 11.0 MB in 50s (219 kB/s)
Descarga finalizada (17 paquetes).
Generando el archivo Packages ...
Finalizado. Su repositorio se ubica en /var/tmp/mirepo

Lea el archivo /var/tmp/mirepo/leame.txt para más detalles.

Algo que conviene mencionar, es que el script utiliza los orígenes que el sistema donde se corre tenga declarados, por ejemplo, en este caso, se utilizó el origen de mi repositorio dotdeb para obtener una dependencia más actualizada.

Si el script se invoca múltiples veces manteniendo la ruta /var/tmp/mirepo/, el resultado es que puede irse construyendo gradualmente un repositorio en dicho directorio. Una manera más cómoda de mantener la ruta puede ser modificando la variable REPOPATH en el script, o mejor aun, exportándola antes de ejecutar el script, por ejemplo de la siguiente forma:

export REPOPATH=/var/tmp/mirepo

De cualquier manera, en una sola ejecución pueden especificarse muchos paquetes y no uno solo, si así se desea.

Para utilizar el repositorio creado, podemos entonces copiar el directorio mirepo en el equipo de destino, digamos en /home/miusuario/ y crear un archivo de origen como por ejemplo /etc/apt/sources.list.d/mirepo.list con el siguiente contenido:

deb [trusted=yes] file:/home/miusuario/mirepo /

Nótese que en el caso de este simple script, no se ha realizado la firma de los paquetes, de ahi que sea necesario agregar el origen como trusted. Queda entonces actualizar el origen de los paquetes, para lo cual puede ejecutarse uno de los siguientes comandos:

apt-get updateaptitude update
Entonces podrán instalarse los paquetes normalmente.

Naturalmente, este script es demasiado simple para permitir cosas avanzadas como preparar repositorios para otra arquitectura o sistema operativo; para esto mejor utilizar otras herramientas.

Notas:

Artículo y script actualizados el 2017-12-14.

Suscríbete · Newsletter

Mantente al día, cada semana

Artículos prácticos sobre Linux, redes, seguridad, virtualización y la nube — escritos por sysadmins cubanos.

  • Guías y tutoriales de administración de sistemas
  • Nuevos artículos sobre servidores, redes y nube
  • Sin spam, cancela cuando quieras

Respetamos tu bandeja de entrada. Cancela con un clic.

Patrocinado por SYSCU

¿Tu infraestructura en la nube te cuesta de más?

SYSCU optimiza tu nube de punta a punta — FinOps, DevOps & CI/CD, migraciones a AWS, seguridad y observabilidad. Equipo 100 % senior que reduce tu factura hasta un 40 % y acelera tus despliegues en semanas.

Nuevo · BetaSYSCU Atlas Insight — la plataforma FinOps que convierte tu gasto AWS en decisiones: visibilidad multi-cuenta, recomendaciones automáticas y alertas de anomalías.

No comments yet