web-dev-qa-db-fra.com

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

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

Donc, pour être bref et clair, je suis en stage et mon patron m'a confié une mission pour faire une sonde pour Nagios.
Le but de cette sonde est de vérifier sur tous nos hôtes si un paquet est absent du dépôt si oui alors nous avons un avertissement sur Nagios avec la liste des paquets manquants.
Cette sonde peut inclure une liste blanche si nous voulons conserver un package qui ne se trouve dans aucun référentiel mais que nous ne l'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 de verrouillage dans mon script mais cela ne fonctionne pas, je suis 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 depuis que je suis étudiant et c'est ma première étape dans le monde des scripts Shell.

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

EDIT: J'ai trouvé comment le faire beaucoup Thx à toutes les personnes essayant 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 la mise à jour apt-get est appelée ou install/remove apt-get, apt-show-versions fera l'affaire et toute la sortie standard d'apt-show-versions est écrite 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 the Withelist fonctionne maintenant (bien, mais ce n'est pas le but de ce fil, je demandais juste des crochets)

4
Ghrew

Pensez à utiliser lsof pour vérifier si le fichier est en cours d'utilisation, comme recommandé sur publication relative à Serverfault . 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 humble avis mieux que lsof). Selon documentation :

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

Cela signifie que vous pouvez vous fier au 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 le type de fonction fnctl() pour voir si le fichier est verrouillé, via C ou Python.

Voir également:

4
Sergiy Kolodyazhnyy