mojavy.com

mustache基礎文法最速マスター

October 01, 2013 at 12:08 AM | categories: ruby, mustache |

mustache

mustacheはシンプルなテンプレートエンジンなので本家の英語マニュアル mustache(5) を見ても大したことはないですが、日本語情報の需要もそれなりにあると思うのでまとめておきます。

以下の内容はrubygemのmustache-0.99.4で確認しています。 他の言語の場合は適宜置きかえてください。

目次

変数の展開

{{name}}のように2つのブレースで囲ったタグは、nameという名前のキーの値でおきかえられます。

対応するキーが見つからなかった場合はデフォルトでは空文字になります。

Mustache.render("Hello, {{world}}!", world: "mustache") # => "Hello, mustache!"
Mustache.render("{{no_such_key}}") # => ""

変数のエスケープ

デフォルトではHTMLエスケープが有効になります。アンエスケープされたHTMLが使いたい場合は{{{name}}}のように3つのブレースで囲います。

Mustache.render("{{html}}",  html: "<b>GitHub</b>") # => "&lt;b&gt;GitHub&lt;/b&gt;"
Mustache.render("{{{html}}}", html: "<b>GitHub</b>") # => "<b>GitHub</b>"

条件分岐

{{#name}} ... {{/name}}のように、2つのタグに#/をそれぞれつけたタグで囲われたブロックはセクションといいます。

セクションのキーに対応する値にbool値を渡せばif文のような使い方ができます。 #のかわりに^をつかうと真偽を反転できます。

template = <<DOC
{{#condition}}
It is true.
{{/condition}}
{{^condition}}
No not true.
{{/condition}}
DOC
Mustache.render(template, condition: true) # => "It is true.\n"
Mustache.render(template, condition: false) # => "No not true.\n"

ループ

セクションのキーに対応する値に配列を渡した場合は、それぞれの要素を引数として中のブロックが繰り返し評価されます。

template = <<DOC
{{#animals}}
{{name}}
{{/animals}}
DOC
data = {animals: [{name: "cat"}, {name: "dog"}, {name: "pig"}]}
Mustache.render(template, data) # => "cat\ndog\npig\n"

無名関数 (Lambda)

セクションのキーに対応する値に呼び出し可能なオブジェクトを渡した場合は、そのブロック内のテキストを引数として実行され、その返り値が結果として出力されます。

template = <<DOC
{{#proc}}
mojavy is bad
{{/proc}}
DOC
Mustache.render(template, proc: ->text{text.gsub(/bad/, 'nice')}) # => "mojavy is nice\n"

コメント

!をつけるとコメントになります

Mustache.render("Comment here: {{! ignore me }}") # => "Comment here: "

まとめ

mustacheの基本的な機能について簡単なサンプルコードとともに解説しました。 ここではrubyのmustacheを使用しましたが、他の言語でも同様の機能が使えます。 一部の機能については省略しているので、より詳細な情報については本家ドキュメントを参照してください。



debianパッケージをchefで削除する場合はpurgeを使う方がよい

September 10, 2013 at 07:39 PM | categories: chef, ruby, debian |

apt-getコマンドにはパッケージを削除するためのコマンドが2種類ある

  • remove: パッケージを削除するが設定ファイルはそのまま残す
  • purge: パッケージを削除するとき設定ファイルも削除する

chefをつかっているということは設定ファイルもchefで管理しているはずなので、設定ファイルを残す必要はない。 さらに、依存で入ったパッケージも一緒に削除されるように、options "--auto-remove"などとしてやるとよい。

ゴミは混乱の元なので早めに消すべし。



chef soloでAuthenticationFailedといわれたときの対応

September 09, 2013 at 08:43 PM | categories: chef, ruby |

公開鍵認証なホストに対してパスフレーズ入力無しでsshログインができるにもかかわらず、

$ knife solo cook myhost
Running Chef on myhost...
Checking Chef version...
Enter the password for username@myhost:
ERROR: Net::SSH::AuthenticationFailed: username

のようにいわれてchef soloの実行に失敗してしまうときがある。

パスフレーズ入力無しでsshできたということは、普通は以下のうちの少くとも1つは満たされている。

  1. ssh-agentに対象の秘密鍵が登録されている
  2. デフォルトパス($HOME/.ssh/id_rsa とか)に対象のパスフレーズ無し秘密鍵が保存されている
  3. ssh_configでパスフレーズ無し秘密鍵を指定している

それなのにAuthenticationFailed失敗してしまうのは、Net:SSHがデフォルトでは公開鍵認証を試行しない場合があるため。 1 これを回避するには、ssh_configでPubkeyAuthentication yesを明示すればよい。

なお、Net::SSHがどのような動きをしているかは以下のスニペットを試すとよい。

require 'net/ssh'
Net::SSH.start("myhost", "username", :verbose => :debug) {|x| p x }

備考

使ったのは以下のバージョン

  • chef: 11.6.0
  • knife-solo: 0.3.0

  1. この挙動はknife soloコマンドに-iオプションを渡しても変わらなかった。 



ptraceを駆使してscreenifyっぽいことをするreptyrがすごい

July 12, 2013 at 07:15 PM | categories: C, linux |

reptyrというおもしろいものをみつけたのでご紹介

reptyr とは

reptyrとは"re-ptying"するためのプログラムで、起動中のプロセスを新しい別のターミナルにもってくることができます。 例えば、うっかりscreenやtmuxの外で起動してしまった長い時間のかかるバッチ処理を、起動したままscreenの中にもってくることができます。

https://github.com/nelhage/reptyr

使い方

$ reptyr PID

現在のターミナル内にもってきたいプロセスのpidを引数にします。 attach後は、そのプロセスの入出力は^Cや^Zも含めて新しいターミナル側を向きます。

それscreenifyでできるよ

screenifyと呼ばれるスクリプトが昔からあって、それはgdbつかって似たようなことをやってるらしいです。 でもreptyrならもっとうまくできます。

例えば従来のscreenifyには以下のような問題がありました。

  • screenifyでattachしたプロセスは、元のターミナルから入力をうけつけてしまう
  • ncursesをつかってるプログラムをscreenifyすると、そのプログラムはwindowのリサイズがとれなくなる
  • screenifyした新しいターミナルでは^Cがきかない

reptyrはこういった問題を全部解決できます。

移植性

reptyrは対象プロセスを操作するのにptraceをつかっているのでLinuxに強く依存しており、Linuxだけをサポートしています。 SolarisやBSDに移植することも技術的には可能ですが、現状はプラットフォーム固有の部分を抽象化するようにはデザインされていないようです。

reptyrは現状ではi386, x86_64, ARMをサポートしています。他のアーキテクチャへの対応はarch以下に対応コードを追加すれば比較的容易です。

ptrace_scope on Ubuntu Maverick and up

Ubuntu Maverick以降ではptraceの機能がデフォルトで無効になっています。 以下コマンドで一時的に有効にできます。

$ echo 0 > /proc/sys/kernel/yama/ptrace_scope

rootで/etc/sysctl.d/10-ptrace.confを編集すると永続的に変更できます。またptrace_scopeに関する詳細な説明もここに書いてあります。

どうやってるの?

ソースを追ってみたところ以下のような処理をしているようです。

  1. reptyrプロセス側でptyをつくる
  2. attach対象のプロセスのttyのtermios設定をptyにコピーする
  3. ptraceで対象プロセスをattachしてレジスタ内容を一旦退避
  4. attachしたプロセス側でmmapし、そこにreptyrプロセス側でつくったptyをコピー
  5. attachしたプロセス側でコピーしたptyをopenし、setsid〜ioctlでそこに制御端末を割り当てる
  6. attachしたプロセス側でdup2して入出力をttyに向ける
  7. レジスタ内容を復元、後始末してptraceをdetach

reptyrのキモは5の制御端末をptyに割り当てるところで、これをすることによって従来のscreenifyの問題が回避できます。

しかし、単にioctlTIOCSCTTYするだけではうまくいかないのでちょっとしたトリックが必要です。詳細はhttp://blog.nelhage.com/2011/02/changing-ctty/ に解説があります。 reptyrの作者は自力でこの方法を思いついたそうですが、同様のテクニックは injcodeneercs でも使用されているそうです。

reptyrってどう読むの?

repeaterのように発音してもいいけど曖昧なのでre-P-T-Y-er (たぶんリ・ピーティーワイアー)のように発音してもよいそうです。

制約

  • backgroundにしたときは前のターミナルでbgやfgを実行する必要があります。background制御はshellがやっているので、これを直すにはshell側に手をいれる必要があります。
  • 現状では子プロセスがあるプロセスはattachできません

類似のもの

参考

まとめ

reptyrは1000行くらいの小さなプログラムですが、なかなかおもしろいハックだと思うので興味がある方はソースを読んでみて下さい。



C言語でtuple

July 10, 2013 at 09:02 PM | categories: C, programming |

Cをつかってるとtupleっぽいものがあれば便利なのに、と思うときが時々あります。

別にtupleなんてなくても

typedef struct {
   char *s;
   int *i;
} tuple;

のようにして構造体をつかえばいいのですが、必要になるたびにこれをするのはちょっとめんどくさいですよね。

というわけで色々試行錯誤してみたところ、以下のようにしてunionの配列にするというのがそこそこ便利だったので紹介します。

以下は使用例です。

#include <stdio.h>

typedef union {
    void *p;
    char *s;
    int i;
    char c;
} tuple_u;
typedef tuple_u tuple[2];

int main(int argc, char *argv[]) {
    tuple t = { { .s = "hoge" }, { .i = 123 } };

    printf("%s, %d\n", t[0].s, t[1].i);
    return 0;
}

C99のdesignated initializerをつかえば初期化もまあそこそこ書きやすいし、型の組み合わせもある程度柔軟にできます。

C++ではなくあえてCをつかうような人の多くは独自のコンテナライブラリのようなものをもってると思いますが、上記のようなtupleがあれば便利な場面は結構あるのではないかと思います。



About Me

pic
mojavy

Recent posts






Categories



Badges