システムにインストール済みの全パッケージを依存関係に持つdebファイルの自動生成

ubuntuシステムのバックアップの一環として、定期的に dpkg-query -lからapt-get install ...で使うパッケージ名一覧をとり出し、ファイルで保存してた。

dpkg-query -l | ruby -ane 'puts $F[1] if $F[0] == "ii"' > installed_packages.txt

依存関係のみを列挙したdebを作る - walf443's blog でequivsという、簡単にdebファイルを生成できるツールがあるのを知った。Dependsに必要なパッケージを指定することで、生成したパッケージをインストールすることでその構成を再現できるようになる。

そこで、上記パッケージリストをDependsに指定したパッケージを作成するスクリプトgen-equivs.rb を書いてみた。ついでにhttpやローカルのapt lineのためのPackages.gzも生成するようにしている。

gen-equivs.rb

#!/usr/bin/ruby

# gen-equivs.rb:
#
# Generating the package for system installed packages at once
# Then make apt site for them
# - required deb packages: equivs, apt-utils

#Dir.chdir "."
version = Time.now.strftime "%Y%m%d.%H%M"
name = ARGV[0] || "dependency-package-for-mymachine"
description = "package for installing current installed packages"
site = "file:#{Dir.pwd}"

pkgs = IO.popen("dpkg-query -l").readlines.map(&:split).select{|l|
  l[0] == 'ii' and l[1] != name
}.map{|l| l[1]}

equivis = %{
Section: misc
Priority: optional
Standards-Version: 3.6.2

Package: #{name}
Version: #{version}
Depends: #{pkgs.join(", ")}
Description: #{description}
}

open(name, "w") do |f|
  f.write(equivis)
end

# equivs see: http://d.hatena.ne.jp/walf443/20090413/1239639630
system "equivs-build #{name}"

# local apt see: http://debian.fam.cx/index.php?AptGet#content_1_49
system "apt-ftparchive packages . | gzip -c9 > Packages.gz"

puts %{[usage for the generated package]
add apt line it to "/etc/apt/sources.list":

  deb #{site} ./

and then:

  apt-get update && apt-get install --force-yes -y #{name}
}

使い方: package & apt site生成

適当なディレクトリで上記スクリプトを実行してください。

mkdir ~/public_html/equivs
cd ~/public_html/equivs
gen-equivs.rb

すると、

  • dependency-package-for-mymachine_20090416.1736_all.deb (のようなファイル)
  • Packages.gz

ができます。これをバックアップしておきます。

使い方: リカバリ

バックアップからパッケージを入れなおすときは、上記ディレクトリを素のマシンに回復させます。そして、/etc/apt/sources.listに

deb file:/home/xxxx/public_html/equivs ./

のように追加し、

apt-get update && apt-get install --force-yes -y dependency-package-for-mymachine

と実行すれば、依然の環境になったパッケージをすべて自動で入れてくれるはずでしょう。

感想

スマートにできるかなと思って作ってみたんだけど、ただバックアップリカバリのためだとapt-get install に指定するパッケージ名リストさえあればいいのであんまり意味ないかも。

だけど、同構成のサーバを複数用意するときとかで、cronなどによって自動で構成の同期をとるときなんかでは楽にできるのでしょうか。