Archero ¡Deja de usar Yaourt! ¡Usa aurman!

Foros

Hace algunos meses que he estado compartiendo mi postura frente al uso de Yaourt en ArchLinux y derivados para la instalación de paquetes desde AUR. Luego de varias discusiones en redes sociales (y varios insultos por usuarios inadaptados e inexpertos que no entienden la importancia de utilizar un buen AUR helper y la incidencia de estos dentro del sistema) he decidido crear un tema aquí en el foro donde expondré las razones técnicas por las cuales estoy en total desacuerdo con el uso de Yaourt y cualquier tipo de publicación/comentario que promueva su uso.

Un AUR helper es un script o un conjunto de scripts que nos ayuda a realizar la instalación de paquetes para ArchLinux que se encuentran en AUR de manera automática y con muy poca intervención del usuario, así cómo de la resolución de dependencias  automáticas de paquetes que a su vez dependen de otros paquetes que se encuentran en AUR y que pacman no puede resolver debido a que no tiene soporte para AUR, no fue creado con esa finalidad. Yaourt fue el primer AUR helper que utilicé, funciona "bien" aparentemente, pero luego de revisar su código fuente, te das cuenta del desastre que tiene yaourt en su código. Desde ese momento y luego de realizar varias pruebas, el AUR helper con mejores resultados fue aurman y por lo tanto es el que recomiendo.

A partir de este momento iniciaré con la comparación entre Yaourt y Aurman en diferentes aspectos.

Seguridad

Yaourt

Es inseguro desde su creación, en este fragmento de código podemos observar cómo convierte un fichero PKGBUILD en un "script inofensivo", pero eso no es lo grave del asunto, el problema es que una vez descargado el PKGBUILD este ejecuta el comando source al PKGBUILD antes de que usted pueda revisar lo que hay dentro del PKGBUILD, esto significa que si un usuario malicioso introduce dentro del PKGBUILD una sentencia cómo "rm -rf $HOME" este se ejecutará tal cual y borrara todo lo que tengas en el directorio que tenga asignado la variable $HOME y una vez que haya hecho eso, te dejará ver el contenido del PKGBUILD lo cual debe ser al contrario.

# sanitize_pkgbuild(pkgbuild)
# Turn a PKGBUILD into a harmless script (at least try to)
sanitize_pkgbuild() {
	local file="$1"
	local tmpfile=$(mktemp --tmpdir="$YAOURTTMPDIR")
	sed -n -e '/\$(\|`\|[><](\|[&|]\|;/d' \
	       -e '/ *[a-zA-Z0-9_\-]\+ *( *)/q' \
	       -e 's/^ *[a-zA-Z0-9_]\+=/declare &/' \
	       -e 'p' "$file" > "$tmpfile"
	sed -n -e '1,/^\r$/ d' \
	       -e '/^declare *[a-zA-Z0-9_]\+=(.*) *\(#.*\|$\)/{p;d}' \
	       -e '/^declare *[a-zA-Z0-9_]\+=(.*$/ {:a;N;$bb;/.*) *\(#.*\|$\)/!ba;s/\n/ /g;p;d;:b}' \
	       -e '/^declare *[a-zA-Z0-9_]\+=.*[^\\]$/{p;d}' "$tmpfile"
	sed -n -e '/^declare *[a-zA-Z0-9_]\+=.*\\$/ {:a;N;$bb;/.*[^\\]$/!ba;s/\n/ /g;p;d;:b}' "$tmpfile"
	rm "$tmpfile"
}

# Source a PKGBUILD and return a declare var list:
# Call in a sub process:
# . <(source_pkgbuild file var1 var2)
source_pkgbuild() {
	local file="$1"; shift; local vars=$*
	{ sanitize_pkgbuild "$file" | grep -E "declare (${vars// /|})"; } 2> /dev/null
}

Aurman

Aurman cumple de manera correcta con todas las políticas que hacen inseguro a Yaourt, una vez se descarga el PKGBUILD este permanece intacto y se le preguntará al usuario si desea ver el contenido, cuando el usuario tome la decisión respecto a la pregunta, se procede con la ejecución del contenido PKGBUILD.

Entorno limpio de contrucción (build)

Yaourt

Tampoco cumple con las condiciones que se necesitan para establecer un entorno de creación. El script /usr/lib/yaourt/pkgbuild.sh "exporta" la variable BUILDDIR (para pasarsela a makepkg) cuando está manejando los archivos makefile y utilizan esa variable. No estoy seguro de por qué yaourt necesita hacer eso, ya que makepkg debería ser bastante capaz de manejarlo ya... yaourt solo está dando prioridad al archivo del sistema makepkg.conf? Si es así, ¿por qué? ¿No es tan francamente contradictorio? Por lo tanto yaourt falla en la instalación de varios paquetes, pero si usted lo hace manualmente usando "makepkg" el resultado es satisfactorio.

Aurman

Aurman también resuelve el problema anterior dejándo el trabajo a MAKEPKG. Ver código.

                package.build(ignore_arch, rebuild)
                if package.name in sanitized_names \
                        and package.name not in sanitized_not_to_be_removed \
                        and package.name not in replaces_dict \
                        or (package.name in installed_system.all_packages_dict
                            and installed_system.all_packages_dict[package.name].install_reason
                            == 'explicit') \
                        or (package.name in replaces_dict
                            and installed_system.all_packages_dict[replaces_dict[package.name]].install_reason
                            == 'explicit'):

                    package.install(args_for_explicit, use_ask=use_ask)
                else:
                    package.install(args_for_dependency, use_ask=use_ask)
            except InvalidInput:
                sys.exit(1)

Uso nativo de pacman

Yaourt

Yaourt no usa el estilo nativo y correcto en que debe ser usado pacman, este ejecuta pacman en una serie de comandos divididos y que pueden llegar a romper el sistema en lugar de usar "pacman -Syu". Ver código.

	# `pacman -Spu` fails in some cases (e.g: when a package is replaced
	# by another one)
	if pacman_parse -Sp --noconfirm --print-format "## %n" $_arg \
		    "${PACMAN_S_ARG[@]}" "${pkg_up[@]}" >"$YAOURTTMPDIR/sysupgrade"; then
		packages=($(sed -n 's/^## \(.*\)/\1/p' "$YAOURTTMPDIR/sysupgrade" | sort))
		rm "$YAOURTTMPDIR/sysupgrade"
		[[ $packages ]] && upgrade_needed=1 || { upgrade_needed=0; return 0; }
	else
		# `pacman -Spu` failed so we don't know which packages
		# will be updated
		DETAILUPGRADE=0; upgrade_needed=1; return 1
	fi

	# package-query invocations are expensive, hence, the result is saved
	# in a global variable which can be used later by format_update().
	mapfile pkgs_repo_up_info < <(pkgquery -1Sif "%n %r %v %l %d" "${packages[@]}")

	while read pkgname repo unused; do
		if (( BUILD )) || custom_pkg "$pkgname"; then
			pkgs_src+=("$repo/$pkgname")
		else
			pkgs_repo+=("$repo/$pkgname")
		fi
	done < <(echo -n "${pkgs_repo_up_info[@]}")
}


Aurman

Aurman siempre utiliza la sentencia correcta, aunque usted utilice "aurman -Su", "aurman -S", "aurman $PAQUETE", por lo tanto también queda resuelto el problema anterior. Ver fuente.

Resolviendo dependencias.

Yaourt

Para ser un AUR helper tan usado, yaourt rompe muchas de las reglas básicas, por ejemplo, supongamos que un paquete A, depende de un paquete B y uno C, la manera correcta de hacerlo es: instalando B y C que son las dependencias de A y luego instalar A, pero yaourt hace esto en repetidas ocasiones: Instala A primero y luego B y C, o instala B primero, luego A y luego C, lo cual no es una resolución de dependencias adecuada. Ver fuente.

Aurman

Aurman soluciona el problema anterior tratando las dependencias cómo palabras, strings y entonces si un paquete A, depende de un paquete B, se busca el paquete B y sus dependencias, de instala y luego se instala A, esto se repite tanto para los paquetes requeridos a instalar, cómo para las dependencias requeridas por estos paquetes. Ver fuente.

Dependencia especificas de paquetes

Yaourt

Yaourt no es capaz de instalar/construir un paquete si este contiene dependencias que requieren una versión especifica. Es decir, si un paquete A, depende de uno B, con una versión c, Yaourt no es capaz de instalar ese paquete. Ver fuente.

Aurman

Al contrario que yaourt, aurman es capaz de solucionar esto de manera correcta debido a su sistema de resolución de dependencias mencionado anteriormente.

Uso de Git

Yaourt

Yaourt usa por defecto ABS en lugar de Git, aunque se puede especificar con la opción "-git" para que lo use. El hecho de que use ABS por defecto, permite que operaciones cómo la descarga de código fuente de un paquete ArchLinux mediante la opción "yaourt -G no funcione.

Aurman

Aurman utiliza Git por defecto, de hecho es una dependencia obligatoria del paquete, con eso resuelve los problemas anteriores de yaourt.

Vista de diferencias en los PKGBUILD

Yaourt

Por naturaleza maneja muy mal los PKGBUILD, de una manera peligrosa e insegura para el sistema, pero además de eso, por defecto tampoco da la opción para ver lo que ha cambiado entre la versión anterior y la nueva de un PKGBUILD, exponiendo aún más al usuario. Cabe mencionar que existe una opción para que muestre las diferencias entre commits del PKGBUILD.

Aurman

Aurman siempre te va a preguntar si deseas ver las diferencias, depende de tu decisión el que aurman continue con el proceso de instalación.

Instalación de aurman

Si deseas realizar el cambio hacia aurman lo único que debes hacer es leer https://github.com/polygamma/aurman

Si usar yaourt puedes ejecutar

gpg --recv-keys 4C3CE98F9579981C21CA1EC3465022E743D71E39 && yaourt -Syu aurman

Si deseas hacer el proceso manualmente debes realizar:

gpg --recv-keys 4C3CE98F9579981C21CA1EC3465022E743D71E39

git clone https://aur.archlinux.org/aurman.git && cd aurman && makepkg -si

Los comandos básicos de aurman son los mismos de pacman:

#Actualización del sistema
aurman -Syu

#Buscar un paquete
aurman -Ss paquete

#Instalar un paquete
aurman -S paquete

#Eliminar un paquete
aurman -R paquete

Luego de que finalice el proceso de instalación de aurman, recomiendo eliminar yaourt con:

pacman -Rns yaourt

Con esto finalizo esta discusión y espero que le haya quedado claro al lector que ha llegado hasta este punto, no es mi finalidad desvalorizar yaourt, sencillamente es un AUR Helper que ha dejado de actualizarse y tiene muchas inconsistencias en su código que los desarrolladores no desean solucionar por ahora y probablemente nunca. Cualquier inquietud puede ser dejada en los comentarios.

Acerca del autor

Especialista en Seguridad Informática bajo certificación OSCP, experto en técnicas de privacidad y seguridad en la red, desarrollador back-end, miembro de la FSF y Fundador de Security Hack Labs. Desarrollador de la distribución de hacking BlackArch Linux. Twitter: @edu4rdshl XMPP: [email protected]