检测/避免多个apt-get / dpkg安装

时间:2014-05-12 13:39:43

标签: bash ubuntu debian apt dpkg

我有新用户运行的脚本来配置他们的系统,基本上是一个带有大for循环的bash脚本,如下所示:

DEBCOUNT=${#DEBS[@]}
for (( i=0; i<${DEBCOUNT}; i++ ));
do
  PACKAGE=${DEBS[$i]}
  dpkg -s ${PACKAGE} >> /dev/null
  if [ ${PIPESTATUS[0]} -ne 0 ]; then
    echo -n  =========== Installing ${PACKAGE}
    echo "  ( $((${i}*100/${DEBCOUNT}))% )"

    apt-get -qq install -y --force-yes  ${PACKAGE}
    if [ $? -ne 0 ]; then
      echo ERROR: Failed to install required package ${PACKAGE}
      exit 1
    fi
  else
    echo -n  =========== Skipping ${PACKAGE}
    echo "  ( $((${i}*100/${DEBCOUNT}))% )"
  fi
done

DEBS数组是要在新系统(主要是编译器和编辑器)上安装的50个包的列表。

它很有效,除非某些系统进程启动并在后台开始更新APT数据库..然后它失败并显示dpkg: error: dpkg status database is locked by another process

是否有优雅/健壮的方法来避免此错误?通过检测它并以某种方式等待它自由,或者通过首先防止它。

响应

  • 我不想删除锁定文件。试图安装我的东西和系统同时做的任何事情都将不可避免地破坏一些东西。
  • 我无法在开始时进行单一检查,因为我看到的似乎表明其他进程正在进行我想要的那种等待,然后跳进去我的两个apt-get之间。
  • 这不是一个锁定的进程。有时候我认为它是ubuntu软件更新程序,有时候我认为它是cron工作大{{1} }}。

3 个答案:

答案 0 :(得分:2)

我带着同样的问题来到这里,想要检测apt-getdpkg使用的锁定文件是否被锁定,不管这是否是最相关的测试(它在我的身上)案件)。我最终使用了以下Python代码片段:

import fcntl

def is_dpkg_active():
    """
    Check whether ``apt-get`` or ``dpkg`` is currently active.

    This works by checking whether the lock file ``/var/lib/dpkg/lock`` is
    locked by an ``apt-get`` or ``dpkg`` process, which in turn is done by
    momentarily trying to acquire the lock. This means that the current process
    needs to have sufficient privileges.

    :returns: ``True`` when the lock is already taken (``apt-get`` or ``dpkg``
              is running), ``False`` otherwise.
    :raises: :py:exc:`exceptions.IOError` if the required privileges are not
             available.

    .. note:: ``apt-get`` doesn't acquire this lock until it needs it, for
              example an ``apt-get update`` run consists of two phases (first
              fetching updated package lists and then updating the local
              package index) and only the second phase claims the lock (because
              the second phase writes the local package index which is also
              read from and written to by ``dpkg``).
    """
    with open('/var/lib/dpkg/lock', 'w') as handle:
        try:
            fcntl.lockf(handle, fcntl.LOCK_EX | fcntl.LOCK_NB)
            return False
        except IOError:
            return True

答案 1 :(得分:1)

正确的解决方案是使用虚拟包替换您的复杂脚本,在您要安装的所有其他包中Depends:

equivs包是构建这样一个虚拟包的简单方法(虽然起初不是很直观)。

顺便说一下,这不是一个临时的黑客行为;这就是例如Debian build-essential包引入了整个构建链。

答案 2 :(得分:0)

@ tripleee的答案是最好的答案,但如果由于某种原因你不能这样做(我知道在一些罕见的情况下这是真的 - 因为它发生在我们身上),正确的事情是发出一个命令,而不是使用循环:

apt-get -qq install -y --force-yes $DEBS