Controlla in modo affidabile se un pacchetto è installato o meno


20

Ho un semplice requisito. Voglio definire diverse variabili che corrisponderanno a qualsiasi numero di pacchetti dati che voglio installare tramite uno script di shell.

Codice di esempio di seguito:

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

Tutto funziona, ma la logica sembra imperfetta perché non sta installando in modo affidabile i pacchetti che voglio. Indica che sono già stati installati o sta tentando di installare pacchetti che sono già stati installati in precedenza.

Ho anche provato con command -vo il seguente:

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

E anche con i flag -ne -zper verificare se la stringa restituita era vuota. Abbastanza sicuro che mi manchi un po 'di buon senso qui.

Hai idea di cosa potrei fare per assicurarmi che un pacchetto sia effettivamente installato o no?

Grazie!


Che danno c'è, se apt-get installrichiedi anche i pacchetti installati? Potresti semplicemente chiamare apt-get install $MISC $WEB.
jarno,

Risposte:


15

Fondamentalmente devi solo sostituire la ifcondizione con

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

Non è possibile utilizzarlo dpkg-query, poiché restituisce true anche per i pacchetti rimossi ma non eliminati.

Inoltre suggerisco di controllare il codice di uscita apt-getprima di dare il messaggio corretto:

if apt-get -qq install $pkg; then
    echo "Successfully installed $pkg"
else
    echo "Error installing $pkg"
fi

Cosa fa &>?
Taymon,

@Taymon: reindirizza sia stdin che stderr al file dato ( /dev/nullin questo caso), perché non abbiamo bisogno dell'output, ma solo del codice di uscita. Funziona solo in bash(la prima riga dello script deve essere #!/bin/bash) altrimenti utilizzare >/dev/null 2>&1.
enzotib,

@Taymon: ho cambiato la logica, perché ho trovato un difetto nella soluzione precedente.
enzotib,

Attenzione: se si utilizza bash e l'opzione pipefail è impostata, grep -q può generare Heisenbugs. Fondamentalmente, grep esce prima che dpkg finisca di scrivere (in questo caso si desidera uno stato di uscita 0), quindi dpkg non riesce a scrivere sulla pipe (che invece genera uno stato di uscita diverso da 0). Assicurati che non sia impostato pipefail o abbandona i (probabilmente minuscoli) incrementi di efficienza dell'opzione "-q".
Ron Burk,

2

Puoi testarlo con dpkg-query:

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

Notare che * e? sono caratteri jolly, se appaiono in $ pkg. Immagino che dpkg-query possa stampare "reinst-richiesto installato" invece di "ok installato", se il pacchetto è rotto e deve essere reinstallato dal comando apt-get install --reinstallche può essere utilizzato anche per installare nuovi pacchetti.


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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.