「一般ユーザー権限で chroot 環境下で外部コマンドを実行する」というコードを脳に優しく書けるようにするために、 ensure
節を使って後始末のことを心配しないメソッドをつくる。
run_with_chroot - chroot 環境下で外部コマンドを実行する
「一般ユーザー権限で chroot 環境下で外部コマンドを実行する」用。なお、 mount
, umount
, chroot
は sudoers で使用を許可されているものとする。
run_with_chroot.rb
def run_with_chroot(root, command)
dirs_for_chroot = %w[bin dev etc lib lib64 proc tmp usr var]
begin
Dir.mkdir(root) unless Dir.exists?(root)
dirs_for_chroot.each do |dir|
Dir.mkdir("#{root}/#{dir}") unless Dir.exists?("#{root}/#{dir}")
system("sudo mount -o bind #{dir} #{root}/#{dir}")
end
system("sudo chroot #{root} #{command}")
ensure
dirs_for_chroot.each do |dir|
system("sudo umount #{root}/#{dir}")
end
end
end
# chroot 環境下で /hoge というファイルを作成すると、
# chroot 環境外では /var/root/hoge というファイルができる
run_with_chroot('/var/root', 'touch /hoge')
chroot
環境をお膳立てするために、事前に mount
しておいて事後に umount
する必要があるが、これを毎回書くのはしんどいし、途中でプログラムが例外を投げて umount
しないまま落ちたりすると面倒なことになる。そこで umount
するコードを ensure
節に置くことで、後始末用のコードが確実に実行されるようにする。
プログラムを root
権限で動かせるなら system("chroot /path/to/root command")
の代わりに Dir.chroot
を使うとなお良い。そうすれば with_chroot
というブロック付きメソッドを定義して、より読みやすいコードが書けるだろう。