2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

後始末用のコードの実行を ensure 節で保証する

Last updated at Posted at 2012-05-19

「一般ユーザー権限で 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 というブロック付きメソッドを定義して、より読みやすいコードが書けるだろう。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?