运行脚本
#!/bin/bash
(
flock 9
# ... commands executed under lock ...
fuser -v /var/lib/dpkg/lock
apt-get -f --assume-no install
) 9>/var/lib/dpkg/lock
作为超级用户不会显示错误信息。但是如果有 egsynaptic
正在运行,apt-get
则会显示错误信息:“E: 无法获取锁 /var/lib/dpkg/lock - open (11: 资源暂时不可用)”。
答案1
dpkg
(反过来 apt)不用于flock(2)
锁定。检查所涉及的系统调用,似乎它们使用fcntl(2)
:
$ sudo strace -f -e trace=desc apt install foo |& grep -B2 F_SETLK
close(4) = 0
open("/var/lib/dpkg/lock", O_RDWR|O_CREAT|O_NOFOLLOW, 0640) = 4
fcntl(4, F_SETFD, FD_CLOEXEC) = 0
fcntl(4, F_SETLK, {l_type=F_WRLCK, l_whence=SEEK_SET, l_start=0, l_len=0}) = -1 EAGAIN (Resource temporarily unavailable)
close(4) = 0
来自这篇文章:
在 Linux 中,
lockf()
只是 的包装器fcntl()
,而flock()
锁是分开的(并且只适用于本地文件系统,不适用于 NFS 挂载)。也就是说,一个进程可以flock()
对文件拥有咨询性排他锁,而另一个进程对同一个文件拥有咨询性排他fcntl()
锁。两者都是咨询性锁,但它们不会交互。
因此,flock
无法有效地将其锁定在其他包管理命令上。(想想看……如果有效的话,那么后续命令apt-get
无论如何都会失败。)
/var/lib/dpkg/lock
我能想到的最简单的方法是在任务执行期间创建一个不可变的文件。
touch /var/lib/dpkg/lock
chattr +i /var/lib/dpkg/lock
或者您可以编写一个简短的 C 程序(或任何提供简单界面的语言fcntl
)fcntl
来像 dpkg 一样锁定它。