ローファイ日記

出てくるコード片、ぼくが書いたものは断りがない場合 MIT License としています http://udzura.mit-license.org/

HaconiwaでDockerのsshdコンテナを利用してみる

こんにちは。これは技術記事です。みなさんは、技術記事ですか?

まず、 Haconiwa の近況報告なんですが、この度 mruby で書き直し、ひとまず MRI 版と同じ程度の機能までは実装できました。

github.com

これに伴い、Linux用のバイナリを配布する形にインストール方法を変更しました。また、今後MRI版の開発(haconiwa-mri とプロジェクトをリネーム済みです)は積極的には行わない予定です。何か機能追加したい際は mruby 版の方へPRを!

(一応、MRI版のリリース記事は以下です)

udzura.hatenablog.jp


ということで、今日はこのmruby版のHaconiwaを用いて、Dockerのsshdコンテナを再利用してsshdを立ち上げてみる手順を紹介します。

続きを読む

mruby便利tips: 利用しているmgemのリビジョンを知りたい

mgemは、 mgem: 指定にしても github: 指定にしても基本的にgitリポジトリをチェックアウトして持ってくるようになっている。なので、チェックアウトした段階でのリビジョンが知りたいことがある。

build_config.rb に以下のようなモンキーパッチを書いておくと、

module MRuby
  module HookGemRevision
    def gem(gemdir, &block)
      gem = super(gemdir, &block)
      if File.exist? gem.dir + "/.git"
        print "#{gem.name}: revision="
        sh "git --git-dir #{gem.dir}/.git rev-parse HEAD"
      end
      gem
    end
  end

  class Build
    include HookGemRevision
  end
end

MRuby::Build.new do |conf|
  toolchain :gcc
  # ...
end

その時点でチェックアウトしている mgem のリビジョンを(可能な場合に)表示してくれて便利かもしれない。

$ rake
cd mruby && MRUBY_CONFIG=/Users/udzura/.ghq/github.com/udzura/mruby-argtable/build_config.rb rake all
mruby-argtable: revision=d0077ef2504be4cb3ae8e855dfe88a532fb6997b
mruby-dir: revision=0c3c538855dd15208d34fee96b13675e564bb4b6
CC    src/array.c -> build/host/src/array.o
CC    src/backtrace.c -> build/host/src/backtrace.o
CC    src/class.c -> build/host/src/class.o
CC    src/codedump.c -> build/host/src/codedump.o
CC    src/compar.c -> build/host/src/compar.o
CC    src/crc.c -> build/host/src/crc.o
...

(コアにこんな感じの機能が入ってもいい気がするが、どういうやり方があるか考え中...)

mruby-argtable というものを書いた

github.com

宜しくお願いします。こんな感じです。

t = Argtable.new
t.literal("v", "verbose", "You are verbose")
t.integer("c", "count", "<c>", "My count")
t.double("s", "seconds", "<t>", "My seconds")
t.string("n", "name", "<n>", "My name")

t.parse(["prog", "-c", "9999", "--verbose", "--name=udzura", "-s", "12.25"])

t["v"].count #=> 1, no value
t["c"].value #=> 9999
t["n"].value #=> "udzura"
t["s"].value #=> 12.25

t.glossry
# -v, --verbose             You are verbose
# -c, --count=<c>           My count
# -s, --seconds=<t>         My seconds
# -n, --name=<n>            My name

テストという名のサンプル もあります。

optparseのmruby移植もあったんですけど、せっかくなので練習も兼ねCの argtable をラップする奴を書いた。

今の所、mgemを入れる時に取得するようにしています。なんかリポジトリに最初から含めた方がいい気もしている。

mgem-listには申請中ですマージされました。→ Add mruby-argtable by udzura · Pull Request #179 · mruby/mgem-list · GitHub

# mgemの依存に追加する例。
MRuby::Gem::Specification.new('your-cli') do |spec|
  spec.bins = ["your-cli"]

  spec.add_dependency 'mruby-argtable', mgem: 'mruby-argtable'
  #...
end

mruby-cli 本体にはオプションパーサーは添付されていないので、組み合わせると幸せになるかも。

github.com

今の所、mrubyのHEADだと??な感じでテストが失敗するので、何かをします。 (mruby-cliがデフォルトで使うっぽい) 1.2.0 ならOK。


mruby-argtable のAPI、最初は元のCのインタフェースに忠実な感じで、こうだった(一応今も動く)けど、

a = Argtable::Literal.new("a", "aaa", "aaa aaa")
b = Argtable::Literal.new("b", "bbb", "bbb bbb")
t = Argtable.new
t.push a; t.push b
t.compile

t.parse(["prog", "-a"])
a.count

あまりに、罠が多そう(例えばcompile必ず呼ぶところとか)なので、必要なものは暗黙に呼んだりする今の形に変更した。

Rubyらしさ」というか「Rubyとして使いたいか」みたいな設計の感じは、CRubyと一緒な感じがする。

IPC Namespaceをまたいだプロセス間で、pipeでやりとりする。mrubyで。

Introduction to Linux namespaces - Part 2: IPC | Yet another enthusiast blog!

こういうブログ記事があって、元記事はC言語なんだけど、これと同じことをmrubyでもやってみたサンプル。なお元記事は clone(2) だけど今回はforkしてから unshare(2) している。clone未実装なんで。。

reader, writer = IO.pipe
puts " - Hello ?"

p = Process.fork do
  Namespace.unshare(Namespace::CLONE_NEWUTS | Namespace::CLONE_NEWIPC)

  writer.close
  reader.read # blocking

  system "hostname 'In-Namespace'"
  puts " - World !"
  Exec.exec "/bin/bash"
end

10.times do
  sleep 0.5
  print "."
end
puts
writer.close

Process.waitpid p

(build_configはこんな感じで)

MRuby::Build.new do |conf|
  toolchain :gcc
  conf.gembox 'full-core'
  conf.gem github: 'haconiwa/mruby-exec'
  conf.gem github: 'iij/mruby-process'
  conf.gem github: 'iij/mruby-io'
  conf.gem github: 'haconiwa/mruby-namespace'
end

めちゃくちゃハマっていたのは、forkするんでwriter FDが親子プロセスともにコピーされるため、両方クローズしないとreadでブロックし続けるよね...というところ...。

[vagrant@localhost vagrant]$ sudo ./mruby/bin/mruby sample/ipc_ns.rb 
 - Hello ?
..........
 - World !
[root@In-Namespace vagrant]# 

unshare(Namespace::CLONE_NEWIPC) は成功しているが、プロセス間でやりとりをやっていけているようだ。 (mruby はこういう挙動をサクッと試せて便利)


Linuxプログラミングインタフェース

Linuxプログラミングインタフェース

とにかくこれを読まないとダメな気がする、このままでは俺はダメになる気がするこの頃。