Verifique de forma confiável se um pacote está instalado ou não


20

Eu tenho um requisito simples. Eu quero definir várias variáveis ​​que corresponderão a qualquer número de pacotes que eu quero instalar via um script de shell.

Código de exemplo abaixo:

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

Tudo meio que funciona, mas a lógica parece falha porque não é a instalação confiável dos pacotes que eu quero. Ele diz que já foi instalado ou está tentando instalar pacotes que já foram instalados anteriormente.

Eu também tenho tentado com command -vou o seguinte:

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

E mesmo com os sinalizadores -ne -zpara verificar se a sequência retornada estava vazia. Tenho certeza de que estou perdendo algum bom senso aqui.

Você tem alguma idéia do que eu poderia fazer para garantir que um pacote esteja realmente instalado ou não?

Obrigado!


Que mal existe, se você pedir apt-get installpacotes instalados também? Você poderia simplesmente ligar apt-get install $MISC $WEB.
Jarno

Respostas:


15

Essencialmente, você só precisa substituir a ifcondição por

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

Não é possível usar dpkg-query, porque retorna true também para pacotes removidos, mas não eliminados.

Sugiro também verificar o código de saída apt-getantes de enviar a mensagem de sucesso:

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

O que &>faz?
Taymon

@ Taymon: redirecione stdin e stderr para o arquivo fornecido ( /dev/nullneste caso), porque não precisamos da saída, apenas o código de saída. Ele só funciona bash(a primeira linha do script deve ser #!/bin/bash) caso contrário, use >/dev/null 2>&1.
enzotib 12/07/2013

@ Taymon: mudei a lógica, porque encontrei uma falha na solução anterior.
enzotib

Cuidado: se estiver usando bash e a opção pipefail estiver definida, o grep -q poderá gerar Heisenbugs. Basicamente, o grep sai antes que o dpkg termine de gravar (você deseja um status de saída 0 nesse caso); portanto, o dpkg falha na gravação no canal (que gera um status de saída diferente de 0). Verifique se o pipefail não está definido ou abandone os (provavelmente pequenos) ganhos de eficiência da opção "-q".
precisa

2

Você pode testá-lo através do dpkg-query:

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

Observe que * e? são curingas, se aparecerem em $ pkg. Eu acho que o dpkg-query pode imprimir "reinst-required installed" em vez de "ok installed", se o pacote estiver quebrado e precisar ser reinstalado pelo comando apt-get install --reinstallque pode ser usado para instalar novos pacotes também.


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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.