Verifique de manera confiable si un paquete está instalado o no

20

Tengo un requisito simple Quiero definir varias variables que corresponderán a cualquier número de paquetes dados que quiero instalar a través de un script de shell.

Código de muestra a continuación:

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

Todo funciona, pero la lógica parece defectuosa porque no está instalando de manera confiable los paquetes que quiero. Dice que ya se han instalado o está intentando instalar paquetes que ya se han instalado anteriormente.

También he estado intentando command -vo lo siguiente:

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

E incluso con las banderas -ny -zpara verificar si la cadena devuelta estaba vacía. Estoy bastante seguro de que me falta algo de sentido común aquí.

¿Tienes alguna idea de lo que podría hacer para asegurarme de que un paquete esté realmente instalado o no?

¡Gracias!

vanz
fuente
¿Qué daño hay si también pides apt-get installpaquetes instalados? Podrías simplemente llamar apt-get install $MISC $WEB.
jarno

Respuestas:

15

Esencialmente solo necesita reemplazar la ifcondición con

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

No es posible usarlo dpkg-query, porque devuelve verdadero también para los paquetes eliminados pero no purgados.

También sugiero verificar el código de salida de apt-getantes de dar el mensaje exitoso:

if apt-get -qq install $pkg; then
    echo "Successfully installed $pkg"
else
    echo "Error installing $pkg"
fi
enzotib
fuente
¿Qué &>hacer?
Taymon
@Taymon: redirige stdin y stderr al archivo dado ( /dev/nullen este caso), porque no necesitamos la salida, solo el código de salida. Solo funciona en bash(la primera línea del guión tiene que ser #!/bin/bash) de lo contrario usar >/dev/null 2>&1.
enzotib
@Taymon: Cambié la lógica, porque encontré una falla en la solución anterior.
enzotib
Cuidado: si usa bash y la opción pipefail está configurada, entonces grep -q puede generar Heisenbugs. Básicamente, grep sale antes de que dpkg termine de escribir (desea un estado de salida 0 en ese caso), por lo que dpkg falla al escribir en la tubería (que en su lugar genera un estado de salida que no es 0). Asegúrate de que pipefail no esté configurado o abandona las ganancias (probablemente pequeñas) de eficiencia de la opción "-q".
Ron Burk
2

Puede probarlo con dpkg-query:

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

Tenga en cuenta que * y? son comodines, si aparecen en $ pkg. Supongo que dpkg-query puede imprimir "reinst-required instalado" en lugar de "ok instalado", si el paquete está roto y necesita ser reinstalado por un comando apt-get install --reinstallque también se puede utilizar para instalar nuevos paquetes.

jarno
fuente
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
Señor Linux
fuente