
El arranque en mi Ubuntu 17.04 falla y quiero depurarlo.
El arranque falla aleatoriamente y creo que se debe a una condición de carrera.
¿Puedo pedir que systemd
no se ponga en paralelo ninguna tarea para poder ver si esto hace que el arranque falle de forma predecible?
Respuesta1
Una solución alternativa: ejecutar servicios manualmente
Tuve unfalla durante el inicio. En mi caso, el bloqueo se produjo después de alcanzar el basic.target
objetivo, pero antes multi-user.target
, por lo que quería saber cuál de los servicios iniciados multi-user.target
estaba causando el bloqueo.
Primero arreglé arrancar desde basic.target
más un shell raíz. Puedes hacerlo permanentemente (¡suponiendo que consigas arrancar!) con
systemctl set-default basic.target
systemctl enable debug-shell
El debug-shell
servicio ejecuta un shell raíz en tty 9.
Puede obtener el mismo efecto agregando los parámetros systemd.unit=basic.target systemd.debug-shell
a la línea de comando del kernel. Por ejemplo, en Grub, edite la línea de comando a algo como
linux /vmlinuz-4.13.0-38-generic root=/dev/mapper/crypt-root ro systemd.unit=basic.target systemd.debug-shell
Desde este shell, ejecuté el siguiente script para iniciar los servicios uno por uno. Tenga en cuenta que esto no se ha probado en gran medida (lo ejecuté una vez y falló como se esperaba en el servicio problemático).
#!/bin/sh
wants=$(systemctl show -p Wants multi-user.target | sed 's/^Wants=//' | tr ' ' '\n' | sort)
log=/var/tmp/multi-user-steps-$(date +%Y%m%d-%H%M%S)
log () {
echo "$* ..." | tee -a "$log"
sync
"$@"
ret=$?
echo "$* -> $ret" | tee -a "$log"
sync
return $ret
}
# systemd services
for service in $wants; do
log systemctl start $service
sleep 2
done
# upstart services
for conf in /etc/init/*.conf; do
service=${conf##*/}; service=${service%.conf}
log service ${service} start
sleep 2
done
# sysvinit services
for service in /etc/rc3.d/S*; do
log ${service} start
sleep 2
done
Agregar dependencias adicionales
El siguiente script declara dependencias "Antes" de las unidades systemd que son dependencias directas de un objetivo determinado para obligarlas a ejecutarse en un orden específico. Quizás quieras ejecutarlo en multi-user.target
o basic.target
.
Tenga en cuenta queeste script no funciona en generalporque no tiene en cuenta las dependencias existentes: puede provocar un bucle de dependencia. Un script adecuado debe recopilar las dependencias existentes y realizar una clasificación topológica. Resolví mi problema, así que no tengo intención de trabajar más en él; Lo publico por si alguien quiere adaptarlo a sus necesidades.
Tenga en cuenta también que esto no afecta a los servicios Upstart y SysVinit.
¡Haga una copia de seguridad /etc
antes de ejecutar esto! (Recomiendo encarecidamente usaretc guardián.)
#!/bin/sh
set -e
if [ $# -eq 0 ] || [ "$1" = "--help" ]; then
cat <<EOF
Usage: $0 TARGET
Linearize the dependencies of a systemd target so it starts deterministically.
This scripts adds systemd unit files called linearize-for*.conf containing
extra Before= dependencies for each dependency of TARGET.
EOF
fi
service_dir=/etc/systemd/system
target=$1
wants=$(systemctl show -p Wants "$target" | sed 's/[^= ]*=//' |
tr ' ' '\n' | sort)
previous=
for want in $wants; do
[ -d "$service_dir/$want.d" ] || mkdir "$service_dir/$want.d"
cat <<EOF >"$service_dir/$want.d/linearize-for-${target%.*}.conf"
[Unit]
Before=$previous
EOF
previous=$want
done