我有一个可以重新运行的 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