web-dev-qa-db-ja.com

flockが使用されていても、aptがエラーメッセージを表示しないのはなぜですか?

実行中のスクリプト

#!/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

スーパーユーザーはエラーメッセージを表示しません。しかし、例えばsynaptic実行中、apt-getはエラーメッセージを表示します:「E:ロックを取得できませんでした/ var/lib/dpkg/lock-オープン(11:リソースが一時的に利用不可)」。

4
jarno

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

そして this SO post :から

Linuxでは、lockf()fcntl()の単なるラッパーですが、flock()ロックは独立しています(また、NFSマウントではなく、ローカルファイルシステムでのみ機能します)。つまり、1つのプロセスがファイルに対してアドバイザリーの排他的なflock()ロックを持ち、別のプロセスがその同じファイルに対してアドバイザリーの排他的なfcntl()ロックを持ちます。どちらもアドバイザリロックですが、相互作用しません。

したがって、flockは、他のパッケージ管理コマンドに対してロックするのに効果的ではありません。 (考えてみてください...もしそうなら、その後のapt-getはとにかく失敗するでしょう。)


私が考えることができる最も簡単な方法は、タスクの期間中に不変の/var/lib/dpkg/lockファイルを作成することです。

touch /var/lib/dpkg/lock
chattr +i /var/lib/dpkg/lock

または、fcntlを使用してdpkgのようにロックする短いCプログラム(またはfcntlへの簡単なインターフェースを提供する任意の言語)を作成できます。

2
muru