Como posso idempotentemente instalar um módulo duas vezes?

2

Eu tenho um script bash que deve ser reexecutável. Inclui

pecl install foo ||
{
    echo "Could not install foo!";
    exit 1;
}

Se isso ocorrer duas vezes, erros

pecl/foo is already installed and is the same as the released version 1.2.3
install failed
Could not install foo!

Diferentemente de ferramentas como apt-get ou yum, o pecl retorna um código de erro se o módulo já estiver instalado, enquanto eu quero reportar sucesso.

Eu poderia capturar e usar o stdout / stderr, mas existe uma maneira menos hacky de conseguir o mesmo?

    
por spraff 27.11.2016 / 19:29

2 respostas

1
if ! pecl list | grep foo >/dev/null 2>&1;
then
    pecl install foo ||
    {
        echo_err "Could not pecl install foo";
        exit 1;
    }
fi
    
por 28.11.2016 / 07:56
1

Você pode discriminar e mascarar

o valor de retorno do comando pecl install foo com a técnica abaixo. Ele salva o valor de retorno da chamada, mas o comando 'true' o mascara de modo que a instrução retorne 0, independentemente do valor de retVal .

pecl install foo >/dev/null 2>&1 || { retVal=$?; true; }

Mas ...

isso não ajudará muito, porque pecl install parece retornar um valor de 1, independentemente da natureza da falha - um teste rápido mostrou que um pacote já instalado ou um erro de pacote não encontrado retornará 1.

Então, eu simplesmente verificaria se o pacote já estava instalado antes de chamar pecl install .

Para verificar se um pacote está instalado, presumo que o nome não inclua o prefixo pecl, por exemplo. jsonc não pecl / jsonc; e que a saída do pecl list-all sempre começará com o pecl. Para esclarecer, digamos que estamos trabalhando com o pacote jsonc:

 pkg="jsonc"
 pecl list-all | grep "$pkg"

Resultará nessa saída (supondo que esteja instalada):

pecl/jsonc                    1.3.10 JavaScript Object Notation

Para evitar declarar falsamente um pacote instalado, o regex usado com o grep alavanca esse formato de saída - se simplesmente correspondermos ao nome do pacote, uma correspondência no jsonc também seria uma correspondência para jsoncde (não um pacote real). Portanto, o regex está procurando o início da linha para ser pecl/ seguido pelo nome do pacote, com um espaço após o nome do pacote: "^pecl/$pkg "

Você pode precisar modificar esse regex com base nos possíveis nomes de pacotes em uso.

#!/bin/bash

if [ $# -lt 1 ]; then
  echo "Package name must be passed as sole argument"
  exit 2
else
  pkg="$1"
fi

if pecl list-all | grep -Eq "^pecl/$pkg " ; then
  echo "package $pkg is already installed"
  exit 0
else # not installed
  if pecl -q install "$pkg" >/dev/null ; then
    echo "Package $pkg installed successfully"
    exit 0
  else
    echo "Error occurred during installation of $pkg"
    exit 1
  fi
fi

Se o comando pecl list-all | grep ... se comportar mal ao verificar pacotes instalados, você também poderá usar o comando pecl info $pkg . Eu não olhei muito, mas parece retornar um 0 (e um monte de informações para stdout) quando o pacote que está sendo consultado está instalado, e retorna um 1 quando o pacote não está instalado (e um erro para stderr) ).

    
por 29.11.2016 / 11:26

Tags