我有新用户运行的脚本来配置他们的系统,基本上是一个带有大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
之间。cron
工作大{{1} }}。答案 0 :(得分:2)
我带着同样的问题来到这里,想要检测apt-get
和dpkg
使用的锁定文件是否被锁定,不管这是否是最相关的测试(它在我的身上)案件)。我最终使用了以下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