これは何?
CentOSやRockyLinuxでrpmdbが壊れてしまい困ったことがある人は多いのではないでしょうか?
この状態からの復旧方法はインターネットを調べるとたくさん見つかるのですが、あえてこのrpmdbが壊れた状態を作り出す方法についてはあまり見かけなかったので方法を紹介します。
復旧方法
典型的な復旧方法は以下のコマンドを実行することです。(これで復旧しないこともあります)
sudo rpm --rebuilddb
他にもいろいろなケースでの復旧方法があるようですが、この記事では省きます。
rpmdbの壊し方(本題)
前述のような復旧手段に関しての文書はインターネット上に多数あるのですが、rpmdbを壊す方法についてはあまり情報がなかったので、試した方法を紹介します。
yumコマンドをkillする
まずはRockylinuxコンテナを用意します
$ docker run -it --rm rockylinux:8 bash
以下のようなスクリプトを用意します
yum list # yumリポジトリの情報をキャッシュさせます
for x in `seq 10000`; do
yum list &
pid=$!
sleep 0.$(($RANDOM%10)) # ランダム時間待ったのちにkillします
kill -9 $pid
echo "killed"
done
これをルート権限で動作させるとしばらくするとrpmdbが壊れます
error: rpmdb: BDB0113 Thread/process 618/140670157765504 failed: BDB1507 Thread died in Berkeley DB library
error: db5 error(-30973) from dbenv->failchk: BDB0087 DB_RUNRECOVERY: Fatal error, run database recovery
error: cannot open Packages index using db5 - (-30973)
error: cannot open Packages database in /var/lib/rpm
Error: Error: rpmdb open failed
rpmdb-breaker.sh: line 2: 1552 Killed yum list
rpmdb-breaker.sh: line 6: kill: (1554) - No such process
rpmコマンドをkillする
準備は上記と同様ですが、以下のようなスクリプトでも壊れます
yumではなくrpmコマンドにしていることと、killまでのタイミングを少し調整しています。
for x in `seq 10000`; do
rpm -qa &
pid=$!
sleep 0.0$(($RANDOM%10))
kill -9 $pid
echo "killed"
done
最後に
rpmdbをあえて壊す、というのはあまり役立つことはなさそうですが、この状態に陥った時に復旧する手順書や、スクリプトを作る際には便利かと思います。
他にも壊すケースがあるかもしれないので、ご存知の方はコメントなどで教えて欲しいです。