如何在Bash脚本中检查某个软件是否已安装?

5

我想要检查软件清单中的软件是否已安装。如果没有安装,应该显示出来并使脚本中止/退出。如果我执行该脚本,则输出应如下所示:

  wget is not installed
  telnet is not installed

目前看起来是这样的:

  wget is not installed

再次执行脚本...

  telnet is not installed

目前的脚本正在检查安装的软件,并在当前检查的软件未安装时终止/退出。这不太好,因为您必须运行脚本多次才能确定并检查每个软件是否已安装:

  LINUX_DISTRIBUTATION=$(grep -Eo "(Debian|Ubuntu|RedHat|CentOS)" /etc/issue)

  # Debian / Ubuntu
  if [ -f /etc/debian_version ] || [ "$LINUX_DISTRIBUTATION" == "Debian" ] || [ "$LINUX_DISTRIBUTATION" == "Ubuntu" ]; then
          declare -a NEEDED_SOFTWARE_LIST=(bash rsync wget grep telnet sed)

          for SOFTWARE in ${NEEDED_SOFTWARE_LIST[@]}; do
                  dpkg -l | grep -i $SOFTWARE | head -1 | if [[ "$(cut -d ' ' -f 1)" != "ii" ]]; then
                          echo -e "[ ${Red}FAILED ${RCol}]\t$SOFTWARE is NOT installed completely! Please install it...\n";
                          exit 1;
                  fi
          done
  # RedHat / CentOS
  elif [ -f /etc/redhat-release ] || [ "$LINUX_DISTRIBUTATION" == "RedHat" ] || [ "$LINUX_DISTRIBUTATION" == "CentOS" ]; then
          declare -a NEEDED_SOFTWARE_LIST=(bash rsync wget grep telnet sed)

          for SOFTWARE in ${NEEDED_SOFTWARE_LIST[@]}; do
                  if [[ "$(rpm -q $SOFTWARE)" == "package $SOFTWARE is not installed" ]]; then
                          echo -e "[ ${Red}FAILED ${RCol}]\t$SOFTWARE is NOT installed completely! Please install it...\n";
                          exit 1;
                  fi
          done
  else
          echo "[ ${Red}FAILED ${RCol}]\tYour system is currently not supported by this script.";
          exit 1;
  fi

我认为我的解决方案不是最好的。有人能调整它吗?提前谢谢!:)

提示:我声明变量“NEEDED_SOFTWARE_LIST”两次,因为我认为我将需要两个软件列表数组,因为某些发行版需要其他软件包。

1个回答

6

如果软件包已安装,为什么要执行一项庞大的测试,而不是简单地检查某些实用程序的可用性呢?

SCRIPTNAME="${0##*/}"

warn() {
    printf >&2 "$SCRIPTNAME: $*\n"
}

iscmd() {
    command -v >&- "$@"
}

checkdeps() {
    local -i not_found
    for cmd; do
        iscmd "$cmd" || { 
            warn $"$cmd is not found"
            let not_found++
        }
    done
    (( not_found == 0 )) || {
        warn $"Install dependencies listed above to use $SCRIPTNAME"
        exit 1
    }
}

checkdeps wget rsync realpath

然而,如果您想检查Debian上是否安装了软件包,请不要再使用这个噩梦般的方法。

dpkg -l | grep -i $SOFTWARE | head -1 | if [[ "$(cut -d ' ' -f 1)" != "ii" ]]; then

使用

if dpkg -l $SOFTWARE; then

1
比起我修补原版的尝试,这要干净得多。 - Floris
哈哈。这个解决方案真是太简洁了。:o 非常感谢! :) - user2966991
最后一个问题:第一行“SCRIPTNAME="${0##*/}""的意思是什么?这个解决方案适用于每个Linux发行版吗? - user2966991
1
@user2966991 “SCRIPTNAME="${0##*/}" 是一行经常出现在许多 Bash 脚本的开头之一的代码。它将包含脚本的文件的短名称放入变量中,该变量可以用于生成警告/错误的正确格式(就像这里)或打印使用说明等。它与你的问题没有任何关系。它只是因为我从我的一个真实脚本中复制了代码而出现在这里的。 - Dmitry Alexandrov
@user2966991 这个解决方案并不特定于操作系统。它是纯Bash编写的,甚至不需要GNU Coreutils。因此,它不仅适用于每个GNU发行版,也适用于安装了Bash的每个系统。 - Dmitry Alexandrov
啊,太棒了。谢谢! - user2966991

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接