最近お世話になることがあったので。
FreeBSD は、cron から起動される periodic で、
いくつかシステムにとって重要なデータがバックアップされています。
/var/backups にいろいろ置いてあって、aliases だとか、
起動パーティションのデータとか、gpart の結果とか。
master.passwd とか、pkg のデータベースなどもあります。
それぞれ、periodic の daily で走るスクリプトによってバックアップが行われていて、
現在の状態が最新のバックアップと異なっていれば、
コピーして圧縮を行う感じでやってるみたいです。
その中でも最近お世話になったのが pkg のデータベース。
pkg のインストール済み一覧とかは、/var/db/pkg/local.sqlite にあるのですが、
ディスクのエラーで破損してしまいました。
そんなときの復旧手順です。
ネットで検索すると、pkg backup を使うみたいな話があったりしますが、
/var/backups に置いてあるのは SQLite の生データなので、これでは復元できません。
具体的には以下のコマンドで復旧します。
$ sudo mv /var/db/pkg/local.sqlite{,.bak} $ xzcat var/backups/pkg.sql.xz.7 | sudo pkg shell ".read /dev/stdin"
1行目は元の SQLite ファイルをリネームして保存してます。
破損していることが分かっているなら別に削除でもいいのですがなんとなく。
2行目が復元のコマンドです。
xz で圧縮されているので、xzcat で伸張したデータを stdout に流します。
そして、pkg shell は SQLite の対話環境を起動するサブコマンドです。
パイプで流し込んだデータは stdin から読み込めるので、/dev/stdin をファイルとして開いて、
そこからデータを読み込みます。.read は読み込んだ SQL を実行する命令です。
なお、当然ながら SQLite 対話環境は sudo 権限で起動する必要があります。
ポイントとしては、パイプで流し込んだデータは /dev/stdin をファイルとして開くと、
そのまま読み込める。というのは意外と汎用性が高そう?と思ったりしました。
大抵のコマンドは入力ファイル名に - を指定すると stdin から読んでくれたりしますが。
たまにそういう気が利かないツールでも、/dev/stdin を読めば OK なのは便利です。
ただし、/dev/stdin はシークができないので、1pass で読み込めるツール限定ですが。