Vérifier de manière fiable si un package est installé ou non

20

J'ai une simple exigence. Je veux définir plusieurs variables qui correspondront à n'importe quel nombre de packages donnés que je veux installer via un script shell.

Exemple de code ci-dessous:

MISC="shutter pidgin"
WEB="apache2 mongodb"

for pkg in $MISC $WEB; do
    if [ "dpkg-query -W $pkg | awk {'print $1'} = """ ]; then
        echo -e "$pkg is already installed"
    else
        apt-get -qq install $pkg
        echo "Successfully installed $pkg"
    fi
done

Tout fonctionne un peu, mais la logique semble imparfaite car elle n'installe pas de manière fiable les packages que je veux. Il indique soit qu'ils ont déjà été installés, soit qu'il essaie d'installer des packages qui ont déjà été installés précédemment.

J'ai également essayé avec command -vou ce qui suit:

if [ "dpkg -l | awk {'print $2'} | grep --regexp=^$pkg$ != """ ]; then

Et même avec les drapeaux -net -zpour vérifier si la chaîne retournée était vide. Je suis sûr que je manque de bon sens ici.

Avez-vous une idée de ce que je pourrais faire pour m'assurer qu'un package est réellement installé ou non?

Merci!

vanz
la source
Quel mal y a-t-il si vous demandez également apt-get installdes packages installés? Vous pourriez simplement appeler apt-get install $MISC $WEB.
jarno

Réponses:

15

Il vous suffit essentiellement de remplacer la ifcondition par

if dpkg --get-selections | grep -q "^$pkg[[:space:]]*install$" >/dev/null; then

Il n'est pas possible de l'utiliser dpkg-query, car il renvoie vrai également pour les packages supprimés mais non purgés.

Je suggère également de vérifier le code de sortie de apt-getavant de donner le message réussi:

if apt-get -qq install $pkg; then
    echo "Successfully installed $pkg"
else
    echo "Error installing $pkg"
fi
enzotib
la source
Que fait &>-il?
Taymon
@Taymon: redirige à la fois stdin et stderr vers le fichier donné ( /dev/nulldans ce cas), car nous n'avons pas besoin de la sortie, seulement du code de sortie. Cela ne fonctionne que dans bash(la première ligne du script doit être #!/bin/bash) sinon utilisez >/dev/null 2>&1.
enzotib
@Taymon: J'ai changé la logique, car j'ai trouvé une faille dans la solution précédente.
enzotib
Attention: si vous utilisez bash et que l'option pipefail est définie, alors le grep -q peut générer des Heisenbugs. Fondamentalement, grep se ferme avant que dpkg ne termine l'écriture (vous voulez un état de sortie 0 dans ce cas), donc dpkg ne parvient pas à écrire dans le canal (ce qui génère à la place un état de sortie différent de 0). Soit vous assurer que pipefail n'est pas défini, soit abandonner les gains d'efficacité (probablement minimes) de l'option "-q".
Ron Burk
2

Vous pouvez le tester par dpkg-query:

if dpkg-query -W -f'${Status}' "$pkg" 2>/dev/null | grep -q "ok installed"; then

Notez que * et? sont des caractères génériques, s'ils apparaissent dans $ pkg. Je suppose que dpkg-query peut afficher "reinst-required installed" au lieu de "ok installed", si le package est cassé et doit être réinstallé par une commande apt-get install --reinstallqui peut également être utilisée pour installer de nouveaux packages.

jarno
la source
0
#to check package is installed or not without distribution dependency
#!/bin/bash
read -p "Package Name: " pkg
which $pkg > /dev/null 2>&1
if [ $? == 0 ]
then
echo "$pkg is already installed. "
else
read -p "$pkg is not installed. Answer yes/no if want installation_ " request
if  [ $request == "yes" ]
then
yum install $pkg
fi
fi
M. Linux
la source