NetBSDの/bin/shでコマンドがexecve(2)されるまでの流れを追いかけてみた

NetBSD/bin/shでコマンドがexecve(2)されるまでの流れを追いかけてみた

技評×オングスこんなシェルスクリプトは書いちゃダメだ!にてシェル上でコマンドを実行する際のユーザランドからカーネルまでの流れが説明されていました。

ちょっと興味が出てきたので、NetBSD/bin/shでコマンドを実行した場合のコマンド入力からexecve(2)までの流れをソースコードレベルで追いかけてみました。

NetBSDソースコードにおける/bin/shの場所

NetBSDソースコードは、ユーザランド/カーネル共に/usr/srcの下に置かれます。ユーザランドのコマンドは/usr/src/<コマンドのパス>の位置に用意されており、/bin/shの場合は/usr/src/bin/shソースコードのあるディレクトリになります。

$ which sh
/bin/sh
$ cd /usr/src/bin/sh
$ ls
CVS/            error.h         jobs.h          mktokens        redir.h
Makefile        eval.c          machdep.h       myhistedit.h    sh.1
TOUR            eval.h          mail.c          mystring.c      shell.h
USD.doc/        exec.c          mail.h          mystring.h      show.c
alias.c         exec.h          main.c          nodes.c.pat     show.h
alias.h         expand.c        main.h          nodetypes       syntax.c
arith.y         expand.h        memalloc.c      options.c       syntax.h
arith_lex.l     funcs/          memalloc.h      options.h       trap.c
bltin/          histedit.c      miscbltin.c     output.c        trap.h
builtins.def    init.h          miscbltin.h     output.h        var.c
cd.c            input.c         mkbuiltins      parser.c        var.h
cd.h            input.h         mkinit.sh       parser.h
error.c         jobs.c          mknodes.sh      redir.c

main()からexecve(2)までの流れ

/bin/shを実行し、ユーザがコマンドを入力・実行する場合は、以下の関数を通過しています(細々とした関数は除き、主要な関数のみ抽出しています)。

  • /usr/src/bin/sh/main.c:main()
    • /usr/src/bin/sh/main.c:cmdloop()
      • /usr/src/bin/sh/eval.c:evaltree()
        • /usr/src/bin/sh/eval.c:evalcommand()
          • /usr/src/bin/sh/jobs.c:forkchild()
          • /usr/src/bin/sh/exec.c:shellexec()
            • /usr/src/bin/sh/exec.c:tryexec()
              • execve(2)

main()から順に追いかけてみます。

main()

何やら不穏なコメントがありますが、単純に/bin/shを起動してキーボードからコマンドを入力する場合は、cmdloop()に入って行くようです。

/usr/src/bin/sh/main.c:
 95 /*
 96  * Main routine.  We initialize things, parse the arguments, execute
 97  * profiles if we're a login shell, and then call cmdloop to execute
 98  * commands.  The setjmp call sets up the location to jump to when an
 99  * exception occurs.  When an exception occurs the variable "state"
100  * is used to figure out how far we had gotten.
101  */
102
103 int
104 main(int argc, char **argv)
105 {
...中略...
218         if (sflag || minusc == NULL) {
219 state4: /* XXX ??? - why isn't this before the "if" statement */
220                 cmdloop(1);
221         }

cmdloop()では、255行目のparsecmd()の戻り値からEOFの入力の有無を判定し、EOFでなければevaltree()を呼んでいます。

/usr/src/bin/sh/main.c:
230 /*
231  * Read and execute commands.  "Top" is nonzero for the top level command
232  * loop; it turns on prompting if the shell is interactive.
233  */
234
235 void
236 cmdloop(int top)
237 {
...中略...
245         for (;;) {
...中略...
255                 n = parsecmd(inter);
256                 /* showtree(n); DEBUG */
257                 if (n == NEOF) {
258                         if (!top || numeof >= 50)
259                                 break;
260                         if (!stoppedjobs()) {
261                                 if (!Iflag)
262                                         break;
263                                 out2str("\nUse \"exit\" to leave shell.\n");
264                         }
265                         numeof++;
266                 } else if (n != NULL && nflag == 0) {
267                         job_warning = (job_warning == 2) ? 1 : 0;
268                         numeof = 0;
269                         evaltree(n, 0);
270                 }

単純なコマンド実行の場合、evaltree()内の301行のcase文が実行されます。

/usr/src/bin/sh/eval.c:
 214 /*
 215  * Evaluate a parse tree.  The value is left in the global variable
 216  * exitstatus.
 217  */
 218
 219 void
 220 evaltree(union node *n, int flags)
 221 {
...中略...
 235         switch (n->type) {
...中略...
 293         case NNOT:
...中略...
 297         case NPIPE:
...中略...
 301         case NCMD:
 302                 evalcommand(n, flags, NULL);
 303                 do_etest = !(flags & EV_TESTED);
 304                 break;

マクロ定数NCMDはnodes.hで定義されています。nodes.hはmake時に生成され、元になる定義はファイルnodetypesにあり、NCMDについては"a simple command"というコメントがあります。

nodetypesにはNCMDの他に論理演算子やパイプに関する定義があり、evaltree()内のcase文でNNOTやNPIPEをチェックしています。

$ grep NCMD *.h
nodes.h:#define NCMD 1
$ grep -A1 'create.*nodes\.h' my_make.log
#    create  sh/nodes.h
AWK=awk  SED=sed /bin/sh mknodes.sh nodetypes nodes.c.pat /home/fpig/work/sh
$ grep ^N nodetypes
NSEMI nbinary                   # two commands separated by a semicolon
NCMD ncmd                       # a simple command
NPIPE npipe                     # a pipeline
NREDIR nredir                   # redirection (of a complex command)
NBACKGND nredir                 # run command in background
NSUBSHELL nredir                # run command in a subshell
NAND nbinary                    # the && operator
NOR nbinary                     # the || operator
NIF nif                         # the if statement.  Elif clauses are handled
NWHILE nbinary                  # the while statement.  First child is the test
NUNTIL nbinary                  # the until statement
NFOR nfor                       # the for statement
NCASE ncase                     # a case statement
NCLIST nclist                   # a case
NDEFUN narg                     # define a function.  The "next" field contains
NARG narg                       # represents a word
NTO nfile                       # fd> fname
NCLOBBER nfile                  # fd>| fname
NFROM nfile                     # fd< fname
NFROMTO nfile                   # fd<> fname
NAPPEND nfile                   # fd>> fname
NTOFD ndup                      # fd<&dupfd
NFROMFD ndup                    # fd>&dupfd
NHERE nhere                     # fd<<\!
NXHERE nhere                    # fd<<!
NNOT nnot                       # ! command  (actually pipeline)

NCMDの場合はevalcommand()が呼ばれます。この関数の中でプロセスのフォークが行われます(vfork()が呼ばれています)。実行されるコマンドを追いかけたいので、858行目からの子プロセス側の処理を追って行きます。

/usr/src/bin/sh/eval.c:
 672 /*
 673  * Execute a simple command.
 674  */
 675
 676 STATIC void
 677 evalcommand(union node *cmd, int flgs, struct backcmd *backcmd)
 678 {
...中略...
 845                 if (cmdentry.cmdtype == CMDNORMAL) {
 846                         pid_t   pid;
 847
 848                         savelocalvars = localvars;
 849                         localvars = NULL;
 850                         vforked = 1;
 851                         switch (pid = vfork()) {
 852                         case -1:
 853                                 TRACE(("Vfork failed, errno=%d\n", errno));
 854                                 INTON;
 855                                 error("Cannot vfork");
 856                                 break;
 857                         case 0:
 858                                 /* Make sure that exceptions only unwind to
 859                                  * after the vfork(2)
 860                                  */
 861                                 if (setjmp(jmploc.loc)) {
 862                                         if (exception == EXSHELLPROC) {
 863                                                 /* We can't progress with the vfork,
 864                                                  * so, set vforked = 2 so the parent
 865                                                  * knows, and _exit();
 866                                                  */
 867                                                 vforked = 2;
 868                                                 _exit(0);
 869                                         } else {
 870                                                 _exit(exerrno);
 871                                         }
 872                                 }
 873                                 savehandler = handler;
 874                                 handler = &jmploc;
 875                                 listmklocal(varlist.list, VEXPORT | VNOFUNC);
 876                                 forkchild(jp, cmd, mode, vforked);
 877                                 break;
 878                         default:
 879                                 handler = savehandler;  /* restore from vfork(2) */

一見すると、子プロセス側の処理はforkchild()側で完結する(別プロセスがexecされる)ように見えますが、forkchild()は生成したプロセスに対するシグナルハンドリング処理などの便利関数となっていました。なので、今回はforkchild()の中身についてはスキップします。

/usr/src/bin/sh/jobs.c:
 891 void
 892 forkchild(struct job *jp, union node *n, int mode, int vforked)
 893 {
...中略...
 953 }

forkchild()から戻ってきた子プロセス側の処理は、vfork()の戻り値による親・子プロセスの判別を抜け、evalcommand()の916行目以降の処理に入って行きます。

ここからの処理では、シェル関数、組み込みコマンド、通常コマンドのいずれかにより処理が分かれます。今回は通常コマンドなので、1051行目以降の処理となります。

/usr/src/bin/sh/eval.c:
 676 STATIC void
 677 evalcommand(union node *cmd, int flgs, struct backcmd *backcmd)
 678 {
...中略...
 876                                 forkchild(jp, cmd, mode, vforked);
 877                                 break;
...中略...
 916         /* This is the child process if a fork occurred. */
 917         /* Execute the command. */
 918         switch (cmdentry.cmdtype) {
 919         case CMDFUNCTION:
 920 #ifdef DEBUG
 921                 trputs("Shell function:  ");  trargs(argv);
 922 #endif
...中略...
 973 #ifdef DEBUG
 974                 trputs("builtin command:  ");  trargs(argv);
 975 #endif
...中略...
1051         default:
1052 #ifdef DEBUG
1053                 trputs("normal command:  ");  trargs(argv);
1054 #endif
1055                 clearredir(vforked);
1056                 redirect(cmd->ncmd.redirect, vforked ? REDIR_VFORK : 0);
1057                 if (!vforked)
1058                         for (sp = varlist.list ; sp ; sp = sp->next)
1059                                 setvareq(sp->text, VEXPORT|VSTACK);
1060                 envp = environment();
1061                 shellexec(argv, envp, path, cmdentry.u.index, vforked);
1062                 break;
1063         }
1064         goto out;
1065
1066 parent: /* parent process gets here (if we forked) */

通常コマンドの場合はshellexec()が呼ばれ、ここからtryexec()が呼ばれます。

/usr/src/bin/sh/exec.c:
 116 /*
 117  * Exec a program.  Never returns.  If you change this routine, you may
 118  * have to change the find_command routine as well.
 119  */
 120
 121 void
 122 shellexec(char **argv, char **envp, const char *path, int idx, int vforked)
 123 {
 124         char *cmdname;
 125         int e;
 126
 127         if (strchr(argv[0], '/') != NULL) {
 128                 tryexec(argv[0], argv, envp, vforked);
 129                 e = errno;
 130         } else {
 131                 e = ENOENT;
 132                 while ((cmdname = padvance(&path, argv[0])) != NULL) {
 133                         if (--idx < 0 && pathopt == NULL) {
 134                                 tryexec(cmdname, argv, envp, vforked);
 135                                 if (errno != ENOENT && errno != ENOTDIR)
 136                                         e = errno;
 137                         }
 138                         stunalloc(cmdname);
 139                 }
 140         }
 141
 142         /* Map to POSIX errors */
 143         switch (e) {
 144         case EACCES:
 145                 exerrno = 126;
 146                 break;
 147         case ENOENT:
 148                 exerrno = 127;
 149                 break;
 150         default:
 151                 exerrno = 2;
 152                 break;
 153         }
 154         TRACE(("shellexec failed for %s, errno %d, vforked %d, suppressint      %d\n",
 155                 argv[0], e, vforked, suppressint ));
 156         exerror(EXEXEC, "%s: %s", argv[0], errmsg(e, E_EXEC));
 157         /* NOTREACHED */
 158 }

tryexec()内で晴れて(?)execve(2)が呼ばれる運びとなります。

/usr/src/bin/sh/exec.c:
 161 STATIC void
 162 tryexec(char *cmd, char **argv, char **envp, int vforked)
 163 {
...中略...
 169 #ifdef SYSV
 170         do {
 171                 execve(cmd, argv, envp);
 172         } while (errno == EINTR);
 173 #else
 174         execve(cmd, argv, envp);
 175 #endif

まとめ

NetBSD/bin/shでコマンドが実行されるまでの流れをソースコードレベルで追いかけてみました。今回は単純なコマンド実行だけでしたが、パイプやリダイレクトと組み合わせたコマンド実行の場合についても調べてみたいと思います。

「技評×オングスこんなシェルスクリプトは書いちゃダメだ!」に参加してきました

技評×オングスこんなシェルスクリプトは書いちゃダメだ!」に参加してきました

技評×オングスこんなシェルスクリプトは書いちゃダメだ!に参加してきました。FreeBSD勉強会を開催している@daichigotoさんが主催されています。FreeBSD勉強会は若干お堅い内容なので、もう少しカジュアルな内容の勉強会にしたいとのことです。

シェルスクリプトの3つの側面

シェルスクリプトには以下の3つの側面があるとのことです。

  • システムを組み上げるためのソフトウェア
  • ユーザが操作するインタフェース
  • 業務システムを組み上げるためのソフトウェア

シェルスクリプトはエンジニアの腕前の差がはっきりと出るものであり、学ぶことによって効率のよいシェルスクリプトが書けるようになるということ、また、シェルとカーネルをよく知るエンジニアが書くスクリプトは効率がよい処理になるという説明がありました。

ポイントとしては"at a glance"(一瞥してわかる)な書き方が重要とのことです。
(私の英語力はまったくダメダメなので思わず辞書を引いてしまいました……)

ダメなスクリプトの例

ダメなスクリプトの例として以下が挙げられていました。

手続き型的な発想のシェルスクリプト

手続き型的なプログラミングでは、データに対する順次処理を書いてしまいがちですが、「まず最初に処理するデータを減らす」ことが重要とのことで、悪い書き方と良い書き方として、以下のような例が示されていました。

  • (悪い書き方)データレコードの各フィールドを都度if文でチェックしてから集計する方法
  • (良い書き方)awkでマッチする行を抜き出してから集計する方法

前者と後者では1000倍くらい速度が違うという結果を示しながらの説明となっていました。料理でも下ごしらえが重要だったりするので、データ処理においても下ごしらえに相当する処理をどうするかは重要なのだなと思いました。

変数を多用するシェルスクリプト

シェルスクリプトの変数展開は遅い処理であるという説明がありました。例として文字列の連結をシェル変数上で行った場合とファイルに追加出力した場合の結果が示されていました。

私の環境でもちょっと試してみました。26Kbyteほどのテキストファイルに対して先の手順を実施してみます。

$ w3m -dump http://www.aozora.gr.jp/cards/000081/files/4601_11978.html > furandon.txt
$ ls -hl furandon.txt
-rw-r--r--  1 fpig  users   26K Sep  2 04:49 furandon.txt

結果は以下となりました。データサイズが小さいとはいえ、すでに10倍程度の速度差が出ています。数メガ、数ギガ単位のデータであれば、見過ごせないほどの速度差になってくるはずです。

$ # シェル変数上で文字列連結した場合
$ time (cat furandon.txt | while read i; do a=$a$i; done)

real    0m1.348s
user    0m1.047s
sys     0m0.031s

$ # ファイルに追加出力した場合
$ time (cat furandon.txt | while read i; do echo $i >> out.txt; done)

real    0m0.124s
user    0m0.040s
sys     0m0.053s

関数(ただし、これは場合によりけりのようです)

これはシェル変数のスコープに関連してくる話で、シェルスクリプト関数の実態はグルーピングした処理であるため、文脈によってグローバルな変数を書き換えてしまう、という話でした。ただ、これは必ずしも悪手というわけではなく、シェルスクリプトの振る舞いをよく理解せずにコードを書くとハマる可能性があるよ、という意味での説明のようでした。

なぜこんな仕組みになっているのか?

シェルスクリプトのダメな例/良い例の話があった後、なぜこんな仕組みになっているのかの説明がありました。

シェルスクリプトの深い部分を理解しようと考えた場合、それはOSレイヤに踏み込んで行く形になります。取っ掛かりとして、シェルと結びつきが強い以下のシステムコールがどういう振る舞いをするか把握するとよいとのことでした。

  • fork(2)
  • execve(2)
  • pipe(2)
  • wait3(2)

ちょっと興味があったので、別エントリでNetBSDでの場合を調べてみました。

シェルによるシステム開発方式

一通り「こんなシェルスクリプトは書いちゃダメだ!」という説明があった後、株式会社オングスさんで実践しているttt開発方法を例にしたシェルによるシステム開発方式の説明がありました。

どのシステム開発にも言えることだと思いますが、シェルによるシステム開発でもうまく行くパターンと失敗するパターンがあるようです。

うまく行くパターンとしては、開発するシステムに対する業務フロー図やER図がちゃんと記述できること(記述できないということは、どんなシステムにするかを明確化できていない)、データの配置が事前に考えられているころ、UIにはHTML5/CSS3アダプティブデザインなど、最新の技術が活用されていることや、バックエンド側は長くても数百行程度のシェルスクリプトになっていること等が挙げられていました。

上記のパターンと逆の状態になっているケースが、いわゆる失敗するパターンとして説明されていました。

スキルアップのための書籍やサイト

これからシェルスクリプトやシェルによる開発を始めてみようという人向けに、以下の情報源が提示されていました。

次回の勉強会について

今回の勉強会は満員ということもあり、次回の開催も決定しています!とのことです。

また、FreeBSD勉強会が今月中頃に開催されます。

参加者からの質問

参加者から出た質問については、シェルスクリプトデバッグ手法に関する内容が多かった気がします。また、BSD系OSをこれから使ってみようと考えている方もおられたようで、BSD人気を増やす向きの勉強会はありがたいものです。

シェルのデバッグ手法としては、シェバンに"/bin/sh -exv"を指定する方法、パイプの途中をteeで眺める方法などが紹介されていました。

他にもシェル変数の意味(「$$」など)の意味をどう調べたらよいか(man shに説明があるようですが、もう少しカジュアル(?)な変数の意味リストが欲しいかと……)、といった質問や、jsonやpdf等のデータをシェルスクリプトで扱う方法(オングスさんではズバリjsonというコマンドを用意しているそうです)といった質問が出ていました。

まとめ

技評×オングスこんなシェルスクリプトは書いちゃダメだ!に参加してきました。シェルスクリプトは日々の小さな作業をパッとこなすために使っており、大きなシステムを作ったことはなかったのですが、この勉強会の内容を元に比較的大きなシステムを手早く作れるようになれれば良いなと思います。

第20回「ネットワーク パケットを読む会(仮)」に参加してきました

第20回「ネットワーク パケットを読む会(仮)」に参加してきました

第20回「ネットワーク パケットを読む会(仮)」に参加し、tcpdumpの出力からネットワークパケットを読むための取っ掛かりとなる手順を発表してきました。

発表してきた内容

発表資料は以下のURLにて公開しています。ネットワークパケットをtcpdumpで出力し、その16進ダンプ内容をetherヘッダからICMP echo/replyまで読み解いてみようという内容です。

発表スライドはMagicPointで作成しています。発表スライドのソースファイル(.mgpファイル)についてもgist上で公開しています。

勉強会メモ

以下は勉強会のメモです。自分なりにまとめた内容なので、間違って理解している箇所があるかもしれませんのでご注意ください。

hpingで作るパケット

「Hentaiなping」であるhpingに関する発表で、hpingから設定可能なIP,ICMP,TCP,UDPのオプションについて解説されていました。発表者はCTF for Beginnersの問題作成用にhpingを利用してみましたとのことです。

ポートスキャンやパケットジェネレータの機能を併せ持つツールのようで、Scapypkttoolsと似たツールのようです。ただし、hping自体は10年ほど前くらいから更新されていないようです……。

512K問題をビッグデータ解析した先にあるもの

  • 発表者はととろさん

つい先ごろ話題になった、BGPの512K問題に関する発表でした。私自身はBGPは名前くらいしか聞いたことがなく、512K問題の具体的な内容を知りませんでした。

BGPはAS番号を元に、接続先に最もホップ数が少ない経路を自動で選択する仕組みで、BGPオペレーションはごく限られた人しか行わない(行う必要がない)ようです。12K問題はIPv4に関する経路データの増加が引き金とのことですが、IPv6でも経路情報が爆発したら発生する可能性があるようです。

今回の512K問題は、2014/08/12前後から17にかけて発生しており、米ベライゾンが使用するCISCOルータで発生しました。ルータの物理メモリが少ないことで発生しており、経路数が512,000を越えると発生することから「512K問題」と呼ばれています。2011年以前製造のCISCOルータが原因であると特定されており、回避configの適用で対応加能です。一番の対策はルータを買い換えることのようですが、お値段が数千万円単位(!)のものらしく、おいそれと購入はできなさそうです。

BGP,512K問題については、以下のURLにて詳しく解説されています(BGPルータのメモリがDRAMと異なる仕組みだとは知りませんでした……)。

上記記事の中から、よく理解できていないキーワードを(自分用に)がーっと列挙しておきます。

  • AS(Autonomous System)
  • フルルート(Full Route:BGPが収集した世界中のASネットワークへの全経路情報)
  • BGP version 4(RFC4271)
  • EGP(Exterior Gateway Protocol)
    • インターネット上で組織間の経路情報をやり取りする経路制御プロトコル
    • BGPはEGPに分類される
  • IGP(Interior Gateway Protocol)
    • 組織の内部で完結する経路制御プロトコル
    • 以下はIGPに分類される
      • RIP(Routing Information Protocol)
      • OSPF(Open Shortest Path First)
      • EIGRP(Enhanced Interior Gateway Routing Protocol)
  • RIR(Regional Internet Registry;地域インターネットレジストリ)
  • NIR(National Internet Registry;国別インターネットレジストリ)
  • LIR(Local Internel Registry;ローカルインターネットレジストリ)
  • (AS番号→RIRやJPNIC等のNIRから割り当てを受けることができる)
  • (AS番号、原則として2バイトのサイズだが、AS番号数が不足してきたため、最近は4バイト化が進んでいる)
  • iGP(内部BGP)
  • eBGP(外部BGP)
  • パンチングホール(経路数の増大を招く一因?)
  • IRR(Internet Routing Registry)
  • S-BGP(Secure BGP)
  • soBGP(Secure Origin BGP)
  • BFD(Bidirectional Forwarding Detection)
  • TCAM(Ternary Content-Addressable Memory)
  • CAM(Content-Addressable Memory)
  • FIB(Forward Information Base)
  • RIB(Routing Information Base)
  • コンフェデレーション
  • route reflector
  • route server
  • BGP経路のアグリゲーション

あと、これも知らなかったのですが、BGPMONというネットワークモニタリングサービスがあるようです。

Fiddler使ってる?

  • 発表者はTakagiさん

WebデバッグツールFiddlerに関する発表でした。私はFiddlerを全く知らなかったので、ただ聞くだけになっていました。

FiddlerIE開発リーダー格のひとりであったエリック・ローレンスによって作成されたツールで、Webのデバッグや、パフォーマンステスト、HTTP/HTTPSトラフィックレコーディングやセッション操作、セキュリティテストといった、Web開発(の後の一連のテスト)に役立つ機能が提供されているようです(公式サイトからの受け売りですが……)。発表者の方もおっしゃっていましたが、「攻撃される前に自分でテスト」というのは重要だと感じました。

QUIC

QUIC(Quick UDP Internet Connections)に関する発表でした。QUICはSPDYに関連し、HTTP->SPDY->QUIC->UDP->IPの形で置き換えようとするプロトコルのようです。

The Chromium Blogの以下のエントリでQUICの解説と設計ドキュメントが公開されています(が、それ以降QUICに関するエントリが無いのがちょっと気になります……)。

上記のブログと設計ドキュメントを読まないとダメかな……と思っていたら、既にブログにまとめていた方がいました。

なるほど、と思いながら読んでいたところ、以下のキーワードについては自分のなかでちゃんと理解できていなかったので、別途調べておこうと思いました。

Fiddler Add-on

FiddlerのAdd-onに関する発表でした。Fiddlerを動作させる際は、.NETのフル版でないとハマる場合があるとのことです。また、.NETのバージョンにも注意する必要があるようです。atmarkITさんにてバージョン確認用のバッチファイルが公開されているので、これを利用すると良いとのことでした。

FiddlerのAdd-onは.NETで開発したdllで提供されており、Add-onの例として、Burp-like InspectorとSessionDecoratorが紹介されていました。

また、実践Fiddlerという書籍があるようです。

まとめ

第20回「ネットワーク パケットを読む会(仮)」にて発表してきました。次回のネッ トワークパケットを読む会は9/22(月)を予定しているとのことです。

FiddlerやQUICなど、(私が情報収集をサボっているだけですが)知らなかった技術キーワードを補足することができ、勉強になりました。知らないキーワードなどは少しずつ調べておこうと思います。

ラブライブ!OP曲を(株)白ヤギさんのテキスト要約にかけてみた

ラブライブ!OP曲を(株)白ヤギさんのテキスト要約にかけてみた

つい先日、株式会社 白ヤギコーポレーションさんにて「自動要約サービス」が公開されました。

Webスクレイピング勉強会への参加で、自然言語処理に興味が湧いてきており、さっそくこのサービスを試してみました。

ラブライブ!OP曲をテキスト要約してみる

要約の元になるテキストとして、アニメ版ラブライブ!のOP曲を用いてみました(いずれも名曲です)。

結果は以下となりました。要約結果を自分のなかで予想したものと並べてみます。

「僕らは今のなかで」の要約結果

予想
  1. まっすぐな想いが みんなを結ぶ
  2. それぞれが好きな場所で頑張れるなら 新しい場所がゴール
  3. 怖がる癖は捨てちゃえ
結果(歌詞が丸ごと返ってきた)

「それは僕たちの奇跡」の要約結果

予想
  1. 夢を叶えるのはみんなの勇気
  2. 最後まで駆け抜けるよ!
  3. いまここで出会えた奇跡
結果(歌詞が丸ごと返ってきた)

歌詞が丸ごと要約結果として返されます。これは当たり前の結果であり、『要約』は文書内の重要な部分を抽出するものであるからして、ラブライブ!の歌詞は一字一句無駄は無いと言えるのです!(キリッ

……ではなく、少し考えてみると、歌詞というものは想いのたけをそのまま文字にしているので、論理的な構成を見つけ出して抽出する要約には不向きな文章と言えるのだと思います。

フランドン農学校の豚」を要約してみる

今度は歌詞ではなく、宮沢賢治の「フランドン農学校の豚」を要約してみましょう。

要約結果は以下となります。みごとに要約されています。

  1. フランドン農学校の豚宮沢賢治〔冒頭原稿一枚?なし〕以外の物質は、みなすべて、よくこれを摂取(せっしゅ)して、脂肪(しぼう)若(もし)くは蛋白質(たんぱくしつ)となし、その体内に蓄積(ちくせき)す。
  2. 」とこう書いてあったから、農学校の畜産(ちくさん)の、助手や又(また)小使などは金石でないものならばどんなものでも片(かた)っ端(ぱし)から、持って来てほうり出したのだ。
  3. というわけはその晩方、化学を習った一年生の、生徒が、自分の前に来ていかにも不思議そうにして、豚のからだを眺(なが)めて居た。
  4. 豚の方でも時々は、あの小さなそら豆形(まめがた)の怒(おこ)ったような眼(め)をあげて、そちらをちらちら見ていたのだ。
  5. ところが次の日のこと、畜産学の教師が又やって来て例の、水色の上着を着た、顔の赤い助手といつものするどい眼付して、じっと豚の頭から、耳から背中から尻尾(しっぽ)まで、まるでまるで食い込むように眺めてから、尖(とが)った指を一本立てて、「毎日阿麻仁(あまに)をやってあるかね。

まとめ

ラブライブ!OP曲をテキスト要約にかけてみました。あまり論理的な構成になっているとは言えない歌の歌詞のようなものは、機械的な要約に向かないようです。これを逆手に取って、自分の書いた文章の要約結果から文章の良し悪しを判定できたりもするのかなと思いました。

「第2回Webスクレイピング勉強会@東京」に参加してきました

「第2回Webスクレイピング勉強会@東京」に参加してきました

第2回Webスクレイピング勉強会@東京に参加し、お手軽に未知語を探すアイディアについて発表してきました。

発表してきた内容

前回に引き続き、今回の勉強会でも発表させていただきました。発表資料は以下のURLにて公開しています。

発表内容はGoogleサジェストで得られた単語をChasen(形態素解析器)にかけ、未知語の場合はChasen辞書の登録エントリを作成する、というものです。

Googleサジェスト結果からChasen辞書を作成するスクリプト

発表時はデモの実演ができませんでしたが、作成したスクリプトGitHubで公開しています。シェルスクリプトで作成しており、Chasenwgetがインストールされている環境であれば動作するかと思います。
(自分の環境ではNetBSD-6.1-i386にて動作確認が取れています)

以下のような実行結果を得られます。

$ ./suggest2chadic.sh きるみ 
(品詞 (名詞 一般)) ((見出し語 (キルミーダンス 3641)) (読み キルミーダンス) (発音 キルミーダンス))
(品詞 (名詞 一般)) ((見出し語 (キルミーベイベー 3641)) (読み キルミーベイベー) (発音 キルミーベイベー))

まとめ

第2回Webスクレイピング勉強会@東京にて発表してきました。この勉強会は全3回の予定となっており、次回が最終回となるようです。Webスクレイピング勉強会 Season 2が決定したり、この勉強会での知見を活かした発展的な勉強会が開催されるとイイなと思いつつ、次回も楽しみにしています。

CentOS 7.0でDockerを動かしてみた

CentOS 7.0でDockerを動かしてみた

先日開催された第2回東京SoftLayer勉強会で『SoftLayerでDockerを使ってみた』という発表があり、Dockerのインストールから使い方までの手順が解説されていました。

個人的にDockerを試してみたいということもあり、さっそく解説されていた手順を参考にDockerを動かしてみました。勉強会ではCentOS 6系向けの手順となっていましたが、私の方ではCentOS 7系で試してみました。

CentOS 7.0のセットアップ

GUI等は使用しないので、minimalインストールの状態からDocker環境を構築していきます。以下はインストール後にsshログインが行えるようになるまでの手順です。

SELinuxの無効化

/etc/selinux/configを以下のように修正し、SELinuxを無効化します。

--- config.orig 2014-07-29 11:24:02.949653548 +0900
+++ config      2014-07-29 11:24:09.957653412 +0900
@@ -4,7 +4,7 @@
 #     enforcing - SELinux security policy is enforced.
 #     permissive - SELinux prints warnings instead of enforcing.
 #     disabled - No SELinux policy is loaded.
-SELINUX=enforcing
+SELINUX=disabled
 # SELINUXTYPE= can take one of these two values:
 #     targeted - Targeted processes are protected,
 #     minimum - Modification of targeted policy. Only selected processes are protected.

grub.cfgの設定

起動時のコンソールログを見えるようにしておきたいので、/boot/grub2/grub.cfgを以下のように修正します。ついでにLANGもen_US.UTF-8に変更しておきます。

--- grub.cfg.orig       2014-07-29 11:24:18.721653243 +0900
+++ grub.cfg    2014-07-29 11:24:38.572652858 +0900
@@ -81,7 +81,7 @@
        else
          search --no-floppy --fs-uuid --set=root dd4521d9-ca1c-462b-b353-2ba57bf4fc61
        fi
-       linux16 /boot/vmlinuz-3.10.0-123.el7.x86_64 root=UUID=dd4521d9-ca1c-462b-b353-2ba57bf4fc61 ro vconsole.keymap=us crashkernel=auto  vconsole.font=latarcyrheb-sun16 rhgb quiet LANG=ja_JP.UTF-8
+       linux16 /boot/vmlinuz-3.10.0-123.el7.x86_64 root=UUID=dd4521d9-ca1c-462b-b353-2ba57bf4fc61 ro vconsole.keymap=us crashkernel=auto  vconsole.font=latarcyrheb-sun16 LANG=en_US.UTF-8
        initrd16 /boot/initramfs-3.10.0-123.el7.x86_64.img
 }
 menuentry 'CentOS Linux, with Linux 0-rescue-6764668114ff4741a8994286ae140fdd' --class centos --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-0-rescue-6764668114ff4741a8994286ae140fdd-advanced-dd4521d9-ca1c-462b-b353-2ba57bf4fc61' {
@@ -95,7 +95,7 @@
        else
          search --no-floppy --fs-uuid --set=root dd4521d9-ca1c-462b-b353-2ba57bf4fc61
        fi
-       linux16 /boot/vmlinuz-0-rescue-6764668114ff4741a8994286ae140fdd root=UUID=dd4521d9-ca1c-462b-b353-2ba57bf4fc61 ro vconsole.keymap=us crashkernel=auto  vconsole.font=latarcyrheb-sun16 rhgb quiet
+       linux16 /boot/vmlinuz-0-rescue-6764668114ff4741a8994286ae140fdd root=UUID=dd4521d9-ca1c-462b-b353-2ba57bf4fc61 ro vconsole.keymap=us crashkernel=auto  vconsole.font=latarcyrheb-sun16
        initrd16 /boot/initramfs-0-rescue-6764668114ff4741a8994286ae140fdd.img
 }
 if [ "x$default" = 'CentOS Linux, with Linux 3.10.0-123.el7.x86_64' ]; then default='Advanced options for CentOS Linux>CentOS Linux, with Linux 3.10.0-123.el7.x86_64'; fi;

ホスト名の設定

以下の手順でホスト名を設定します。

# echo dockertest.furandon.net > /etc/hostname

固定IPアドレスの設定

DHCPよりも固定IPアドレスの方が作業しやすいため、Arch Wikiの『固定IPアドレス』を参考にしながら設定します。

/etc/conf.d/network@enp0s3にIPアドレス等を記述します。/etc/conf.dディレクトリは存在しないので予め作成しておきます。

# mkdir /etc/conf.d
# touch /etc/conf.d/enp0s3

/etc/conf.d/network@enp0s3の中身は以下の通りです。

address=192.168.0.232
netmask=24
broadcast=192.168.0.255
gateway=192.168.0.1

/etc/systemd/system/network@.serviceにsystemdのユニットファイルを作成します。
(Arch Wikiの内容を参考に作成しています)
Arch Wikiの/etc/systemd/system/network@.service中でipコマンドが/usr/bin/ipでフルパス指定されていますが、CentOS-7では/sbin/ipとパスが異なるので注意してください。

[Unit]
Description=Network connectivity (%i)
Wants=network.target
Before=network.target
BindsTo=sys-subsystem-net-devices-%i.device
After=sys-subsystem-net-devices-%i.device

[Service]
Type=oneshot
RemainAfterExit=yes
EnvironmentFile=/etc/conf.d/network@%i

ExecStart=/sbin/ip link set dev %i up
ExecStart=/sbin/ip addr add ${address}/${netmask} broadcast ${broadcast} dev %i
ExecStart=/bin/sh -c 'test -n ${gateway} && /sbin/ip route add default via ${gateway}'

ExecStop=/sbin/ip addr flush dev %i
ExecStop=/sbin/ip link set dev %i down

[Install]
WantedBy=multi-user.target

サービスを有効化します。

# systemctl enable network@enp0s3.service

/etc/resolv.confの設定

インストール時にrpmパッケージのインストール等でネットワーク設定が行われており、/etc/resolv.confには(DHCPでのIPアドレス取得による)nameserver設定が入っています。固定IPアドレスでも同じnameserver設定を利用するため、この段階での設定変更は不要です。

LANGの設定

/etc/locale.confでLANGをen_US.UTF-8に設定します。
(日本語のままでいいよ、という場合はこの手順をスキップしてください)

--- locale.conf.orig    2014-07-29 11:24:55.014652540 +0900
+++ locale.conf 2014-07-29 11:25:01.258652419 +0900
@@ -1 +1 @@
-LANG="ja_JP.UTF-8"
+LANG="en_US.UTF-8"

不要なサービスの停止

Dockerを試す用途では不要と思われるサービスを停止します。

$ sudo systemctl disable avahi-daemon.service
$ sudo systemctl disable dbus-org.fedoraproject.FirewallD1.service
$ sudo systemctl disable dbus-org.freedesktop.Avahi.service
$ sudo systemctl disable dbus-org.freedesktop.NetworkManager.service
$ sudo systemctl disable dbus-org.freedesktop.nm-dispatcher.service
$ sudo systemctl disable NetworkManager-dispatcher.service
$ sudo systemctl disable NetworkManager.service
$ sudo systemctl disable postfix.service
$ sudo systemctl disable tuned.service
$ sudo systemctl disable avahi-daemon.socket

ユーザの追加

作業用のユーザを追加します。

$ sudo useradd -g users -G wheel -m -s /bin/bash fpig
$ sudo passwd fpig

再起動

ここで一旦再起動します。再起動後、固定IPアドレスが付与されているか等の確認をおこないます。

$ sudo shutdown -r now

ここまでで最低限の設定は完了し、sshでログインできる状態になっています。
以降はsshログインした状態での作業となります。

Dockerを試してみる

dockerのインストール

docker.x86_64というパッケージが提供されているので、これをインストールします。

$ yum search docker
...
docker-registry.noarch : Registry server for Docker
docker.x86_64 : Automates deployment of containerized applications
$ sudo yum install docker

勉強会で例示されていたCentOS 6系の環境では、EPELからDockerをインストールしていましたが、CentOS 7系の環境ではベースリポジトリにDockerパッケージが含まれていました。

$ rpm -qa | grep docker
docker-0.11.1-22.el7.centos.x86_64
$ yum provides docker
...
docker-0.11.1-19.el7.centos.x86_64 : Automates deployment of containerized
                                   : applications
Repo        : extras
$ grep -A5 '^\[extras' /etc/yum.repos.d/CentOS-Base.repo
[extras]
name=CentOS-$releasever - Extras
mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=extras
#baseurl=http://mirror.centos.org/centos/$releasever/extras/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7

Dockerサービスを有効化します。DockerパッケージにSystemdのユニットファイルが同梱されているので、これを利用します。

$ rpm -ql docker-0.11.1-22.el7.centos.x86_64 | grep systemd
/usr/lib/systemd/system/docker.service
$ sudo systemctl enable docker.service
ln -s '/usr/lib/systemd/system/docker.service' '/etc/systemd/system/multi-user.target.wants/docker.service'
$ systemctl list-unit-files | grep docker
docker.service                            enabled

上記設定は再起動してから有効になるので、ここでは手動でdocker.serviceを起動します。

$ sudo systemctl start docker.service

さっそくdockerコマンドを使ってみます。

$ sudo docker version
Client version: 0.11.1-dev
Client API version: 1.12
Go version (client): go1.2
Git commit (client): 02d20af/0.11.1
Server version: 0.11.1-dev
Server API version: 1.12
Go version (server): go1.2
Git commit (server): 02d20af/0.11.1

Dockerイメージのダウンロード

手元でDockerイメージを作るところまで試してみたかったのですが、まだ使い始めたばかりということもあり、既存のDockerイメージファイルを使ってみることにしました。

$ sudo docker pull ubuntu

しばらく待つとUbuntuのイメージファイルが手元にダウンロードされます。使用可能なイメージはdocker imageで確認できます。

$ sudo docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
ubuntu              14.04               ba5877dc9bec        7 days ago          192.7 MB
ubuntu              trusty              ba5877dc9bec        7 days ago          192.7 MB
ubuntu              latest              ba5877dc9bec        7 days ago          192.7 MB
ubuntu              precise             b9e56c8f2cf5        7 days ago          103.8 MB
ubuntu              12.04               b9e56c8f2cf5        7 days ago          103.8 MB
ubuntu              14.10               6ef6f1a66de1        7 days ago          194.1 MB
ubuntu              utopic              6ef6f1a66de1        7 days ago          194.1 MB
ubuntu              12.10               c5881f11ded9        5 weeks ago         172.1 MB
ubuntu              quantal             c5881f11ded9        5 weeks ago         172.1 MB
ubuntu              13.04               463ff6be4238        5 weeks ago         169.4 MB
ubuntu              raring              463ff6be4238        5 weeks ago         169.4 MB
ubuntu              13.10               195eb90b5349        5 weeks ago         184.6 MB
ubuntu              saucy               195eb90b5349        5 weeks ago         184.6 MB
ubuntu              10.04               3db9c44f4520        3 months ago        183 MB
ubuntu              lucid               3db9c44f4520        3 months ago        183 MB

Dockerコンテナの起動

さっそくDockerでUbuntuを起動してみます。

$ sudo docker run -i -t ubuntu:14.10 /bin/bash

サクッとUbuntuが起動しました!
/etc/lsb-releaseを見ると、確かにUbuntuです。

root@9cf71dd83894:/# cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=14.10
DISTRIB_CODENAME=utopic
DISTRIB_DESCRIPTION="Ubuntu Utopic Unicorn (development branch)"

Dockerコンテナのデタッチ・アタッチ

起動したDockerコンテナ上でexitするとコンテナは停止してしまいます。練習もかねてDockerコンテナのデタッチ→アタッチ→exitによるコンテナ停止という手順を試してみます。

Dockerコンテナを終了せずに抜ける(デタッチする)には、Ctrl+p Ctrl+qを入力します。

root@9cf71dd83894:/# (ここでCtrl+p Ctrl+qを入力)$
$

docker psコマンドで稼働しているコンテナを確認できます。

$ sudo docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
9cf71dd83894        ubuntu:14.10        /bin/bash           9 minutes ago       Up 9 minutes                            backstabbing_rosalind0

コンテナにアタッチしてみます。

$ sudo docker attach 9cf71dd83894
root@9cf71dd83894:/#

無事にアタッチでできました。後はexitでコンテナを終了します。

root@9cf71dd83894:/# exit
exit
$ sudo docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
$

export/import

私の手元ではまだ試していませんが、イメージファイルのexport/importも可能です。
以下の手順でexport/importを行います。

$ docker export <コンテナID>
$ docker export 14773ff9e93c > myweb.tar    # コマンド例
$ docker import [リポジトリTAG]
$ docker import < - myweb:rel1 < myweb.tar  # コマンド例

ローカルストレージのアタッチ

こちらも私の手元では試していませんが、Runコマンドの"-v"オプションでホストのディレクトリをアタッチ可能です。

$ docker run -t -i -v <local_dir>:<container dir>:<rw|ro> centos /bin/bash
$ docker run -d -p 5000:5000 -v /home/hoge/data:/tmp/data centos  # コマンド例

/home/data/dataは、共有ストレージ(NFS)やディスクミラー(DRBD)、分散ストレージ(Ceph-fs)等を利用して自分でミラーリングします。

まとめ

参加した勉強会でDockerの一連の使用手順が解説されていました。Dockerを覚えてみたいと思っていたので、さっそく覚えた手順を自分の環境で試してみました。

思っていたよりも簡単にコンテナの実行が行え、ついに我が家にもDockerの技術が伝来したという感じです。
(種子島に火縄銃が伝来した……という気分です)

まだ試してはいないものの、イメージのexport/importやプライベートリポジトリといった機能もあるようなので、勉強会用のイメージ提供に活用できればと思います。

第2回 東京SoftLayer勉強会に参加してきました

第2回 東京SoftLayer勉強会に参加してきました

第2回 東京SoftLayer勉強会に参加してきました。前回は5月だったので、2ヵ月ぶりの開催ですね。

前回の勉強会メモと同様に、今回も勉強会メモをまとめてみました。

サムライスタートアップアイランドご紹介

はじめに勉強会の会場であるサムライスタートアップアイランドの紹介がありました。

2011年11月1日にオープンしたサムライスタートアップアイランド(SSI=Samurai Startup Island)は、スタートアップ企業とその支援者が集まる場所を提供しているとのことです。
(SSIの紹介ページからの受け売りです……)
会計士さんも常駐しており、スタートアップ企業におけるファイナンス関係のお悩みごともフォローできますとのことです。

現在50社ほど入居しており、コワーキングスペースとしても活用されています。羽田空港が近いことから、外国からの訪問者への対応も考えられており、海外展開を考える企業にもオススメのようです。

SoftLayerのストレージと使い分けについて

発表者は日本IBMの新島さん。SoftLayerのビギナーズガイドを書いておられるとのことです。

SoftLayerはサーバに組み込まれたストレージだけでも複数種類あり、ストレージの観点から利用可能なサービスの一望と目的別の使い分け方の解説という内容での発表でした。

SoftLayerのストレージ

  • BM(Mare Metal Server)とVS(Virtual Server)で構成が異なる
  • BMのディスク

    • SATA,SAS,SSDから選んで指定できる
    • BMのモデルによって搭載できるディスクの台数が異なる
    • 生のディスク(物理的なディスク)なので、必ずミラーリングRAID構成にすること
      • BMのディスクは本当のサーバー(手元に物理サーバを構築する場合)と同じに考えた方がよい
  • VSのディスク

    • ローカルドライブとSAN storageのを選んで指定できる
    • ローカルドライブは2台で400Gまで

    • SAN storage(iSCSI)は以下の構成から選択できる

      • 5台まで、25,100Gまで、2台以降は100-2000GBまで)の2つ
    • 仮装サーバのローカルドライブ→故障すると少し時間かかる

      • (SoftLayerの中の人が故障ドライブをせっせと交換する)
    • SANストレージの場合はバックアップ構成がくめる
      • ただしネットワークも障害点となる可能性が出てくる
  • portable diskとしての利用

    • virtual serverの2nd diskを切り離し、portable diskとして利用できる
    • 切り離したportable diskは、別のvirtual serverに取り付けることもできる

SoftLayerで利用できるストレージ

  • NAS,iSCSI,オブジェクトストレージが利用できる
  • NAS
    • CIFS,FTPでアクセス可能
    • プライベートLANに接続されている
      • (SoftLayerのサーバルーム写真における、青色のケーブルですね)
    • 現時点では未対応のため、NFSは利用できない
  • iSCSI
    • iSCSIもプライベートLANに接続されている
    • スナップショットが取得可能
    • データセンター間でレプリケーション可能
  • オブジェクトストレージ
    • OpenStackのswift互換
    • ポータルやREST APIからアクセスできる
    • CloudFuseでインスタンスにmountして使うこともできる
    • CDNを使ってファイルを配信することもできる
  • eVault(イーボルト)というバックアップツールがある

iSCSIのスナップショット

  • 30分毎にレプリケーションが実行される
  • 切り戻しは時間がかかる
  • レプリカのカスケードはできないので、マスター復帰時には必ず切り戻しが行われる
    • 切り戻しは時間がかかる!とのこと

各ストレージの使い分け

  • サーバのストレージとして

    • 大容量ならBMでSATA Drive
    • 高速IOならBMでSSDSAS Drive
    • サーバ生涯時の切り替えならVSでSAN Drive
    • 少用量で安さならVSでlocal drive
  • データ用、バックアップ用として

    • Snapshot使いたいならiSCSI
    • 複数サーバで共有したいなら
      • NASもしくは
      • VSかBMでファイルサーバを構成、
    • archive用ならobject storage

その他

  • 近日中にiSCSIの弱点を克服したソリューションが出てくるかも?

Why Riak & Why SoftLayer?

発表者はBashoジャパンの上西さん。Riakの紹介とSoftLayer上でRiakを動かすと何が嬉しいかについての発表でした。

スライドはWhy Riak? Why SoftLayer?にて公開されています。

スライドが公開されているので、自分のメモは不要かとも思ったのですが、前回のSoftLayer勉強会でのRiakのLTはただ聞くだけになっていたので、今一度自分なりにRiakについてがーっとまとめてみました。

Riakについて

  • システムの運用において可用性は大事
  • しかし、可用性に対する脅威は数多く存在する
    • ハードウェア故障
    • ネットワーク故障
      • スプリットブレインシンドロームによるデータ破壊
    • ソフトウェアのアップデートやメンテナンス
    • システムの過負荷

Riak

  • RiakはErlangで記述されたNoSQLデータベース
  • QuorumレプリケーションによりN個のノードにデータを複製することでノードがひとりくらい壊れていてもデータの書き込みが可能
  • 各ノードが管理するパーティションConsistent Hashingと呼ばれる160bitのキー空間を等分したリング状のハッシュテーブルになっている
    • レプリカはN個(=3)のノードにコピーされる

ノードが一時故障した場合

  • リング上の次のパーティションに書き込むことで、レプリカがN個ある状態を担保しておく
  • 一時故障ノードが復旧した時にレプリカを返す

ネットワーク故障の場合

  • Riakでは分断された各ノードでの書き込みを許容する
  • 復旧したら書き戻す
  • そのため、復旧時にデータの不整合(暗黙的な上書き)が発生する場合がある
    • 以下の手法で不整合を回避する
    • 不整合のパターンはいくつか存在する
      • write-write conflick →比較的対応しやすい
      • write-delete conflick →少しややこしい対応手順になる

Riakのバックアップ機能

なぜクラウドでRiakか

  • DBなどのミドルウェアが優れていてもHWがこけたら意味がない
  • なので、SoftlayerのBM上でRiakを使えると嬉しい
  • なぜBMか?VSではダメなのか?
    • 分散システムで大事なことは「故障の単位」
    • VSが動いているBMがこけると、Riakからは多重故障にみえてしまう
      • するとRiakの分散ノードがまるごと落ちるという事態が発生する
      • そのため、RiakはBMでの運用を推奨している

その他

参考リンク

QuantaStor概説/QuantaStor使ってみた

発表者はアファーム・ビジネスパートナーズ株式会社の西脇さんと日本情報通信の常田さん。

QuantaStoreアーキテクチャユースケース、使ってみた感想についての発表でした。

  • OSNEXUSについて

  • QuantaStor

    • QuantaStorはSAN(iSCSI/FC)とNAS(NFS)を兼ね備えたストレージアプライアンス
    • 64bit Intel/AMDの汎用サーバで稼働するUbuntu Server(Linux)上にインストールし、ソフトウェアベースのストレージとして利用する
    • QuantaStorはBMのみで利用可能
      • また、RAID構成を組む必要があるため、ディスクは4本以上必要
      • (SoftLayerのBMのドライブ数は2,4,6,12,24,36から選択できる)
  • 来月のSoftwareDedisnからSoftLayerの記事が連載されるとのこと

参考リンク

Object Storageを使ってみた

発表者は日本IBM高良さんSoftLayer探検隊の隊長さんとのことです。

Raspberry PiとSoftLayerのObjectStorageの連携に関する発表でした。

発表スライドは第二回SoftLayerユーザ会 ラズベリーパイとオブジェクトストレージを繋いでみたにて公開されています。詳細な手順はSoftLayer探検隊 第16回 Raspberry Pi で撮影した画像をSoftLayerのオブジェクト・ストレージに保存するにて公開されています。

発表の中で「組み込み機器とクラウドがつながる時代になった」という説明が印象的でした。最近IoT(Internet of Things:モノのインターネット)という言葉(バズワード?)をよく聞きますが、Raspberry PiとSoftLayerの組み合わせによる具体的な事例を見るのは初めてだったので、とても感銘をうけました。

SoftLayerでDockerを使ってみた

発表者はCUPA(一般社団法人クラウド利用促進機構)荒井さん

Dockerを利用したシステムポータビリティとDR(Disaster Recovery)対応について、SoftLayerを使用しての解説でした。

Dockerは個人的に試してみたいと常々思っていたので、SoftLayerの話は一旦どっかに置いておき(Dockerだけに)、別途ブログ記事を分けてみました。

まとめ

第2回東京SoftLayer勉強会に参加してみました。何となくSoftLayerがどんなものが見えてきた気がします。とはいえ、実はまだSoftLayerを使ってみたことが無いので、そろそろ触ってみようかなと思います。