42 votes

Trouver (et réinstaller) des packages avec des fichiers corrompus (sans rien casser)

Je préfère généralement réparer un système Linux plutôt que de le réinstaller à partir de zéro. Mes ordinateurs ont subi de nombreuses mises à niveau de distribution et une liste de PPA ou de dépôts tiers. APT s'assure généralement que tout fonctionne à la fin. Cependant, le fait que le gestionnaire de paquets pense que tous les paquets requis sont 'installés' ne garantit pas que tous les fichiers sont présents sur le système de fichiers.

Une telle situation peut se produire si vous devez contourner des problèmes de dépendance avec dpkg --force-*. On pourrait également reproduire une telle situation en supprimant un fichier de /usr en tant que root.

Y a-t-il un moyen simple de vérifier si tous les fichiers appartenant à un paquet installé sont présents?

Si un tel paquet problématique est trouvé, aptitude reinstall résout le problème.

61voto

b34r Points 316

De la page de manuel de debsums:

apt-get install --reinstall $(dpkg -S $(debsums -c) | cut -d : -f 1 | sort -u)
       Réinstalle les paquets avec des fichiers modifiés.

Je viens de faire cela sur mon système car le contenu du disque était aléatoirement corrompu pendant que j'expérimentais avec un OS bêta. Voici ce que j'ai fait (et cela semble avoir bien fonctionné) :

Tout d'abord, j'ai installé 'debsums' et je l'ai exécuté pour voir si j'avais des fichiers corrompus sur mon système :

$ sudo apt-get install debsums
$ sudo debsums_init
$ sudo debsums -cs
/usr/share/bash-completion/completions/ssh
/usr/share/icons/hicolor/scalable/actions/cheese-take-photo.svg
/usr/share/gnome/help/gnumeric/C/files-textopen.xml
/usr/share/dbus-1/services/indicator-sound.service
/lib/modules/3.11.0-12-generic/kernel/drivers/mtd/ubi/ubi.ko

Comme vous pouvez le voir, j'ai cinq fichiers corrompus donc j'ai besoin de les réinstaller. Voici comment j'ai trouvé quels paquets contiennent les fichiers corrompus :

$ sudo debsums -c | xargs -rd '\n' -- dpkg -S | cut -d : -f 1 | sort -u
bash-completion
cheese-common
gnumeric-doc
indicator-sound
linux-image-extra-3.11.0-12-generic

Ensuite, j'ai réparé la corruption en réinstallant les paquets endommagés :

$ xargs -rd '\n' -a <(sudo debsums -c | xargs -rd '\n' -- dpkg -S | cut -d : -f 1 | sort -u) -- sudo apt-get install -f --reinstall --
Lecture des listes de paquets... Fait
Construction de l'arbre des dépendances       
Lecture des informations d'état... Fait
Le paquet suivant a été installé automatiquement et n'est plus nécessaire :
  linux-image-generic
Utilisez 'apt-get autoremove' pour le supprimer.
0 mis à jour, 0 nouvellement installés, 5 réinstallés, 0 à enlever et 0 non mis à jour.
Il est nécessaire de télécharger 43,9 Mo d'archives.
Après cette opération, 0 o d'espace disque supplémentaires seront utilisés.
Récupération des sources 1http://us.archive.ubuntu.com/ubuntu/ saucy/main bash-completion all 1:2.0-1ubuntu3 [173 Ko]2http://us.archive.ubuntu.com/ubuntu/ saucy/main cheese-common all 3.8.3-0ubuntu1 [2 929 Ko]3http://us.archive.ubuntu.com/ubuntu/ saucy/universe gnumeric-doc all 1.12.6-1 [7 295 Ko]     4http://us.archive.ubuntu.com/ubuntu/ saucy/main linux-image-extra-3.11.0-12-generic i386 3.11.0-12.19 [33,5 Mo]5http://us.archive.ubuntu.com/ubuntu/ saucy/main indicator-sound i386 12.10.2+13.10.20131011-0ubuntu1 [55,7 Ko]Récupérés 43,9 Mo en 10min 23s (70,4 Ko/s)                                                           (Lecture de la base de données ... 174913 fichiers et répertoires déjà installés.)
Préparation du remplacement de bash-completion 1:2.0-1ubuntu3 (en utilisant .../bash-completion_1%3a2.0-1ubuntu3_all.deb) ...
Dépaquetage de la mise à jour de bash-completion ...
Préparation du remplacement de cheese-common 3.8.3-0ubuntu1 (en utilisant .../cheese-common_3.8.3-0ubuntu1_all.deb) ...
Dépaquetage de la mise à jour de cheese-common ...
Préparation du remplacement de gnumeric-doc 1.12.6-1 (en utilisant .../gnumeric-doc_1.12.6-1_all.deb) ...
Dépaquetage de la mise à jour de gnumeric-doc ...
Préparation du remplacement de linux-image-extra-3.11.0-12-generic 3.11.0-12.19 (en utilisant .../linux-image-extra-3.11.0-12-generic_3.11.0-12.19_i386.deb) ...
Dépaquetage de la mise à jour de linux-image-extra-3.11.0-12-generic ...
Examen de /etc/kernel/postrm.d .
run-parts: exécution de /etc/kernel/postrm.d/initramfs-tools 3.11.0-12-generic /boot/vmlinuz-3.11.0-12-generic
run-parts: exécution de /etc/kernel/postrm.d/zz-update-grub 3.11.0-12-generic /boot/vmlinuz-3.11.0-12-generic
Préparation du remplacement de indicator-sound 12.10.2+13.10.20131011-0ubuntu1 (en utilisant .../indicator-sound_12.10.2+13.10.20131011-0ubuntu1_i386.deb) ...
Dépaquetage de la mise à jour de indicator-sound ...
Traitement des actions différées pour man-db ...
Traitement des actions différées pour libglib2.0-0:i386 ...
Aucune clé 'auto-launch' dans le schéma 'com.ubuntu.update-notifier' spécifiée dans le fichier de remplacement '/usr/share/glib-2.0/schemas/20_xubuntu-default-settings.gschema.override' ; ignoré le remplacement pour cette clé.
Traitement des actions différées pour hicolor-icon-theme ...
Configuration de bash-completion (1:2.0-1ubuntu3) ...
Configuration de cheese-common (3.8.3-0ubuntu1) ...
Configuration de gnumeric-doc (1.12.6-1) ...
Configuration de linux-image-extra-3.11.0-12-generic (3.11.0-12.19) ...
Déclenchement de depmod.
update-initramfs: report de la mise à jour (le hook sera appelé plus tard)
Ne pas mettre à jour les liens symboliques initrd car nous sommes en cours de mise à jour/réinstallation
(3.11.0-12.19 a été configuré en dernier, selon dpkg)
Ne pas mettre à jour les liens symboliques des images car nous sommes en cours de mise à jour/réinstallation
(3.11.0-12.19 a été configuré en dernier, selon dpkg)
Examen de /etc/kernel/postinst.d.
run-parts: exécution de /etc/kernel/postinst.d/apt-auto-removal 3.11.0-12-generic /boot/vmlinuz-3.11.0-12-generic
run-parts: exécution de /etc/kernel/postinst.d/dkms 3.11.0-12-generic /boot/vmlinuz-3.11.0-12-generic
run-parts: exécution de /etc/kernel/postinst.d/initramfs-tools 3.11.0-12-generic /boot/vmlinuz-3.11.0-12-generic
update-initramfs: génération de /boot/initrd.img-3.11.0-12-generic
run-parts: exécution de /etc/kernel/postinst.d/pm-utils 3.11.0-12-generic /boot/vmlinuz-3.11.0-12-generic
run-parts: exécution de /etc/kernel/postinst.d/update-notifier 3.11.0-12-generic /boot/vmlinuz-3.11.0-12-generic
run-parts: exécution de /etc/kernel/postinst.d/zz-update-grub 3.11.0-12-generic /boot/vmlinuz-3.11.0-12-generic
Génération de grub.cfg...
Image Linux trouvée : /boot/vmlinuz-3.11.0-14-generic
Image initrd trouvée : /boot/initrd.img-3.11.0-14-generic
Image Linux trouvée : /boot/vmlinuz-3.11.0-12-generic
Image initrd trouvée : /boot/initrd.img-3.11.0-12-generic
Image memtest86+ trouvée : /boot/memtest86+.bin
Windows 7 (loader) trouvé sur /dev/sda1
Terminé
Configuration de indicator-sound (12.10.2+13.10.20131011-0ubuntu1) ...

Enfin, j'ai vérifié pour m'assurer qu'il ne reste plus de fichiers corrompus :

$ sudo debsums -c

Il n'y avait aucune sortie de cette commande, ce qui signifie qu'aucune erreur n'a été trouvée. :-)

Une dernière remarque : vous devriez également vérifier les fichiers de configuration de vos paquets pour vous assurer qu'ils sont corrects. Cela peut être plus difficile car les fichiers de configuration changent souvent, et les changements sont légitimes, donc vous devrez inspecter manuellement chaque fichier de configuration modifié pour déterminer s'il est effectivement corrompu. Voici comment obtenir une liste des fichiers de configuration modifiés :

$ sudo debsums -as
debsums: fichier modifié /etc/gnome/defaults.list (du package desktop-file-utils)
debsums: fichier modifié /etc/default/rcS (du package initscripts)
debsums: fichier modifié /etc/subuid (du package login)
debsums: fichier modifié /etc/subgid (du package login)
debsums: fichier modifié /etc/sudoers (du package sudo)

16voto

ajn Points 348

Le script donné par PeniWize fonctionne très bien pour les fichiers corrompus, mais ne prend pas en charge les paquets avec des fichiers manquants, car debsums les signale sur stderr. Pour réinstaller les paquets avec des fichiers manquants, cela a fonctionné pour moi :

xargs -rd '\n' -a <(sudo debsums -c 2>&1 | cut -d " " -f 4 | sort -u | xargs -rd '\n' -- dpkg -S | cut -d : -f 1 | sort -u) -- sudo apt-get install -f --reinstall --

4voto

Jan Points 3433

La question a été répondue ailleurs:

Y a-t-il un contrôle de santé Ubuntu? : le paquet debsums peut calculer les hachages MD5 et les comparer avec le paquet deb.

Y a-t-il un moyen sûr de réinstaller via le gestionnaire de paquets : Oui, mais ce n'est pas recommandé.

2voto

iva2k Points 121

J'ai élaboré le script suivant pour restaurer les fichiers manquants en utilisant divers astuces.

Sauvegardez-le dans le fichier dpkg-fix.sh, rendez-le exécutable avec chmod a+x dpkg-fix.sh et exécutez sudo ./dpkg-fix.sh -x.

Avis/Notez que l'option -x restaure les fichiers de configuration (dans /etc) qui ne sont pas restaurés par défaut. Cela peut endommager votre système. Il est très délicat de créer un outil automatisé pour restaurer correctement cela, car les fichiers de configuration sont souvent personnalisés. Vous devriez faire des sauvegardes et après la restauration comparer les différences avec votre dernière sauvegarde et prendre des décisions. Même après cela, élaborez un plan pour tester chaque changement car il est possible de casser gravement les choses sans moyen de récupération.

#! /bin/bash

## (c) 2020 IVA2K

# Doit être root
if [ $(id -u) -ne 0 ]; then
  printf "Doit être root. Avez-vous utilisé 'sudo' ?\n"
  exit 1
fi

do_install () {
  echo "Installation de debsums :"
  apt-get install debsums

  echo "Initialisation de debsums (cela peut prendre un certain temps)..."
  debsums_init

  echo "Installation & Initialisation de debsums terminées."
  exit 0
}

# Basé sur des idées de https://askubuntu.com/a/392326
# $1=arg debsums $2=0(pas d'erreur) 1(capture stderr de debsums) $3=fix|no_fix
do_debsums_parse () {
  echo "Analyse des fichiers modifiés ou manquants (debsums ${1} erreurs=${2} > debsums${1}${2}.log)..."
  if [ "${2}" -ne "0" ]; then
    IFS=$'\n' readarray -t badfiles <<< "$(debsums "${1}" 2>&1)"
  else
    IFS=$'\n' readarray -t badfiles <<< "$(debsums "${1}" 2>/dev/null)"
  fi

  IFS=$'\n' printf '%s\n' "${badfiles[@]}" >debsums${1}${2}.log

  unset files
  unset packages

  # définir IFS pour permettre le "for" dans un tableau avec des éléments contenant des espaces. Bash moche !
  local IFS=$'\n'
  for line in "${badfiles[@]}" ; do
    IFS=' ' read -a fields <<< "${line}"
    #echo "DEBUG: line=$line fields=${fields[@]}"

    # définir IFS pour permettre le "if" des tableaux à comparer avec des chaînes. Bash moche !
    local IFS=$' '
    if [ "${#line}" -eq "0" ] ; then
      echo -e ;# sauter les lignes vides
    elif [ "${fields[*]:0:4}" = "debsums: no md5sums for" ] ; then
      local IFS=$'\n'
      package="${fields[@]:4:1}"
      echo "DEBUG: pas de md5sums pour le paquet=$package"
      packages=(${packages[@]} "$package")
    elif [ "${fields[*]:0:3}" = "debsums: changed file" ] ; then
      local IFS=$'\n'
      file="${fields[@]:3:1}"
      package=$( dpkg -S ${file} | cut -d : -f 1)
      echo "DEBUG: fichier modifié=$file paquet=$package"
      files=(${files[@]} "$file")
      packages=(${packages[@]} "$package")
    elif [ "${fields[*]:0:3}" = "debsums: missing file" ] ; then
      local IFS=$'\n'
      file="${fields[@]:3:1}"
      package=$( dpkg -S ${file} | cut -d : -f 1)
      echo "DEBUG: fichier manquant=$file paquet=$package"
      files=(${files[@]} "$file")
      packages=(${packages[@]} "$package")
    elif [ "${#fields[@]}" -eq "1" ] ; then
      local IFS=$'\n'
      file="${fields[@]:0:1}"
      package=$( dpkg -S ${file} | cut -d : -f 1)
      echo "DEBUG: fichier modifié=$file paquet=$package"
      files=(${files[@]} "$file")
      packages=(${packages[@]} "$package")
    elif [ "${fields[*]:0:3}" = "debsums: symlink loop" ] ; then
      local IFS=$'\n'
      file="${fields[@]:8:1}"
      package=$( dpkg -S ${file} | cut -d : -f 1)
      echo "DEBUG: boucle de lien symbolique fichier=$file paquet=$package"
      files=(${files[@]} "$file")
      packages=(${packages[@]} "$package")
    else
      local IFS=$' '
      echo "AVERTISSEMENT: ligne non reconnue='$(declare -p line)' champs='$(declare -p fields)' test1:'${fields[*]:0:4}' test2:'${fields[*]:0:3}'"
    fi

  done

  local IFS=$' '
  if [ "${#files[@]}" -gt "0" ] ; then
    local IFS=$'\n'
    readarray -t files <<< "$(printf '%s\n' "${files[@]}" | sort -u)"
  fi
  local IFS=$' '
  if [ "${#packages[@]}" -gt "0" ] ; then
    local IFS=$'\n'
    readarray -t packages <<< "$(printf '%s\n' "${packages[@]}" | sort -u)"
  fi

  echo "Fichiers modifiés ou manquants ${#files[@]} (fichiers${1}${2}.log) :"
  echo ${files[*]}
  echo
  IFS=$'\n' printf '%s\n' "${files[@]}" >files${1}${2}.log

  echo "${#packages[@]} paquets avec des fichiers modifiés ou manquants (paquets${1}${2}.log) :"
  echo ${packages[*]}
  echo
  IFS=$'\n' printf '%s\n' "${packages[@]}" >packages${1}${2}.log

  if [ "${3}" = "fix" ]; then
    local IFS=$' '
    if [ "${#packages[@]}" -gt "0" ] ; then
      echo "Réinstallation de ${#packages[@]} paquets :"
      apt-get install -f --reinstall -o Dpkg::Options::=--force-confmiss ${packages[@]}
      echo
    fi

    #local IFS=$'\n'
    #for package in "${packages[@]}" ; do
    #  # effort spécial pour restaurer les fichiers de configuration manquants du paquet
    #  # (il inclut les scripts dans /etc/*, que apt/dpkg ne réinstallera pas par défaut)
    #  dpkg -i --force-confmiss /var/cache/apt/archives/${package}*.deb
    #done

    if [ -f "$(which debsums).patched" ]; then
      echo "Application du correctif debsums :"
      cp -vf "$(which debsums)" "$(which debsums).orig"
      cp -v  "$(which debsums).patched" "$(which debsums)"
      echo
    fi

    echo "Finition de la correction des ${#files[@]} fichiers modifiés ou manquants, ${#packages[@]} paquets."
  else
    echo "Analyse terminée : ${#files[@]} fichiers modifiés ou manquants, ${#packages[@]} paquets."
  fi
  echo

  exit 0
}

case "$1" in
  -i|install)
    do_install
    ;;
  -s|check_sums|"")
    do_debsums_parse "-cs" 0 no_fix
    ;;
  -c|check_changed)
    do_debsums_parse "-as" 1 no_fix
    ;;
  -f|fix_corrupt)
    do_debsums_parse "-c" 0 fix
    ;;
  -m|fix_missing)
    do_debsums_parse "-c" 1 fix
    ;;
  -x|fix_missing_config)
    do_debsums_parse "-as" 1 fix
    ;;
  *)
    echo "Utilisation : $0 [ -i|install | -s|check_sums | -c|check_changed | -f|fix_corrupt | -m|fix_missing | -x|fix_missing_config ]" >&2
    exit 3
    ;;
esac

-1voto

colivier Points 361

En utilisant le programme dpkg avec un peu de scripting Bash, vous devriez pouvoir faire cela. La seule réserve serait si quelqu'un remplaçait les versions "propres" des fichiers par des versions "malveillantes". Pour cela, vous auriez besoin d'obtenir des sommes de contrôle MD5 valides à partir d'un paquet intact. Quoi qu'il en soit, voici le code shell pour réaliser ce que vous voulez :

#!/bin/sh
PACKAGE_NAME="xterm"
for i in `sudo dpkg -L ${PACKAGE_NAME}`
do
    if ! [ -e $i ]; then
            echo "$i est un fichier manquant dans le paquet $PACKAGE_NAME."
    fi
done

Le script n'afficherait que si un fichier ou un répertoire défini dans le paquet était manquant. Vous devriez également remplacer la variable 'PACKAGE_NAME' par le nom du paquet que vous souhaitez inspecter. J'espère que cela vous aidera.

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X