如何检查 apt 锁文件是否被锁定?

如何检查 apt 锁文件是否被锁定?

我正在编写一个脚本来执行一些apt命令,但我遇到了apt/dpkg数据库被锁定的潜在问题,因此我的脚本被释放。我想在执行任何操作之前检查锁定文件(即/var/lib/dpkg/lock),就像apt在运行命令时一样,但我不知道如何apt执行锁定。

锁定文件始终存在,并且apt-get不会对文件进行锁定。否则,它如何检查是否正在使用?从strace我看到的文件中可以看到apt-get文件已打开,但仅此而已。在我的脚本中,我可以在打开文件的同时apt-get打开它。

答案1

好吧,我以为这里有一个简单的答案,但我什么也找不到。首先,你 100% 确定锁文件始终存在吗?尝试运行

lsof /var/lib/dpkg/lock

以 root 身份查看是否有任何进程已打开它。

据我所知,apt-get 会执行 fcntl 锁定,但我还没有查看代码来验证。我想这可以解释为什么文件一直在那里,apt 只是在需要时才锁定它。

如果脚本运行时只检查进程列表,如果 apt 同时运行,则退出,这样行吗?这样能满足您的使用要求吗?

好像这个人走了和你同样的路,但没有取得多大成功。

答案2

我来这里是为了寻找一个类似于 gondoi 最终使用的解决方案,但是用 Python 而不是 Ruby 编写。下面的方法似乎效果很好:

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

答案3

从 shell 脚本(参见羊群(1)):

flock --timeout 60 --exclusive --close /var/lib/dpkg/lock apt-get -y -o Dpkg::Options::="--force-confold" upgrade
if [ $? -ne 0 ]; then
  echo "Another process has f-locked /var/lib/dpkg/lock" 1>&2
  exit 1
fi

答案4

我发现 apt 正在使用 fcntl。由于我使用 Ruby 作为脚本语言,因此我必须创建自己的函数来查找 lock。原因是 Ruby 并未完全实现 fcntl 函数。它仅提供函数调用和常量。构建 flock 结构以及如何传递它们的能力被遗漏或未记录。

这里是列表我发现有人在谈论那件事。

这是我最终编写的函数:

def flocked? &block
  flockstruct = [Fcntl::F_RDLCK, 0, 0, 0, 0].pack("ssqqi")
  fcntl Fcntl::F_GETLK, flockstruct
  status = flockstruct.unpack("ssqqi")[0]
  case status
    when Fcntl::F_UNLCK
      return false 
    when Fcntl::F_WRLCK|Fcntl::F_RDLCK
      return true
    else
      raise SystemCallError, status
  end
end

相关内容