我如何才能幂等地使用 pecl 安装一个模块两次?

我如何才能幂等地使用 pecl 安装一个模块两次?

我有一个可以重新运行的 bash 脚本。它包括

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

如果运行两次,则会出错

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

与 apt-get 或 yum 等工具不同,如果模块已安装,pecl 会返回错误代码,而我希望它报告成功。

我可以捕获并 grep stdout/stderr,但是有没有更简单的方法来实现相同的目的?

答案1

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

答案2

你可以歧视面具

使用下面的技术来获取命令的返回值pecl install foo。它保存了调用的返回值,但“true”命令有效地掩盖了它,因此无论 的值如何,语句都会返回 0 retVal

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

但...

这不会有太大帮助,因为pecl install无论失败的性质如何,似乎都会返回值 1 - 快速测试表明,已安装的包或未找到包错误都会返回 1。

因此,我只需在调用之前检查该包是否已安装pecl install

为了检查某个包是否已安装,我假设名称不包含 pecl 前缀,例如 jsonc 而不是 pecl/jsonc;并且 pecl list-all 的输出将始终以 pecl 开头。为了说明起见,假设我们正在使用包 jsonc:

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

将导致以下输出(假设其已安装):

pecl/jsonc                    1.3.10 JavaScript Object Notation

为了避免错误地声明已安装包,grep 使用的正则表达式会利用该输出格式 - 如果我们仅匹配包名称,则 jsonc 的匹配也将匹配 jsoncde(不是真正的包)。因此,正则表达式会查找行首后面跟着pecl/包名称,包名称后面有一个空格:"^pecl/$pkg "

您可能需要根据可能使用的包名称来修改该正则表达式。

#!/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

如果pecl list-all | grep ...命令在检查已安装的软件包时出现错误,您也可以使用命令pecl info $pkg。我没有深入研究它,但当查询的软件包已安装时,它似乎返回 0(并将一堆信息返回到 stdout),而当软件包未安装时,它返回 1(并将错误返回到 stderr)。

答案3

我通过简单地卸载模块来解决这个问题,就好像模块不存在而你执行卸载时,它会返回 0,而且因为在我看来这是一项罕见的工作,所以额外的重新安装并不重要。

答案4

为什么不假装安装(-p选项),然后如果可以的话再安装?

set -e
if pecl install -p -- "$PACKAGE"; then
  pecl install -- "$PACKAGE"
fi

相关内容