4 votes

Comment faire attendre mon script si une autre instance d'APT est en cours d'exécution ?

J'ai rencontré quelques problèmes avec mes scripts.

Donc pour faire court et clair, je suis en stage et mon patron m'a donné la mission de faire une sonde pour Nagios.
Le but de cette sonde est de vérifier sur tous nos hôtes si un paquet est manquant dans le repo ; si oui, nous avons un avertissement sur Nagios avec la liste des paquets manquants.
Cette sonde peut inclure une liste blanche si nous voulons conserver un paquet qui n'est pas dans un quelconque repo mais que nous n'utilisons pas.

Voici mon script :

#!/bin/bash

STATE_OK=0
STATE_WARNING=1
STATE_CRITICAL=2

which apt-show-versions >/dev/null
STATE=$?

declare -a WHITELIST=( host1:elasticsearch:all host2:elasticsearch:all)
PACKAGES=()
NOT_AVAILABLE=()
HOST=$(hostname)

#while [ -f /var/lib/apt/lists/lock ]
#do
#  sleep 2
#done

if [ "$STATE" = 0 ] #Verifie la condition apt-show-version = installer
then

    packets=$(apt-show-versions | grep 'No available version in archive' | cut -d" " -f1)

    for packet in $packets;do
        PACKAGES+=("${HOST}:$packet")
    done

    for package in "${PACKAGES[@]}"; do
        if [ "${WHITELIST[*]}" != "${package}" ]; then
            NOT_AVAILABLE+=("$package")
        fi
    done

    if [ -z "$NOT_AVAILABLE" ]; then
        #Ok dans Nagios
        echo "There is no package without version in archive"
        exit $STATE_OK
    else
        #Warning dans Nagios
        echo "Some package have no available version in archive"
        echo ${NOT_AVAILABLE[*]//"${HOST}":}
        exit $STATE_WARNING
    fi
else
    #Critical dans nagios
    echo "Package apt-show-versions is missing"
    exit $STATE_CRITICAL
fi

Et il y a le message qui vient de Nagios :

Remote command execution failed: Failed to open file /var/lib/apt/lists//security.debian.org_dists_stretch_updates_InRelease for reading: Permission denied

J'ai essayé de jouer avec le fichier lock dans mon script mais ça ne marche pas, j'ai comme une boucle infinie.

J'ai déjà jeté un coup d'œil à cette question et j'ai essayé de faire un wrapper mais il n'a pas fonctionné ou j'ai raté quelque chose puisque je suis étudiant et c'est mon premier pas dans le monde des scripts Shell.

J'ai regardé este aussi, mais c'est un peu vieux.

EDIT : J'ai trouvé comment le faire. Merci à toutes les personnes qui ont essayé de m'aider et spécialement à Sergiy Kolodyazhnyy.

J'ai donc utilisé APT et DPkg Hooks pour cela et j'ai dû modifier mon script pour utiliser ces hooks.

Je crée un fichier nommé 00apt-show-version dans /etc/apt/apt.conf.d/ avec ces deux lignes :

APT::Update::Post-Invoke {"apt-show-versions 1>/tmp/nagios_apt_show_versions";};
DPkg::Post-Invoke {"apt-show-versions 1> /tmp/nagios_apt_show_versions";}

Chaque fois que apt-get update est appelé ou apt-get install/remove, apt-show-versions fera son travail et tout le stdout de apt-show-versions est écrit dans nagios_apt_show_versions.

Après cela, j'ai dû modifier mon script comme ceci :

#!/bin/bash
#Script qui verifie si les paquets installer sur une machine ne dispose
#pas de versions dans les depots.

STATE_OK=0
STATE_WARNING=1
STATE_CRITICAL=2

which apt-show-versions >/dev/null
STATE=$?

declare -a WHITELISTHOST=(host1:elasticsearch:all host2:elasticsearch:all host2:linux-image-4.9.0-0.bpo.5-amd64:amd64 host3:python-django-flatpages-tinymce:all)
WHITELIST=()
NOT_AVAILABLE=()
HOST=$(hostname)

if [ "$STATE" = 0 ]; then #Verifie la condition apt-show-version = installer

    #Verifie que le fichier n existe pas et le cree
    if [ ! -f "/tmp/nagios_apt_show_versions" ]; then
        touch /tmp/nagios_apt_show_versions
    fi

    packets=$(grep 'No available version in archive' /tmp/nagios_apt_show_versions | cut -d: -f1)

    for white in "${WHITELISTHOST[@]}"; do
        if [ "${HOST}" = "$(echo $white | cut -d: -f1)" ]; then
            WHITELIST+=("$(echo $white | cut -d: -f2)")
        fi
    done

    for packet in $packets; do
        if [ "${WHITELIST[@]}" != "${packet}" ]; then
            NOT_AVAILABLE+=("$packet")
        fi
    done

    if [ -z "$NOT_AVAILABLE" ]; then
        #Ok dans Nagios
        echo "There is no package without version in archive"
        exit $STATE_OK
    else
        #Warning dans Nagios
        echo "Some package have no available version in archive"
        echo ${NOT_AVAILABLE[*]}
        exit $STATE_WARNING
    fi

else
    #Critical dans nagios
    echo "Package apt-show-versions is missing"
    exit $STATE_CRITICAL
fi

BTW la Withelist fonctionne maintenant (enfin un peu mais ce n'est pas le but de ce fil, je demandais juste des crochets).

5voto

Sergiy Kolodyazhnyy Points 97292

Envisagez d'utiliser lsof pour vérifier si le fichier est en cours d'utilisation, comme recommandé dans la rubrique poste d'erreur de serveur associé . Vous pourriez faire quelque chose comme ça :

while [ "x$(lsof /var/lib/apt/lists/lock)" != "x" ] ; do
    # if lsof returns output, that means some apt task is running
    # wait 60 seconds and check again
    sleep 60
done

Une autre commande serait fuser (et, à mon avis, mieux que lsof ). D'après documentation :

fuser renvoie un code de retour non nul si aucun des fichiers spécifiés n'est accédé ou en cas d'erreur fatale. Si au moins un accès a été trouvé, fuser renvoie zéro.

Cela signifie que vous pouvez compter sur le statut de sortie dans la boucle, ce qui rend la syntaxe plus agréable :

while fuser /var/lib/apt/lists/lock > /dev/null ; do
    sleep 60
done

Idéalement, vous devriez probablement utiliser fnctl() type de fonction pour voir si le fichier est verrouillé, soit via C ou Python.

Voir aussi :

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