我正在编写一个脚本来执行一些apt
命令,但我遇到了apt/dpkg
数据库被锁定的潜在问题,因此我的脚本无法使用。我想/var/lib/dpkg/lock
在做任何事情之前检查锁定文件(即),就像apt
它运行它的命令一样,但我不知道如何apt
执行锁定。
锁定文件始终存在,并且apt-get
不会对该文件进行群集操作。否则将如何检查它是否在使用中?从strace
我看到apt-get
打开文件,但就是这样。在我的脚本中,我可以在打开文件的同时apt-get
打开它。
好吧,我以为这里会有一个简单的答案,但我找不到任何东西。首先,您是否 100% 确定锁定文件始终存在?尝试跑步
lsof /var/lib/dpkg/lock
Run Code Online (Sandbox Code Playgroud)
以 root 身份查看是否有任何进程打开了它。
从我读过的内容来看,apt-get 做了一个 fcntl 锁,但我还没有查看代码进行验证。我想这会解释为什么文件一直在那里,apt 只是根据需要锁定它。
只在脚本运行时检查进程列表,如果 apt 同时运行则退出怎么样?这足以供您使用吗?
看起来这个人和你走的路一样,但没有取得多大成功。
小智 5
我来到这里寻找类似于 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
Run Code Online (Sandbox Code Playgroud)
我发现 apt 使用的是 fcntl。由于我使用 Ruby 作为脚本语言,因此我必须创建自己的函数来查找锁。这样做的原因是 Ruby 没有完全实现 fcntl 函数。它只提供函数调用和常量。构建集群结构以及如何传递它们的能力被遗漏或没有记录。
这是我发现的有关此内容的列表。
这是我最终编写的函数:
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
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
7286 次 |
最近记录: |