OmniAICreator/Qiita-1.07M huggingface dataset:
OpenSSLを利用して接続したServerの証明書検証について

# はじめに
間違いがある場合はご指摘いただけると嬉しい
あと、素直にSwiftかObj-Cで実装したほうが絶対にいい

# どのような方向けのTipsか?
1. Verisign、Let's Encryptなどから発行されたサーバ証明書および中間証明書を持つSSLサーバに、 **iOS端末からNSURLConnectionなどではなく、OpenSSLのAPIを用いてSSL接続を行いたい**
2. ただし、**接続後にサーバからクライアント側に渡されたサーバ証明書および中間証明書が正しいかどうかを、iOSのシステムに組み込まれたルートCA証明書まで辿って検証したい**
3. ここで、iOSに於いてはルートCA証明書リストへのアクセスは不可能(と思われる)
4. つまり、OpenSSLで提供されている、SSL_CTX_load_verify_locationsやSSL_CTX_set_default_verify_pathsといったAPIが利用できず、BundleにルートCA証明書リストなどを追加しておかなくてはならない(オレオレ証明書を通すのと同様に)  
5. これは嫌だ！

という方向け

# 解決方法
## OpenSSL(C/C++)での実装
1. SSL_set_verifyを用いて、SSL_VERIFY_NONEにしておく
(なお、verifycallbackを利用する、という手段は未検証)
2. SSL_Connectする
3. SSL_get_peer_certificate_chainする  
これにより、サーバ証明書(と中間証明書)が得られる  
得られた証明書は、X509形式のポインタで表されているため、OpenSSLで提供されるAPIを利用して、iOSで取り扱うことのできる、DER形式のバイナリ列に直す  

```
  unsigned char* buf = NULL; // NULL  
  int len = i2d_X509(cert, &buf); // NULLを与えると、新たにmallocしてDERを返してくれる。勿論、後ほどfree必須
```
## Objective-C側の実装
```
CFMutableArrayRef certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, NULL); // 最大配列個数 => 指定なし
for (サーバから返答された証明書チェーンに含まれる証明書の個数) {
  CFDataRef data = CFDataCreate(kCFAllocatorDefault, buf, len); // 前節3.で得られたDERへのポインタと長さ
  SecCertificateRef cert = SecCertificateCreateWithData(NULL, data);
  CFArrayAppendValue(certs, cert);
}
SecTrustRef trust;
OSStatus status = SecTrustCreateWithCertificates(certs, SecPolicyreateBasicX509(), &trust);
SecTrustResultType r = kSecTrustResultInvalid;
status = SecTrustEvaluate(trust, &r);
```
これで、rの返り値がkSecTrustResultProceed==1もしくはkSecTrustResultUnspecified==4であれば、サーバ証明書検証成功[^注1]
なお、サーバから渡された証明書に中間CAが含まれていないなどのミスでルートCAまで辿れなかったり、オレオレ証明書+オレオレCA証明書(システムにインストールされていない証明書)がサーバから渡された場合は、kSecTrustResultRecoverableTrustFailure == 5となる  

# 最後に
この辺りを実装したコードは、
https://github.com/linear-rpc/linear-objc/blob/master/src/LinearSSLClient.mm#L89
にあるので、興味があればご参照を

[^注1]: > https://developer.apple.com/library/mac/qa/qa1360/_index.html<br>  The semantics behind receiving a kSecTrustResultUnspecified (4) error from Security APIs is that the certificate is indeed valid.  However, the user has not explicitly set the trust settings for the certificate via Keychain Access.
gulpで空フォルダを出力しないようにする

正確には「**gulpのストリームからファイルのみを選択して渡す**」方法です。
その逆、フォルダのみ渡すことも同じようにできます。

## フィルターのやり方
**[gulp-ignore](https://github.com/robrich/gulp-ignore)**を使います。
このプラグインは[gulp-match](https://github.com/robrich/gulp-match)をラップしていて、gulp-matchのオプション`isFile`, `isDirectory`が使えます。

```js
ignore.include({isFile: true})        // 「ファイルのみを選択」

ignore.exclude({isDirectory: true})   // または「フォルダを除外」でもOK
```


### 例1: 全ファイルをコピーするが、空フォルダは出力しない

```js
var gulp = require('gulp');
var ignore = require('gulp-ignore');

gulp.task('copy', function () {
  return gulp.src('src/**')
    .pipe(ignore.include({isFile: true}))    // ファイルのみを選択
    .pipe(gulp.dest('dist'));
});
```

ストリームにフォルダが含まれなくなりますが、`gulp.dest()`は出力先フォルダが存在しない場合は自動でフォルダ作成するので、これでちゃんと動きます。

### 例2: フォルダのみをコピーする

```js
var gulp = require('gulp');
var ignore = require('gulp-ignore');

gulp.task('copy', function () {
  return gulp.src('src/**')
    .pipe(ignore.include({isDirectory: true}))    // フォルダのみを選択
    .pipe(gulp.dest('dist'));
});
```

こちらの例では、フォルダだけが階層どおりコピーされます。

### 例3: 他のプラグインとの組み合わせ

"app/"直下のファイルと"app/lib/"配下のファイルをまとめてzipアーカイブを作ろうと思います。

```
project/
├── app/
│   ├── index.js
│   ├── LICENSE
│   ├── lib/
│   │   └── （いろいろなファイル）
│   └── src/
│       └── （いろいろなファイル）
└── dist/
    └── （zipの出力先）
```

一見`gulp.src(['app/*', 'app/lib/**'])`とすれば問題なさそうですが、`app/*`は`app/src`にもマッチするため、そのままではzipには空の"src"フォルダが含まれてしまいます。

```js
var gulp = require('gulp');
var ignore = require('gulp-ignore');
var zip = require('gulp-zip');

gulp.task('zip', function () {
  return gulp.src(['app/*', 'app/lib/**'])
    .pipe(ignore.include({isFile: true}))    // 空の"src"フォルダを除外する
    .pipe(zip('archive.zip'))
    .pipe(gulp.dest('dist'));
});
```

gulp-ignoreでフィルターすることで、空フォルダが混ざるのを防げます。
Macにnode.jsを複数バージョン切り替えられるようにインストール


# 前提・問題意識
- 作業対象のプロジェクトによってnode.jsのバージョンも切り替えたい
    - プロジェクトによって稼働しているnode.jsのバージョンが異なる
    - ローカルPCの開発環境では仮想環境を使っていない


# 概要
- node.jsのバージョン管理には[nodebrew](https://github.com/hokaccha/nodebrew)を利用する

## nodebrewをインストール(homebrewで）

```bash:homebrewコマンドでnodebrewをインストール
$ brew install nodebrew
```

```bash:nodebrew動作確認
$ nodebrew help
```

- ズラズラとコマンドリストが出てくればOK。

```bash:インストールできるバージョンを確認
$ nodebrew ls-remote
```

- バージョンのリストがズラズラ出てくる。
    - 特にターゲットのバージョンがなければ、[Node.js公式blog](http://blog.nodejs.org/)を見てStableの最新版を選んどく。


## node.jsのインストール

```bash:Command(bash)
$ nodebrew install-binary v0.10.32
```
```bash:こんなログでればOK
$ nodebrew install-binary v0.10.32
fetch: http://nodejs.org/dist/v0.10.32/node-v0.10.32-darwin-x64.tar.gz
######################################################################## 100.0%
Install successful
$
```
**インストールしたnode.jsを確認**

```bash:Command(bash)
$ nodebrew ls
```
```bash:実行例
$ nodebrew ls
v0.10.32

current: none
$
```
- ```current```に、現在利用中のnode.jsバージョンが表示される
- 使用のnode.jsをまだ指定してないので```current: none```となってる

##利用node.jsバージョンを指定する

```bash:Command(bash)
$ nodebrew use v0.10.32
```

```bash:実行例
$ nodebrew use v0.10.32
use v0.10.32
$
```

**利用中のnode.js確認**

```bash:Command(bash)
$ node -v
```

```bash:実行例
$ node -v
v0.10.32
$
```

## インストール後のメンテナンス

```bash:インストール済みverのリスト＋利用中verの確認
$ nodebrew ls
v0.10.32
v0.11.14

current: v0.10.32
```


```bash:利用バージョンの切り替え
$ nodebrew use v0.11.14
```

```bash:特定バージョンの追加インストール
$ nodebrew install v0.11.14  # 特定バージョン指定
$ nodebrew install latest    # 最新
$ nodebrew install stable    # 安定版最新
$ nodebrew install v0.10.x   # マイナーバージョン最新
```

```bash:特定バージョンのアンインストール
$ nodebrew uninstall v0.11.14
```

```bash:nodebrew自体のUpdate
$ nodebrew selfupdate
```

## Reference
* [hokaccha/nodebrew · GitHub](https://github.com/hokaccha/nodebrew)
* [node.jsのversionを管理するためにnodebrewを利用する - Qiita](http://qiita.com/sinmetal/items/154e81823f386279b33c)
* [初心者向け：nodebrewでNode.jsをバージョン管理し、環境を整える（MacOSX） | tipsBear](http://tipsbear.com/homebrew-nodebrew-nodejs/)
Unit型の何が偉大なのか説明してみる

# `Unit`型以前 〜C言語とかPascalとか〜

みなさんは数学の時間に**関数**をどのようなものとして習ったでしょうか？

> ある値$x$に対して，ただ1つの値$y$が対応するような関係$y = f(x)$

という感じだったのではないかと思います。

さて、ここで重要なのは「**ただ一つの値 $y$ が対応する**」というところです。これはプログラミングに置き換えて言えば、何らかの値が返ってくる、ということになります。

次のC言語のコードを見て下さい。

```c
int foo(int x) {
  return x * 2;
}

void bar(int x) {
  printf("%d\n", x * 2);
}
```

この`foo`と`bar`は、どちらもC言語の言葉では関数と言います。ですが、この二つには明確な違いがありますね。
`foo`は`int`型の値を返すのに対して、`bar`は値を返しません。なので、`foo`は数学的にも関数と呼べるかもしれませんが、`bar`は全く呼べないでしょう。

PascalやFortranはより明確に分かれていて、値を返すものは**関数** $function$、値を返さないものは**手続き** $procedure$と呼んだりします。

ともかく、同じように引数を取るものに対して、値を返すものと返さないものの二種類が存在してしまっていたわけです。これだと困ることがあります。例えば、関数同士であれば合成できますが、そうでないときは難しいでしょう。


# `Unit`型の登場 〜MLやHaskell、Scala〜

これはあんまりだなぁ、と思ったのかは分かりませんが、その後の言語では`Unit`型というものが登場してきます。

`Unit`型というのは**値が無いことを表す型**で、**値をただ一つのみ持つ**のが特徴です。

これによって上に挙げた`bar`ような手続きも、`foo`と同様に関数として書くことができるようになりました。例えばScalaなら、こんな風に。

```scala
// int foo(int x) { ... に対応
def foo(x: Int): Int = x * 2

// int bar(int x) { ... に対応
def bar(x: Int): Unit = println(x * 2)

// 合成できる！
((foo _) andThen bar)(100)
//=> 400
```

言ってしまえばこれだけなのですけど、それまで手続きと関数に分離していたものが、一つに統合された、ということは結構なことなんじゃないかと思います。


# あとがき

`void`と`Unit`の違いって何なの？　どうして`void`じゃダメなの？　と訊かれたときに答えられるようになる程度の記事だと思います。それでも、こんな些細なことに気付いて感動できるのなら、それはきっと素晴しいことでしょう。こういうことを考えるのが面白いと思う人は、次はいわゆる`null`と`Unit`の違いについて考えてみるといいかもしれません。

ちなみに、この引数の数と返り値の数とは結構深淵な問題で、例えば、多くのプログラミング言語では引数は複数を取るのに対して、どうして返り値は一つなのでしょうか？　この疑問には恐らく、「多値 プログラミング」とかでググれば、答えてくれるページがあるかと思います。反対に、関数型言語ではタプルや関数を返す関数によって、一つの引数に対して一つの返り値が対応するように設計されていたりするわけです。ここでも`Unit`は役に立っていますね。

最後に、短かい記事でしたが目を通していただきありがとうございました。
Vagrantで同じ物理マシン上なのにNFSマウントがすごい遅いと思ったら

# 概要

もともとは、vagrant の share folder が重いあたりから検索をはじめて、NFSを使うとよい記事をみつけた。

[Vagrantのshare folderが遅い時はNFSを使うといいです - Qiita](http://qiita.com/itopan88/items/06d7c7a08f2d681b042a)

やってみた。
しかし、物理マシンとおなじところにある、仮想マシンのNFSマウントがすごくおそかった。
マウントはできているので、lsとかでは気づかないし、小さなファイルでも気づけなかった。

しかし、大きなファイルを処理すると、とんでもなく時間がかかることがわかった。

これが不具合なのか、NFSの設定ミスなのか、なにかの設定ミスなのかがよくわからなかったので調べた。

# 結論

NATを介してNFS接続すると遅い

以下の事柄を確認する。

* 仮想マシンの中における現在の割当（NATではないとおもいこんでしまうことがある）
* Virtualbox上の設定も確認する。

確認のコマンドとしては、たとえば。

```
ip a
/sbin/ifocnfig
```

# どれくらい遅いか検証してみる

TODO: まずはNATが著しく遅いことがわかればよい。
TODO: 書き出し先が、どこなのか確認しておいたほうがよいかもしれない。
TODO: 圧縮や、キャッシュがきいている可能性があるかもしれない。


## NAT

TODO:

## bridge

TODO:

urandom で NFS 側に書き出す。


## host only adapter

ランダムなファイルをNFS上に作る

```
# dd if=/dev/urandom of=/data/random.dd bs=100K count=1000
1000+0 records in
1000+0 records out
102400000 bytes (102 MB) copied, 8.64082 s, 11.9 MB/s
```

書きだしたファイルのサイズを確認

```
# ls -lh /data/random.dd
-rw-r--r-- 1 root root 98M Feb 19 20:33 /data/random.dd
```

NFSから /tmp にコピー

```
# dd if=/data/random.dd of=/tmp/data.dd bs=100K count=1000
1000+0 records in
1000+0 records out
102400000 bytes (102 MB) copied, 0.78363 s, 131 MB/s
```

# 後々わかったこと

top でみても、ロードが高いし、通常どれくらいの時間でおわるか予想が作るならば
それをこえても終わらない時などが怪しい。
【Android】RetrofitのGETリクエストで配列を☆複数☆渡したい

前回書いた[【Android】RetrofitのGETリクエストで配列を渡したい](http://qiita.com/circularuins/items/ed35a39bb25cc0c2fb16)では、複数の配列を渡すという要件が満たせない。

Parameters: {"hoges"=>["1", "2", "3"]} 
は、可能だけど、
Parameters: {"hoges"=>["1", "2", "3"], "fugas"=>["4", "5"]}
は、下記のやり方だとできない。 

```java:ダメな例
@Query("hoges[]") String... hoges, @Query("fugas[]") String... fugas
```
可変長引数は、パラメーター宣言の最後でしか使えないので、これはコンパイル不可。

なので、必要なパラメーター文字列を自力で作るしかなさそう。
渡す文字列は、@EncodedQueryでエンコードしてやる必要がある。

```java:インターフェース側
@GET("/hogefugas.json")
public Observable<Data> getData(
         @EncodedQuery("hoges[]") String hoges,
         @EncodedQuery("fugas[]") String fugas);
```

```java:呼び出し側
String[] hoges = {"1", "2", "3"};
String[] fugas = {"4", "5"};
// パラメータ文字列を作成
String hogeParameter = null;
String fugaParameter = null;
StringBuilder sbHoge = new StringBuilder();
StringBuilder sbFuga = new StringBuilder();
for (String hoge : hoges) {
  if(sbHoge.length() == 0) {
    sbHoge.append(hoge);
  } else {
    sbHoge.append("&hoges[]=");
    sbHoge.append(hoge);
}
for (String fuga : fugas) {
  if(sbFuga.length() == 0) {
    sbFuga.append(fuga);
  } else {
    sbFuga.append("&fugas[]=");
    sbFuga.append(fuga);
}
hogeParameter = new String(sbHoge);
fugaParameter = new String(sbFuga);

// Retrofit + RxAndroid
observable = restAdapter.create(RetrofitApi.class)
                    .getData(hogeParameter, fugaParameter);
```

```java:生成されるリクエスト
/hogefugas.json?hoges[]=1&hoges[]=2&hoges[]=3&fugas[]=4&fugas[]=5
```

####追記
https://github.com/square/retrofit/issues/1479
@EncodedQueryはRetrofit2.0でdepracateなので、こっちになるらしい。

```java:
@Query(encoded = true)
```
ハッカソンのためにLive2DとSDK (CubismSDK 2.1 for Unity) を俯瞰してみる

# 前置き
## モチベーション
* ハッカソン関係の話を伺い、まずは情報の整理をしなくてはと考えた

## この雑記の想定
* ハッカソンとかで短期間で一気に仕上げたい時とかに効率よく学習するためのガイド
* 高速かつイラストを高品質に保ちながらも、インタラクティブなキャラをインタフェースにしたアプリを作りたい時に読む
* Live2D 初級者から中級者（入門してとりあえず表示までは出来たけどその先がわからない人）
* タイトルにもありますが、ハッカソン的にも一気にダダダッと作るためにUnityで行きます

# 最速で学ぶとしたら？
* 後述の[Live2D Manual](http://sites.cybernoids.jp/cubism2/)を読む・漁る

## モデル製作
* [サンプルモデル](http://sites.cybernoids.jp/cubism2/samples)を開いてみる
* 公式の[入門チュートリアル](http://sites.cybernoids.jp/cubism2/beginner-tutorial)を読む
* [関連書籍](http://www.amazon.co.jp/dp/4797376201)を読む

## SDK
* SDKに付属しているプロジェクトのSampleApp1を動かして、読むのが一番早い（naotaro0123さんがまとめた超わかりやすい[記事](http://qiita.com/naotaro0123/items/790db9c3eb7873110d89)）
* SDKのダウンロード先 [link](http://www.live2d.com/download)
* もっとシンプルなものはないのか → SDKに付属しているプロジェクトのSimpleを開いてみると最高にシンプル！！
（Live2Dが対応しているプラットフォームは[ここ](http://www.live2d.com/products/cubism_sdk)で確認）

# Live2D Manual
* [Live2D Manual](http://sites.cybernoids.jp/cubism2/)
* 全体を俯瞰してみたいときに使える公式のまとめページのような場所
* 役立つチュートリアルがたくさんある
* SDKの基本については、左メニューのアプリケーション開発をのところを適当に読む
* ここからいろんな「使える」ページにいける
* わからんことがある → [フォーラム](http://forum.live2d.com/
)あるよ
* モデルが欲しい！ → [サンプルモデル](http://sites.cybernoids.jp/cubism2/samples)とか[ライブラリ](http://library.live2d.com/)とかあるよ
* APIリファレンスどこ？ → [ここ](http://doc.live2d.com/api/core/cpp2.0j/)

# Unityでハマりやすそうな話のまとめ
→ 公式が以下についてまとめてくれてる [link](http://sites.cybernoids.jp/cubism2/sdk_tutorial/tips/texture)

* 半透明部分が黒ずむ
* 半透明部分が発光する
* 境界部分のみが黒ずむ
* ジャギが目立ち、のっぺりした表示になる
* Unityで境界線がでる。
* Unityでテクスチャの解像度が低い
* UnityでRenderTextureの解像度が低い
* 部分的に発光する
* WebGL版で境界線が出る

# 最後に
そういえば最近Live2Dの公式HPのデザインが変わって、SDKダウンロードまでがわかりやすくなった気がしてます！！
goroutine 使い方まとめ

#goroutineとはなにか？
軽量スレッドである、並行処理で複数のスレッドが立てられる
「go」というシンプルなメソッドを使ってスレッドを立てる
「channel」は複数のgoroutineにメッセージを送るもの
また「select」は複数のchannelを管理するものである

mainの関数が終了しないようにgoroutineを制御する仕組みは「channel」か「sync」を使用する  
以下の例はchannelを使用して複数のリクエストを並行処理で書いてある例である。

```:go

package main

import (
	"fmt"
	"log"
	"net/http"
	"time"
)

func getStatus(urls []string) <-chan string {
	statusChan := make(chan string)
	for _, url := range urls {
		go func(url string) {
			res, err := http.Get(url)
			if err != nil {
				log.Fatal(err)
			}
			defer res.Body.Close()
			statusChan <- res.Status
		}(url)
	}
	return statusChan
}

func main() {
	timeout := time.After(time.Second)
	urls := []string{
		"http://example.com",
		"http://example.net",
		"http://example.org",
	}
	statusChan := getStatus(urls)

	for {
		select {
		case status := <-statusChan:
			fmt.Println(status)
		case <-timeout:
			break
		}
	}
}


```

syncを使って書くと以下のようになる

```:go
package main

import (
	"log"
	"sync"
	"net/http"
)

func getStatus(urls []string) {
	wait := new(sync.WaitGroup)
	for _, url := range urls {
		wait.Add(1)
		go func(url string) {
			res, err := http.Get(url)
			if err != nil {
				log.Fatal(err)
			}
			defer res.Body.Close()
			log.Println(url, res.Status)
			wait.Done()
		}(url)
	}
	wait.Wait()
}

func main() {
	urls := []string{
		"http://example.com",
		"http://example.net",
		"http://example.org",
	}
	getStatus(urls)
}

```

```
Do not communicate by sharing memory;instead, share memory by communicating.
```
の原則につきgoroutineの管理はchannelを使用してメッセージを送ってやりとりするのが望ましい。

参考URL
http://gihyo.jp/dev/feature/01/go_4beginners/0005
https://github.com/astaxie/build-web-application-with-golang/blob/master/ja/02.7.md
http://jxck.hatenablog.com/entry/20130414/1365960707
using System;using UnityEngine;したときのObject

Unityで
`System.Convert`とか`System.Action`とか`System.DateTime`とか`System.Exception`とか`System.IDisposable`とか使うようなプログラムを書いていると
`using System;`を書きたくなる。

しかし
`using System;`してしまうと
`Object`と書くときいちいち`UnityEngine.Object`と書かなければいけなくなる。

そんな場合は
`using UniObject = UnityEngine.Object;`と書いておくと`UnityEngine.Object`の代わりに`UniObject`と書くだけでよくなるので、便利。
Spring Boot で Redis Sentinel を参照する

# application.yml
```yaml:application.yml
spring:
  redis:
    sentinel:
      master: mymaster
      nodes: 192.168.10.11:26379,192.168.10.12:26379
```

[Spring Data RedisでRedis Sentinelを利用する - Qiita](http://qiita.com/yoshidan/items/723912c720c8deedf190 "Spring Data RedisでRedis Sentinelを利用する - Qiita")

* spring-data-redis 1.6.1.RELEASE 現在の記載方法
* mymasterはSentinelの設定名で
* 普通のRedisと同様に動き、Spring Session のストアとかも特別な記述はいらない

# 関連
[Redis, Redis Sentinel の導入 - Qiita](http://qiita.com/thrakt/items/f760f2e1d69029349c43 "Redis, Redis Sentinel の導入 - Qiita")
VDI環境とダイナミックデスクトップ利用における落とし穴

# はじめに
仮想デスクトップ（VDI）を導入する際、スタティックデスクトップとダイナミックデスクトップのどちらかを選択することになります。両者の違いは下記のURLを参照してください。
http://fenics.fujitsu.com/outsourcingservice/lcm/workplacelcm/virtualdesktop-basic.html
![virtualdesktop-basic-static.jpg](https://qiita-image-store.s3.amazonaws.com/0/113341/58be3e63-06a3-ac46-002d-61bb610d3357.jpeg)

![virtualdesktop-basic-dynamic.jpg](https://qiita-image-store.s3.amazonaws.com/0/113341/292d5af1-0cc1-1308-99ef-27bc0bb79703.jpeg)

# ダイナミックデスクトップの選択
上記のURLでも紹介されていますが、ダイナミックデスクトップの場合、ログオフする都度更新したデータが消去される、即ちデスクトップイメージがマスターイメージ（ゴールドイメージ、ゴールドパターンと呼ばれることもある）にリセットされます。利用者が常にVDIを使うのではなくたまに利用するようなケースでは、用意するVDI数を利用者数よりも少なくし、コストを抑えて効率よくリソースを使うことができます。
# ドメインコントローラとセキュアチャネル
Active Directory ドメインのメンバーとなっているVDIは、ドメインコントローラとの間の通信を保護するために、セキュア チャネルと呼ばれる通信チャネルを使用します。認証に使用される資格情報などはこのセキュアチャネルによって暗号化され、安全な状態でネットワークを経由してやりとりされます。セキュア チャネルは下の図のように、VDIごとに個別に作成されます。
![domain-controller.gif](https://qiita-image-store.s3.amazonaws.com/0/113341/6a1188b7-2e84-a1b0-842f-bb9c05993043.gif)
※参照先：
http://blogs.technet.com/b/jpntsblog/archive/2009/06/05/3250724.aspx
# ダイナミックデスクトップの落とし穴（その１）
ドメインコントローラとVDIはお互いに、セキュア チャネルを確立するために必要となる "コンピューター アカウント パスワード" を持ち合っています。このパスワードは既定では30日周期で更新されます。更新周期を迎えると、利用者がVDIにログインしたタイミングでパスワードが更新されます。
ダイナミックデスクトップでは利用者がログオフするとデスクトップイメージがマスターイメージにリセットされることから、更新されたパスワードが破棄され更新前のパスワードに戻ることになります。結果としてそのVDIはドメインコントローラと通信できなくなり、次に利用者がそのVDIにマッピングされるとログインができないといった事象、所謂セキュアチャネルの破損として表面化します。
![schannel-2.png](https://qiita-image-store.s3.amazonaws.com/0/113341/ac069781-d8cd-9186-cfb5-22d01ef89c8a.png)

スタティックデスクトップの場合はデスクトップイメージリセットによるセキュアチャネル破損は起きません。
## セキュアチャネル破損からの回復
ダイナミックデスクトップでは一度VDIを消去して再展開するしかありません。VDI数が多いほど時間もかかり、業務影響は大きくなります。
## セキュアチャネル破損の回避方法
ダイナミックデスクトップでは以下のいずれかの方法でセキュアチャネル破損を回避できます。
1. コンピュータアカウントパスワードの自動更新前に以下の作業をVDI毎に実施する。
①VDIを電源オフする
②VDIをダイナミックからスタティックに変更する
③VDIを電源オンする
④VDIをドメインから外す
⑤VDIをドメインに再登録する
⑥VDIをシャットダウンする
⑦デスクトップタイプをスタティックからダイナミックに変更する
⑧VDIを電源オンし、ユーザが使える状態にする
2. ドメインコントローラでコンピュータアカウントパスワードの変更を拒否する。
https://msdn.microsoft.com/ja-jp/library/cc739351%28v=ws.10%29.aspx
3. VDIで定期的なコンピュータアカウントパスワードの定期的な変更を無効にする。
https://msdn.microsoft.com/ja-jp/library/cc785826%28v=ws.10%29.aspx

製品によって1の処理を自動実行する機能が付与されています。しかしながら、何らかの問題でその機能が正常に働かなかった場合の影響が甚大となるため、運用前に十分に検討することをおすすめします。

# ダイナミックデスクトップの落とし穴（その２）
Windows OSのライセンス認証にKMSクライアントキーを利用していない環境の場合、仮想デスクトップ展開後の初回ログオン時にライセンスアクティベーションが必要です。ダイナミックデスクトップの場合、ログオンするたびにライセンス認証を行う必要があり、プロダクトキーあたりのアクティベーション回数の制限に到達してしまい、オンラインでのライセンス認証が利用できなくなります。回避方法としてグループポリシーにて起動時にコマンドラインでアクティベーションを実行してください。
ライセンスアクティベーションコマンド例：
　　slmgr /ato
slmgrにつきましては下記のURLを参照してください。
https://technet.microsoft.com/ja-jp/library/dn502540.aspx
Redis, Redis Sentinel の導入

# インストール

[Redisの最新版をyumでインスコした - Qiita](http://qiita.com/hayashikun/items/01b0658b8fc2a57a47c3 "Redisの最新版をyumでインスコした - Qiita")
Redis を入れると Redis Sentinel というHA構成ツールもついてくる。

# Redis の設定

`/etc/redis.conf`を編集する。
デフォルトで`bind 127.0.0.1`というオプションが入っており、ローカルホストからしか繋がらないので注意。指定なしの場合はどこからでも繋がる。自IPを指定する形で、サブネット指定とかは多分できず、ちょっとめんどくさい……。

外から繋ぐ場合はこの設定と、ポート開放とかが必要。

# Redis スレーブの設定

もう一台用意してスレーブ設定する。
192.168.10.11 master
192.168.10.12 slave
とする。

slave側の`/etc/redis.conf`に`slaveof 192.168.10.11 6379`と指定すればOK。
それぞれの環境で`redis-cli info replication`で設定確認できる。

# Redis Sentinel の設定

Redis Sentinel というHA構成ツールが付いてきており、masterが落ちたらslaveをmasterに昇格させるよう設定する事ができる。
Redisと同居できるので、masterとslaveそれぞれに1つ起動させる形にする。

それぞれの`/etc/redis-sentinel.conf`の`sentinel monitor`セクションを変更
`sentinel monitor mymaster 192.168.10.11 6379 1`
最後の数字(quorum)を1にしているのは、2ついるsentinelの片方が死んでもfailoverできるようにするため。1なら1台がmaster落ちた！判定したら切り替わる。

master落ちた！判定は`sentinel down-after-milliseconds mymaster 30000`といった形で指定でき、デフォルトで30秒。quorumも含めて、別拠点に置くとか本気で高可用性を担保するなら色々考えて弄る必要がある……。

`can-failover`セクションについて触れている記事も多かったがなくなったっぽい。

**指定するのはmasterだけで良い。**
自分のslaveはどれか、自分を監視している他のsentinelはいるかなど、必要な情報はmasterが持っており、masterと通信するだけで全部把握していい感じに動いてくれる！！！
これマジで便利だし、特化してるかわりに超手軽に使える！ Sentinelはいいぞ！

フェイルオーバー時は旧slaveが新masterに昇格し、旧slaveのRedis・各Sentinelの設定ファイルが更新され完全に新しい構成で動くようになる。
旧masterを復帰させると、新masterのslaveとして動くようになる。設定ファイルも起動後に書き換わる。sentinelが設定ファイルにホスト情報を保存しており、それを元に設定しているようだった。

Sentinelはとにかく設定ファイルを書き換えまくるので、検証する時はあらかじめ設定ファイルのバックアップを取っておいたほうが良いと思われます。
[Javaの小枝] 週刊 簡潔データ構造を作る 番外編 5分でわかるLOUDS

# はじめに
前回登場した「完備辞書」というビット列を使うと木構造を非常に小さなデータ量で保持することができる。LOUDS と呼ばれているのであるが、これはなんと1ノードあたり2bitしか用いずに木構造を保持できるというすさまじいものである。

個人的には理解するのに結構苦労したが理解してみれば非常にシンプルな話であり、言いたくはないが最初に読んだ資料が悪かったのではないかとちょっと疑っている。(いや…たぶん自分の頭の問題だとは思うが)

以下では木構造のビット列への変換を極力可視化して5分で理解できるような資料を作成してみた。

# 完備辞書
前回説明したように、完備辞書は以下の二つの操作が定数時間でできるビット列のことだ。

1. 0～n-1番目のビットまでに true もしくは false がいくつあるか数える操作。以降 int rank(lboolean[] v, int nth, boolean b); というような関数として表現する。
2. 先頭から数えてn個目の true もしくは false であるビットがk番目にあるとして、k+1を求める操作。以降 int select(boolean[] v, int n, boolean b); というような関数として表現する。

前回同様、「定数時間」というところを無視して今は下記のようなコードだと思って先へ進むことにしよう。前回も指摘したが rank と select は逆関数になっていることも強調しておく。

```Java:SampleCode.java
public static int rank(boolean[] v, int num, boolean bit) {
    int result = 0;
    for (int i = 0; i < num; i ++) if (v[i] == bit) result ++;
    return result;
}
public static int select(boolean[] v, int nth, boolean bit) {
    for (int i = 0; i < v.length; i ++) if (rank(v, bit, i) == nth) return i;
    throw new IndexOutOfBoundsException();
}
```

# 木構造をビット列に変換する
以下の図(左)のような木構造があったとしよう。この木の各ノードに幅優先で番号を割り当てる。幅優先というのは図(右)で示されるような順番のことを指す。

![LOUDS1.png](https://qiita-image-store.s3.amazonaws.com/0/110035/89feca4a-09f9-ea3c-16b1-911be3916ae6.png)

次に以下の図のように木を斜めに変形し、親子関係のところに三角形を貼りつける。その三角形を幅優先で並べて行く。

![LOUDS2.png](https://qiita-image-store.s3.amazonaws.com/0/110035/1c1c7d3c-ef14-7bc9-dbb4-969269189dee.png)


ここで上(親側、三角形の頂点)のノードだけ横にノード番号を読んでいくと「1,2,3,4,5,6…」と連番になっていることに着目しておいて欲しい。また下(子側、三角形の底辺)のノードだけ横にノード番号を読んでいくと「2,3,4,5,6,7…」とこれまた連番になっている。これは幅優先でノード番号を振った効果でありこれが木構造を簡潔に表現する重要な秘密となっている。また、この三角形の列には同じノードが2回現われることに(親ノード側と子ノード側として)注意しておいて欲しい。具体的には例えばノード6は上側の列には前から6番目の三角形の頂点として現われているし、下側の列には2番目の三角形の底辺部分として存在している。ということで、ノード6の子の情報が欲しい時は6番目の三角形を見れば良いし、ノード6の親の情報が欲しい時は2番目の三角形を見ればよい。

さて、次にこの三角形の列を元にビット列vを作る。作り方は以下に図示した通りであるがノードが上側(親)にある場合false、下側(子)にある場合trueといった形にする。さらに理由は後述するが先頭にtrueのビットを付け加える。

![LOUDS3.png](https://qiita-image-store.s3.amazonaws.com/0/110035/c9ee2b93-db33-6652-3560-b7e040448fc9.png)


以上でLOUDSで用いるLBSと呼ばれるビット列の完成だ。信じられないような話であるが、以下で図示する通り、このビット列さえあれば木構造を辿っていくのに必要な情報は全て入手することができてしまう。

![LOUDS4.png](https://qiita-image-store.s3.amazonaws.com/0/110035/abb7f912-32a1-0852-3882-28cf5d59f000.png)


具体的には以下のような操作となる。(以下ではビット位置をp-1、ノード番号をnとする)

- ビット位置(=p-1)から子側のノード番号(=n)を求める ⇒ n = rank(v, p, true)
- ビット位置(=p-1)から親側のノード番号(=n)を求める ⇒ n = rank(v, p, false)
- ノード番号(=n)から子側のビット位置(=p-1)を求める ⇒ p = select(v, n, true)
- ノード番号(=n)から親側のビット位置(=p-1)を求める ⇒ p = select(v, n, false) 

親子関係の探索は上の図で書いたように隣接したビットを辿っていけば良い。例えばノード12の親の情報はノード12の子側のビット位置を求め、それより前にあるfalseのビットを探しだせば良い。親ノードに対応するビット位置さえわかれば、そのノード番号を求めることは極めて簡単だ。

![LOUDS5.png](https://qiita-image-store.s3.amazonaws.com/0/110035/e4154066-7fce-6c5e-b592-c651ee5e6ec0.png)

各ノードはビット列中に2回(上側と下側)登場するので、ノードの数×2bit + 1bit(先述のトリック用)しかメモリを必要としない。すさまじいまでの省メモリ化である。

おしまい。
vCloud Air で作る Photon OS の初歩

vCloud Air 上でカタログに登録されている Photon OS を利用してみたので紹介します。

# Photon OS 
![Photon.png](https://qiita-image-store.s3.amazonaws.com/0/111746/992eff6e-d160-1b13-5d8e-72bfa7e583a1.png)

// Photon OS とは
Photon OS は vSphere に最適化されたオープン ソースの Linux コンテナです。Photon OS は拡張性が高く、殆どの Linux コンテナ をサポートします (Docker, rkt, Garden from Pivotal など)。
また、サイズが小さい (約 300 MB くらい) ため コンテナを動作するのに快適な環境です。yum や、RPM パッケージ管理コマンドである "tdnf" や、rpm-ostree image-based system バージョン管理も可能です。
*(※ 参考情報の記載の英文を勝手に直訳)*

# 実際に展開してみる
では、vCloud Air 上で実際に Photon OS を展開して Web サービスを実行してみます。
事前に仮想マシンが外部に接続できるように以下の投稿などを利用してインターネットアクセスをできるようにしておきます。

vCloud Air OnDemand サービス上で仮想マシンの展開とインターネット接続方法
http://qiita.com/namatsuda/items/6917d2b24127b78557c5

1. vCloud Air OnDemand にアクセスします。
2. カタログから Photon OS を展開します。
// カタログ
![1.PNG](https://qiita-image-store.s3.amazonaws.com/0/111746/632f6741-703e-21ff-a74b-7e3f92cd7044.png)
// VM詳細
![4.PNG](https://qiita-image-store.s3.amazonaws.com/0/111746/9da4c293-d45c-813b-1378-d4fa379a4974.png)

3. 自動的に設定されたパスワードでログオンします。
4. 以下の一連のコマンドを実行すると、Docker の初期化とデーモン起動設定行います。 
 `systemctl start docker`  (Docker engine の初期化) 
 `systemctl enable docker` (システムの起動後に常に Docker デーモンの起動を行う)
![6.PNG](https://qiita-image-store.s3.amazonaws.com/0/111746/e7bede9c-d8a8-6a37-3e71-d4c2ea44a4c4.png)

5. Photon OS がインターネットに接続されていることを確認します。 
![7.PNG](https://qiita-image-store.s3.amazonaws.com/0/111746/af06542e-b5f3-f1f9-dab9-493630bfc593.png)
 
5. Docker engine が Docker Hub から Nginx Web Server container を入手します。 
 `docker run -d -p 80:80 vmwarecna/nginx`
![9.PNG](https://qiita-image-store.s3.amazonaws.com/0/111746/17c92474-848b-49ad-b8d2-8336cf4aee53.png)

6. コマンドの実行が完了し、Photon OS の IP アドレスに直接ブラウザでアクセスします。
![11.PNG](https://qiita-image-store.s3.amazonaws.com/0/111746/a739cd54-494f-4c68-6c5d-00ae9537e49f.png)

# インターネット上に Web サーバーを公開する
さらに一時的にインターネット上に Web サーバーを公開してみます。

1. vCloud Air にログインして **ゲートウェイ タブ** を選択します。  
![13.PNG](https://qiita-image-store.s3.amazonaws.com/0/111746/3121cf54-b348-b8ef-8c7f-42640eb5336e.png)
2. "GATEWAY オン VDC1" というタイルをクリックし、**NAT ルール** タブを選択し、**+ 追加** ボタンを選択します。
3. この例では、パブリック IP (XXX.XXX.XXX.XXX) へのポート 80 番へのアクセスを 192.168.100.3 へリダイレクトします。  
![15.PNG](https://qiita-image-store.s3.amazonaws.com/0/111746/a45d0185-d108-4376-42a3-31f68c07499c.png)
4. 次に **ファイアウォール ルール** タブに移動して、**+ 追加** ボタンを選択します。
5. この例では、パブリック IP (XXX.XXX.XXX.XXX) へのポート 80 番からのアクセスを全て許可します。
![19.PNG](https://qiita-image-store.s3.amazonaws.com/0/111746/93ddc412-cf02-2845-58a7-d6654bf374b5.png)
6. パブリック IP (XXX.XXX.XXX.XXX) をブラウザに直接入力して、Web ページが見れることを確認します。
![21.PNG](https://qiita-image-store.s3.amazonaws.com/0/111746/8e5fcc48-9f89-b80b-bc99-d33c8afbf411.png)


// 参考情報
VMware Photon OS™
https://vmware.github.io/photon/

VMWARE PHOTON: VCLOUD AIR NETWORK DEPLOYMENT
http://anthonyspiteri.net/vmware-photon-vcloud-air-network-deployment/

Running Project Photon on vCloud Air
https://github.com/vmware/photon/wiki/Running-Project-Photon-on-vCloud-Air

Basic Commands for VMware Photon and Docker
http://www.virten.net/2015/04/basic-commands-for-vmware-photon-and-docker/

Docker on Photon on vCloud Air OnDemand
http://darrylcauldwell.com/docker-on-photon-on-vcloud-air/
JSP スコープ


#スコープ
プログラミング言語において、宣言した変数の適用範囲のこと。変数を宣言した場所により適用する範囲が異なる。
スコープの種類

スコープは主に4種類ある。

主な違いは、データの保存期間（見ることができる範囲）が違う。

・（ページスコープ）

リクエストスコープ

セッションスコープ

アプリケーションスコープ

[参考ページ](http://cartman0.hatenablog.com/entry/2015/12/22/043744#sec-requestScope)
docker infoコマンド

##| はじめに

ここでは[公式リファレンス](http://docs.docker.com/v1.7/docker/reference/commandline/images/)を参考に説明しています。
ただ、バージョンや環境等により若干挙動が異なるかもしれませんが、その点についてはご容赦ください。
また、その他のdockerサブコマンドについては[こちら](http://qiita.com/kooohei/items/8acb82c6c0bf00bfb9bb)に記載していますので、もしよければ参考にしていただければと思います。

##| 使い方

Dockerの環境情報を表示します。

```:使い方
使い方： docker info
```

```bash:デフォルト
$ docker info
Containers: 2
Images: 10
Server Version: 1.9.0
Storage Driver: aufs
 Root Dir: /mnt/sda1/var/lib/docker/aufs
 Backing Filesystem: extfs
 Dirs: 14
 Dirperm1 Supported: true
Execution Driver: native-0.2
Logging Driver: json-file
Kernel Version: 4.1.12-boot2docker
Operating System: Boot2Docker 1.9.0 (TCL 6.4); master : 16e4a2a - Tue Nov  3 19:49:22 UTC 2015
CPUs: 1
Total Memory: 1.956 GiB
Name: default
ID: 7MF2:JTD4:5MOS:LUDN:77GE:W7AG:YKIG:LGXI:5PN7:2U3I:DGCG:IJ42
Debug mode (server): true
 File Descriptors: 12
 Goroutines: 18
 System Time: 2016-02-19T09:26:19.888234798Z
 EventsListeners: 0
 Init SHA1: 
 Init Path: /usr/local/bin/docker
 Docker Root Dir: /mnt/sda1/var/lib/docker
Username: kohei
Registry: https://index.docker.io/v1/
Labels:
 provider=virtualbox
```

・-D
-Dオプションでdockerのデバッグ情報が出力されます。

```
$ docker -D info
DEBU[0000] Trusting certs with subjects: [010
                                             U
kohei] 
Containers: 2
Images: 10
Server Version: 1.9.0
Storage Driver: aufs
 Root Dir: /mnt/sda1/var/lib/docker/aufs
 Backing Filesystem: extfs
 Dirs: 14
 Dirperm1 Supported: true
Execution Driver: native-0.2
Logging Driver: json-file
Kernel Version: 4.1.12-boot2docker
Operating System: Boot2Docker 1.9.0 (TCL 6.4); master : 16e4a2a - Tue Nov  3 19:49:22 UTC 2015
CPUs: 1
Total Memory: 1.956 GiB
Name: default
ID: 7MF2:JTD4:5MOS:LUDN:77GE:W7AG:YKIG:LGXI:5PN7:2U3I:DGCG:IJ42
Debug mode (server): true
 File Descriptors: 12
 Goroutines: 18
 System Time: 2016-02-19T09:26:34.291738346Z
 EventsListeners: 0
 Init SHA1: 
 Init Path: /usr/local/bin/docker
 Docker Root Dir: /mnt/sda1/var/lib/docker
Username: kohei
Registry: https://index.docker.io/v1/
Labels:
 provider=virtualbox
```

以上となります。
【今すぐチェック】iOSアプリが申請できない、ipaが作成できない問題を解決するためのApple認証局周り対応

## 事象概要

キーチェーンにて以下のようなエラーが表示され、それに伴いAppStoreへのアップロードおよび、
deploygateなどの配布ツールへのアプリ配布が出来ない状態になった。

![9c7a611d899c45ead99cab69b1297c1e.png](https://qiita-image-store.s3.amazonaws.com/0/15812/6a285873-a85f-8610-de2e-59381c49e19b.png "9c7a611d899c45ead99cab69b1297c1e.png")

## 原因

2016/2/15にApple Worldwide Developer Relations Certification Authorityという中間証明書が期限切れになっていた。


## 対応概要

 - 古いApple Worldwide Developer Relations Certification Authority(中間証明書)を削除する
 - 最新のApple Worldwide Developer Relations Certification Authority(中間証明書)を追加する


## 手順
以下のURLを参考に行った。

http://qiita.com/nofrmm/items/f51fdb32602c4f92fafd

## 対応後に確認したいこと(対応したけど事象が解決されない場合も有効)

### 確認したいこと１

#### ①「キーチェーンアクセス」を起動し、「キーチェーン」という枠の中の「システム」という項目を選択し、②「分類」という枠の中の「証明書」という項目を選択し、期限切れになっているApple Worldwide Developer Relations Certification Authorityが存在しないことを確認する。


![スクリーンショット 2016-03-02 16.10.18.png](https://qiita-image-store.s3.amazonaws.com/0/15812/1fd9c3f4-3048-7a36-52de-ca6d3ee8e0e3.png "スクリーンショット 2016-03-02 16.10.18.png")


### 確認したいこと２

#### ①「キーチェーンアクセス」を起動し、「キーチェーン」という枠の中の「ログイン」という項目を選択し、②「分類」という枠の中の「証明書」という項目を選択し、発行元が「Apple Worldwide Developer Relations Certification Authority」と書かれている「iOSアプリ申請に必要な証明書」が「有効」になっており、有効期限も現在日時よりも長いことを確認する

![スクリーンショット 2016-03-02 16.13.58.png](https://qiita-image-store.s3.amazonaws.com/0/15812/6e7d7aa0-ce65-8d88-c973-a874cff0be0d.png "スクリーンショット 2016-03-02 16.13.58.png")



### 確認したいこと３

#### ①「キーチェーンアクセス」を起動し、「キーチェーン」という枠の中の「ログイン」という項目を選択し、②「分類」という枠の中の「証明書」という項目を選択し「Apple Worldwide Developer Relations Certification Authority」と書かれている「中間認証局」が「有効」になっており、有効期限も現在日時よりも長いことを確認する

![スクリーンショット 2016-03-02 16.19.41.png](https://qiita-image-store.s3.amazonaws.com/0/15812/e1a0cc0b-153e-6141-7c53-376a58adce54.png "スクリーンショット 2016-03-02 16.19.41.png")
LAST_INSERT_ID()はauto_incrementedでなくてもいいしINSERTじゃなくてもいい

MySQLにLAST_INSERT_ID()という関数があります。auto_incrementedのフィールドがあって、そこにレコードが追加された時に、最後に追加されたidを取得するというものです。

ですが、LAST_INSERT_ID()には引数を渡すことができて、その結果をUPDATEに渡すと、「最後にUPDATEした数値」を取得することができます。

こんな感じ

```sql
-- 準備
CREATE TABLE sequence (id INT NOT NULL);
INSERT INTO sequence VALUES (0);
-- 採番
UPDATE sequence SET id=LAST_INSERT_ID(id+1);
SELECT LAST_INSERT_ID();
```
まず、idというフィールドだけのテーブルを作り、１件だけレコードをINSERTしておきます。auto_incrementedでなくてもいいです。

採番時には、idをインクリメントしてUPDATEします。その際にLAST_INSERT_ID関数を経由してUPDATEします。同一セッションであれば、トランザクションで囲まなくても、先ほどUPDATEしたIDを取得することができています。INSERTじゃないので、レコードは１件のままです。

似たことは、トランザクションを区切ってやったりロックかけたりしてできないくはないのですが、こちらの方がデッドロックの心配もなく、ロジックはシンプルなのでおすすめです。
mcrypt_get_iv_sizeのBLOWFISH＋ECBバグかな?

■確認環境
PHP 5.5.31 (cli) (built: Jan  6 2016 13:27:11) 
PHP 5.6.16 (cli) (built: Nov 26 2015 07:58:22)
***
■mcrypt_get_iv_size　関数マニュアル
[mcrypt_get_iv_size](http://php.net/manual/en/function.mcrypt-get-iv-size.php)
The IV is ignored in ECB mode as this mode does not require it.
Returns the size of the Initialization Vector (IV) in bytes. On error the function returns FALSE. If the IV is ignored in the specified cipher/mode combination zero is returned.

[mcrypt_get_iv_size](http://php.net/manual/ja/function.mcrypt-get-iv-size.php)
ECB モードでは IV は要求されないため、IV は無視されます。
初期化ベクトル(IV)の大きさをバイト数で返します。 エラーの際には FALSE を返します。IV が指定した暗号/モードで無視される場合には、ゼロを返します。
***
■検証

```lang:php
var_dump(mcrypt_get_iv_size(MCRYPT_BLOWFISH,MCRYPT_MODE_ECB));
var_dump(openssl_cipher_iv_length('BF-ECB'));
```

int(8)
int(0)
***

■Webで検証
[php-by-example - mcrypt_get_iv_size](http://micmap.org/php-by-example/en/function/mcrypt_get_iv_size)

```lang:php
$int = mcrypt_get_iv_size (
MCRYPT_BLOWFISH,
MCRYPT_MODE_ECB
);
```
Result  $int = 8

***
結果は同じだ。
難しいことはわからないけれど
Initialization Vectorのバイトサイズが違う値を返すようだ。

なぜか　ゼロ　を返さない。
見落としがあるのかなぁ、関数のバグかなぁ、こういう仕様なのかなぁ  ＿(:з」∠)＿

■参考Link 同じ悩みみたい。
・[Does PHP's mcrypt_get_iv_size actually return zero when the IV is not required?]
(http://stackoverflow.com/questions/11641554/does-phps-mcrypt-get-iv-size-actually-return-zero-when-the-iv-is-not-required)
Phoenix1.1.4とMySQL5.7の組み合わせで発生する問題

# 問題

Phoenixの現時点の最新バージョンである1.1.4と、MySQLにアクセスするためのドライバであるmariaexには、下記のような依存関係があります。

phoenix 1.1.4 -> phoenix_ecto 2.0.1 -> ecto 1.1.3 -> mariaex 0.5.0

mariaexの最新バージョンは0.6.2になりますので、上記の0.5.0はやや古いバージョンということになりますが、このバージョンがどうやらMySQL5.7に対応出来ていないようです。

現時点で、Mac環境でhomebrewを使用してMySQLをインストールすると5.7.xがインストールされると思いますが、その状態でElixir/Phoenixをインストールしてプロジェクト作成後に、

`mix ecto.migrate`

というマイグレーション用コマンドを実行すると、なんのエラーも表示されないまま実行がスタックした状態になると思います。

コードを追ってみた限りでは、どうやら`Mariaex.Connection.query/4`関数が問題箇所のようですが、具体的な原因までは分かりませんでした。

# 回避方法

回避方法は2種類あります。

### 方法1. mariaexの最新バージョンの使用を強制する

mix.exsのdeps関数に下記のように記述します。

`{:mariaex, "~> 0.6.2", override: true},`

これによって、mariaexの最新バージョンがインストールされるようになります。この回避方法に関しては下記の情報を参考にしました。

[Please update the mariaex dependency to 0.6.1 to work with mysql 5.7.9](https://github.com/phoenixframework/phoenix/issues/1397)

### 方法2. MySQL5.6を使用する

homebrewでMySQLをインストールする際に、

`brew install mysql`

ではなく

`brew install homebrew/versions/mysql56`

というコマンドを実行すると、MySQL5.6がインストールされます。

既にMySQL5.7をインストールしてしまっている場合は、下記の記事をご参照ください。

[homebrew mysql バージョンを落とす](http://qiita.com/shizuma/items/1889dfd6055d69edac8e)

# 最後に

ectoの2.0がもうすぐリリースされる(mariaexの0.6以降が使用されるようになる)ようですが、それに合わせて恐らくPhoenixもバージョンアップすると思いますので、とりあえず上記どちらかの対応で応急処置をしておいて、Phoenixの新バージョンリリース後にアップグレードする、という方式が望ましいのではないかと思われます。
SublimeBookmarkパッケージでブックマーク一覧表示にショートカットをつけてみた

##ソースコードの任意の場所に、すばやくジャンプしたい。しかも一覧から選ぶ形で

その行為はブックマークらしく、bookmarkという単語でパッケージを探すと「SublimeBookmark」というものがあったのでいれてみた。

https://github.com/bollu/sublimeBookmark

##ブックマークを追加してみる

任意の行にて、
・「ctrl＋F2」を押せばブックマークをトグルで入れえることができる。
・「ctrl＋シフト＋F2」の場合、ブックマークに名前を追加できる。

##ブックマーク一覧を出してみよう

一覧を出すために、「コマンド＋シフト＋p」をおしてコマンドパレットから「SublimeBookmark: Goto Bookmamrk」コマンドを入力する

![cap01.png](https://qiita-image-store.s3.amazonaws.com/0/95371/bb21b73c-3e8f-0cf7-b427-6d6496b4b0b2.png)


##素晴らしい！

しかし、それすらも面倒なのだ。
なのでコマンドを割り当てることにした。

なんとなく空いている「コマンド＋F1」を割り当てることにした。

##キーマップを追加
<img width="400" alt="スクリーンショット 2016-02-19 17.33.13.png" src="https://qiita-image-store.s3.amazonaws.com/0/95371/0a38ddce-7259-e5d6-ce37-68ea107d4bc9.png">

Key Bindings-Userを選び「Default.sublime-keymap」ファイルを編集する。
以下のファイルのようだ。
......Application Support/Sublime Text 3/Packages/User/Default.sublime-keymap

```:ショートカットコマンドを追加
[{
  "keys": ["super+f1"],
  "command": "sublime_bookmark",
  "args": {
    "type": "goto"
  }
}]
```

これにより、コマンドパレット上の「SublimeBookmark:Goto Bookmark」コマンドが実行される。
よくわからないが、superはコマンドキーのことのようだ。

#再度コマンドパレットからみてみよう

![cap02.png](https://qiita-image-store.s3.amazonaws.com/0/95371/cf36a274-7678-7177-45d9-908281201ead.png)

なんと、追加したコマンドが見えている！
これで達成じゃあ。

#本当は

本当はサブライムの右の全体俯瞰エリア付近に常時表示とかになっていてほしいのだが、いつの日か自分でつくってみようかと思う。

そんだけ！
iptable アクセス拒否メモ

いちいち忘れるのでメモ。薄いです。

```
${_SRC} : アクセス元のIP 192.168.1.0/24 あたりでレンジ指定してもええ
${_DST} : アクセス先ホストのIP リクエストを受け付けるinterface(ethXとか)のIP
${_DST_PORT} : アクセス先ホストのポート

bash
export _SRC=★
export _DST=★
export _DST_PORT=★


echo "iptables -A INPUT -p tcp -s "${_SRC}" -d "${_DST}" --dport "${_DST_PORT}" -j REJECT"

# echo 結果に問題なければコピペして使ってね
# 今のところReject派です。

iptables -L
iptables -L -n -v
```

参考
http://qiita.com/Tocyuki/items/6d90a1ec4dd8e991a1ce
Nginx1.11.1をWindows7にインストールする手順

# やりたいこと

Nginx1.11.1をWindows7にインストールする。

## 前提環境
* OS: Microsoft Windows 7 Professional 6.1.7601 Service Pack 1 (SP1) ビルド 7601 x64

## インストールするソフトウェア
* Nginx: 1.11.1

## 手順

### 圧縮ファイルをダウンロード

[nginx: download](http://nginx.org/en/download.html) で **nginx/Windows-1.11.1** を選択し、圧縮ファイルをダウンロードします。

### 解凍

**nginx-1.11.1.zip** を解凍します。

1. 解凍先のディレクトリ: C:\nginx-1.11.1

### 完了

## 参考文献

* [Windowsにnginxをセットアップする](http://qiita.com/tatuno/items/44ec8130d7544d1534f7)
中国語サイト作成時のフォント指定（font-family）

中国語サイト作成の機会があり調べました。備忘メモ

★繁体字

```css
font-family:"Microsoft JhengHei", "微軟正黑體", 'PMingLiU' , sans-serif;
```

★簡体字

```css
font-family:"Microsoft YaHei", "微软雅黑",'SimSun', sans-serif;
```
Spring Bootで静的リソースのブラウザキャッシュ対応


備忘のためメモ。
要は、ファイル内容に応じたハッシュ値をリソースのファイル名に埋め込んで、ブラウザキャッシュを制御したいのです。


```html:イメージ
<script src="/js/dist/bundle-58c07a622ea3c101af0d90c6e5f2547f.js"></script>
```

## 環境
Spring Boot 1.3.0.RELEASE

## 設定
application.ymlに以下を追加するだけで実現可能。
※ pathsは対象にしたいファイルによって要調整。

```:application.yml
spring:
  resources:
    chain:
      strategy:
        content:
          enabled: true
          paths: /**
```

ハッシュ値を生成しているのは

org.springframework.web.servlet.resource.ContentVersionStrategy#getResourceVersion

の処理。
コード見ると分かりますが、実際のリソースのStreamからハッシュ値を生成しているので、リソースに改修が入ればハッシュ値も変わります。


ハッシュ値とリソースを紐付けるのは

org.springframework.web.servlet.resource.VersionResourceResolver

あたりの処理。

thymeleaf上でリンクURL式で指定しておけば

```html:thymeleaf
<script th:src="@{/js/dist/bundle.js}"></script>
```

実HTMLではハッシュ値付きのパスで出力されます。

```html:HTML（イメージ）
<script src="/js/dist/bundle-58c07a622ea3c101af0d90c6e5f2547f.js"></script>
```
バッチ処理を登録するときに、deployのたびにcronの設定が増えていってしまう。


opsworksでのデプロイの場合には、curentのディレクトリから、
releaseのpathへシンボリックリンクをしているために、デプロイのたびにwheneverの実行をすると、
crontabに追記がされて、同じcronのタスクが沢山実行されている状態になってしまう。

登録時のコマンドを下記の用に実行することで解決。


```shell
bundle exec whenever --update-cron #{app_name}
```

wheneverでは、実行しているディレクトリ名でcronの登録を管理しているようだが、
登録のコマンドの後ろに、アプリの名称を引数として渡すと、
ディレクトリではなく、アプリの名称で管理されるようになりました。

```shell
bundle exec whenever --clear-crontab
```

これでちゃんと削除出来るようになりました。
DroidKaigi2016メモ：Androidエンジニアになって2年の学び

## スライドはここに上がってました
https://speakerdeck.com/ryugoo/android-ensinianinatute-2-nian-falsexue-hi

## 発表者
* Ryutaro Miyashita
* Chatwork, inc.

## どのように学んだか

#### やりたいことを分解する
* ボタンを押して次の画面に遷移する, といった動作をやりたい場合
  - ボタンをクリックする
      - click
      - long press
      - enable/disable
  - 画面遷移する
      - normal
      - sending data
      - transition effexts
* ドキュメントに触れると、
  - setOnClickListener(匿名クラス...
  - 入門書によく書いてある
  - でも調べてみると、
      - 匿名クラス＋インスタンス変数
      - インターフェースを実装
      - Data Bindingなんてものものあったり
      - ButterKnifeみたいなannotationを使ったり
  - いくつもやり方が存在する→分解して1つずつ検証する
  - 書籍やネットでベストプラクティスと言われているものがなぜそう言われているかを調べてみる
      
#### 適切に技術を選ぶ
* 「Googleが発表してるから安心」→本当？
* 常に疑ってかかる
* *初心者だと良し悪しが判断付かないのでは？*→質問で回答が来ていました
* Support Library
  - android.app.Fragment
  - android.support.v4.app.Fragment
  - どっちを使うべき？
  - v4ってなんだろう？
  - 使うべきはv4-support-libraryだった
  - なぜかうまく動かない、クラッシュするのなら、ライブラリのバグの可能性を疑おう
* Support Libraryもたまに自分自身でバグを生み出すことも
  - 慎重になることが大切？
* v14とv7のどちらを選ぶべきか
  - android.support.v14.preference.PreferenceFragment
  - android.support.v7.preference.PreferenceFragment
* 分解して、いちばんいいやり方を見つける
* Material Design
  - なぜ評価される？
  - 感覚的な要素もすべて数字で示されている
  - ガイドラインには基本的には従うべき、だが...
  - Android 4.4 vs Android 6.0
  - 同じMaterial Designでも微妙に表現が違う
  - ポリフィル系デザインライブラリで近づけるべきか？→No
  - 複雑化させすぎない
  - Google自身も、標準ではAndroid4.x系では最低限の実装にしている

#### 実機を使う
* アプリは直接触るもの
* マウスポインタで開発してるとすごく押しづらいアプリになったり
* Genymotionは速い、だがなぜそれが問題なのか？
  - 実機で動かしたときに比べて、エミュレータはI/Oが速すぎる
  - I/O問題の発見が遅れることも
* どのような端末を選ぶべきか
  - 旧Nexus5をおすすめしたい
  - Android 4.4-6.0まで入れられる唯一の端末
  - *シェアを見ていちばん高い端末(XperiaやGalaxy)を選ぶのもいいんじゃないかと*

## 一人の開発とチーム開発の違い

#### 一人開発
* ライブラリの選択が自由
* コードの変更も自由

#### チーム開発
* コミュニケーションの発生
* コーディングガイドラインの発生
* コードレビューの難しさ
  - はじめすごく時間がかかってしまう
  - コーディング規約をちゃんと定めることで時間短縮
  - COOKPADのスタイルガイドラインがオススメ！★
* コーディングの多様性
  - 一人開発のときからコーディングデザインガイドラインを定める
    - コーディング規約
    - コードの設計思想
    - デザインガイド
    - *どのガイドラインを選定すべきか？判断基準についてもう少し詳しく聞きたかった*

## 質疑応答
* いちばんいい？何を判断基準にする？
  - いちばん美しく書ける、あるいは一番短くかけるものを良しとしましょう
  - *先人たちのコードを読むのもいいかも、と思いました*
JSP MVC 

Model → JAVAのクラス
View → JSPファイル
Controller → Servletクラス

モデルは、中心となるデータやメソッドの一般クラスが担う。
リクエストスコープやフォワードはサーブレットファイルである。
これがControl（コントロール）になり要求や応答の窓口になる。

M＝モデル（主な処理を行う一般クラス）
C＝コントローラ（ブラウザからの応答・要求を受け付けるサーブレット）
V＝ビュー（表示を受け持つJSPファイル）

<font color="##ff0000">M</font>→一般的なJAVAクラス
<font color="##ff0000">V</font>→表示を受け持つJSPファイル。データの取得・更新を行う
<font color="##ff0000">C</font>→ブラウザからの応答・要求を受け付けるサーブレット
has_manyとbelongs_toについて。モデルの関連付けされたformの作り方

#まずuserモデルに関連付けるpostモデルを作成する

$ rails g model Post content:text user:references


referencesオプションはモデルと関連付けるときに使うやつで、関連付けたいモデルを指定することで(今回はuserが指定してある)勝手にpostモデルに外部キー(user_id)のカラムを作成してくれる。
このジェネレートの時に
user_id:referencesとしてしまうと、postカラムuser_id_idが追加されてしまうから注意。
userと指定するだけでuser_idとrailsが勝手に判断してくれる。


#userモデルにhas_manyを追加

もうpostモデルにはbelongs_to userが勝手に指定されているのでuserモデルのみにこれを加える

```lang:user.rb
has_many :posts

```
これで、userとpostが関連づいた。


#postのルーティングを設定

```lang:routes.rb

  resources :users 
  resources :posts, :only => [:create, :destroy]
 
```
postはcreateとdestroyしか使わないからonlyオプションで限定する。


#postコントローラーを作成

$ rails g controller posts

#postコントローラーにcreateメソッドを作成

```lang:posts_controller.rb
 
def create
    @post = current_user.posts.build(post_params)
    if @post.save
      redirect_to current_user
    else
      render root_path
    end
  end

```
buildを使うとどのuserがpostしたかを勝手に関連付けてくれる。


#form_forの作成

私はユーザー詳細ページであるusers/show.html.erbでformを作った。

```lang:show.html.erb

<%= form_for(@post) do |f| %>

  <%= f.label :content, "ひとこと" %>
  <%= f.text_area :content %>
  <%= f.submit "つぶやく"%>
<% end %>


```

これでもエラーが出る。
それはこのshowページがuserのshowアクションだから。
なのでusers_controller.rbのshowアクションにも追加をする。

```lang:users_controller.rb
  
def show
    @user = User.find(params[:id])
    @post = current_user.posts.build if logged_in?
  end


```

#formのすぐ下に表示

```lang:show.html.erb

<% @user.posts.each do |p| %>
  <p>
    <%= p.content %>
  </p>
<% end %>

```

あとはcssで自分の好きなデザインにしておしまい。
GitHubの２段階認証でSourceTreeを使えるようにするには

# はじめに
- GitHubには、セキュリティを強化するために2段階認証を有効化することができます
- 2段階認証を有効にすると、GitHubにログインしようとしたときにアプリやSMSで通知を受け取って、ログインを承認するためのワンタイムパスワードを取得・入力しないとログインできないようになる。
- こうすることで、誰かが不正にログインしようとしたとき **通知を受け取る** ことができるようになり、さらに **アプリやSMSで本人が認証** しない限り不正ログインができなくなります。
- 従って、安全に利用するためにはできれば2段階認証を有効化して、リポジトリを守りたいと思います。

しかし困ったことに、SourceTreeなど、２段階認証に対応していない周辺アプリからIDとパスワードによる利用ができなくなってしまいます。
コマンドラインでGitHubを操作するのは面倒なので、GitHubで2段階認証を有効化した後にもSourceTreeが利用できるようにする方法をお教えします。

# 対応方法
従来のID・パスの方法に変わって「トークン」を使ってSourceTreeを利用します。トークンはSourceTreeだけでなく、アプリ毎に発行でき、アクセス権限も細かく設定できるので、セキュリティを確保しながらSourceTreeを利用できる便利な機能です。


## Personal access tokensを発行する
1. GitHubで2段階認証を有効化したあと「Settings」画面で左メニューから「Personal access tokens」画面へ進み、Generate new tokenをクリックして下さい。
![GitHub2段階認証.png](https://qiita-image-store.s3.amazonaws.com/0/94690/c921d6b8-3a0c-642e-f91e-82b68d2fba80.png)
<br><br>
2. 次の画面で、名前（「SourceTree」など適当なもの）を入れ、付与する権限にチェックを入れます。SourceTreeからのアクセスであれば、repoにチェックを入れておけば良いでしょう。
![GitHub2段階認証2.png](https://qiita-image-store.s3.amazonaws.com/0/94690/50b90b23-cdf8-a284-239a-9c45280851f6.png)
<br><br>
3. Generate tokenボタンを押すと、tokenが表示されていますので、これをコピーして、SourceTreeでパスワードとして入力します。（IDは今まで通り、自分のIDを普通に入力します。）
![GitHub2段階認証3.png](https://qiita-image-store.s3.amazonaws.com/0/94690/32ab9d63-4c83-708f-913f-21ee04e08ed7.png)


以上で完了です。
GitHubを2段階認証で保護しつつ、SourceTreeからトークンでアクセスできるようになりました。

なお、ここで作成したトークンを使い回すのは止めておきましょう。トークンはいくらでも発行できますので、必要なアプリに対して個別のトークンを発行し、個別の権限設定をすることで、セキュアに利用することができます。
Chromecast Audioを買う余裕が無いのでRaspberry PiをAirPlay/DLNAレシーバーにしてみた

どうもこんにちは。

巷ではChromecast Audioの日本発売が話題になっているようですが…
**俺には金がない／(^o^)＼**
ということなので、その辺に眠っていたRaspberry Pi 2を使うことにしました。
ちょうど良く **Volumio** なるものを発見したので、作者様に感謝しながらこれを使うことにします。

#必要なもの
- Raspberry Pi (1/2両対応)
- LANケーブル
- (Micro) SD
- Raspberry Piの電源
- AUXケーブル
- 無線LANアダプタ(※オプション)

#1. SD カードに Volumioをインストールする
まず[Volumioのサイトを訪れて](https://volumio.org/get-started/)、イメージを入手しましょう。左の*DOWNLOAD*をクリックして、SourceForgeからZipファイルをダウンロードします。

![Volumio_Download.PNG](https://qiita-image-store.s3.amazonaws.com/0/114292/39d4cc63-b871-7859-3116-c556df33c26a.png)

落としたZipファイルを解凍すると Volumio 1.55PI.img が出てくるので、SDカードをアンマウントしたあと、ddコマンドでSDカードにこんがりと焼きましょう。(当たり前ですがif=" "とof=" "の中は適当なものに置き換えてください)
`sudo dd if="~/Volumio 1.55PI.img" of="/dev/sdX" bs=1M`
(※ddコマンドが無い、Windows の方は[ここ](http://freesoft-100.com/review/win32diskimager.html)を参考にするといいかもしれません)

#2. 起動してみる
イメージの書き込みが終わったら SD カードを Raspberry Pi に戻します。
起動する前にLANケーブルを差し込んで、Raspberry PiとスピーカーをAUXケーブルで繋いでおきましょう。
そしたら、Raspberry Pi を電源に接続して、起動させてください。

#3. 設定
起動が完了したらように思えたら、
http://volumio.local/
をブラウザのアドレスバーに入力します。
すると、この様なコントロールパネルが表示されるので、右上の MENU から System を選択して設定画面に入ることが出来ます。
![Volumio_Screenshot.PNG](https://qiita-image-store.s3.amazonaws.com/0/114292/f2ef9b69-426a-03b3-bb25-d7f702f7b7e3.png)
(※上のURLでコントロールパネルに接続できない場合は、Raspberry PiのIPアドレスで接続してみてください)

* * *

**Player name** は、その名の通りプレイヤー名で、他の機器から接続する際にこの名前が表示されます。特に理由がなければそのままでもいいでしょう。変更したら APPLY を押して、適用し、再起動する必要があります。
![Volumio_PlayerName.PNG](https://qiita-image-store.s3.amazonaws.com/0/114292/a6caf71d-f8f4-2b6d-cd96-1f7d0dae9b98.png)

* * *

**Service Management** ではサービスのオンオフを切り替えます。他の機器から音楽を飛ばして聞く用途では、Airplay と UPNP Control がオンになっていれば問題無いです。こちらも、切り替えたら APPLY を押して、変更を適用する必要があります。
![Volumio_ServiceManagement.PNG](https://qiita-image-store.s3.amazonaws.com/0/114292/a0b0bd75-8e06-6bf6-7ed2-514fb2b55c19.png)

他にも設定はありますが、~~めんどいし~~違いがわからないので、ここでは説明しません。

#4. 音楽を流してみる
いろいろ方法はありますが、今回は Media Go から流してみます。Media Go は Windows 用の音楽管理ソフトで、Throwという名の、DLNAレンダラーでコンテンツを再生する機能を持っています。

再生したい曲を選択して、画面下部のThrowを押したら…
![Throw1.png](https://qiita-image-store.s3.amazonaws.com/0/114292/11e28e3e-69da-95ff-381b-47d48fb5d75b.png)

Volumioが認識されるので、選択してOKを押します。すると…
![Throw2.png](https://qiita-image-store.s3.amazonaws.com/0/114292/57e1b7fb-d3a1-a301-b668-b012887587db.png)

**スピーカーから曲が流れた！**

これでChromecast Audioを買わなくてもスピーカーをネットワーク化出来るね！

(iOS端末、Macは残念ながら持っていないので、AirPlayでは検証していません)

#おまけ
MENU > Network から、無線LANの設定が出来ます。
Network NameにはSSIDを、Securityは使ってる環境に合わせたものを選択し、Passwordには接続するWi-Fiのパスワードを入力して、SAVE CHANGESを押して変更を保存します。
接続できれば、図のように、`Status: Connected ✔` となります。
![WirelessConnection.PNG](https://qiita-image-store.s3.amazonaws.com/0/114292/a7a18b4a-5fea-8b09-04fa-069ce7c72a6b.png)
ベトナムでオフショア開発をしてみる(2) GYAOのベトナム開発は「俺のフレンチ」風

GYAOの窓際エンジニア　玉利です。

GYAOのベトナム開発では、Ruby on Railsを利用しています。

最初にNode.jsでの開発を提示されたため、そちらを試してみたのですが期待する品質の成果物は出てきませんでした。これについては割愛しますが、あまりにしんどくて、ストレスで膵臓炎を起こしダウンするという事件になったので（開発PJの様式美：SEが入院または逃亡）

もしもその手のデスマの話がお好きであれば拙著、[「敏腕派遣SEの火消し日記」](http://itpro.nikkeibp.co.jp/article/Watcher/20060221/230092/?TOC=1)を御覧ください。


![IMG_0053.JPG](https://qiita-image-store.s3.amazonaws.com/0/113049/7c17cbfa-6b6d-8acf-0c6b-4f1f2935ba0e.jpeg)
_ベトナム風水牛のステーキを出社前に朝からいただきます。300円くらいでした。_


GYAOでは主にPHPを使って開発しています。Ruby on Rails(RoR)を使って開発しているのは、社員では私だけ、RoR使いの私は肩身せまいのですが、なぜRoRを使っているのかお話ししたいと思います。

その前に、よく行くビストロで働く友人が、以前は「俺のフレンチ」で働いていました。俺のフレンチといえば、フォアグラの乗った原価率100%のロッシーニ風ステーキが有名です。私も「俺の・・・」グループの店に行ってみましたが、心躍るものはありませんでした。ただしオペレーションが凄いな、自分がオフショア開発で目指すものと一緒だと感心しました。
# 俺のフレンチの秘密
さて、彼の言う「俺のフレンチ」の裏側ですが、こんな内容でした。

* 毎日、すべてのスタッフに昨日の売上・費用・利益がメールで知らせられる
* ☆レシピは完全に定型化されており、だれでも同様に作れるようになっている。忙しい時はホールスタッフも調理するが同じ品質にな
* ロッシーニ風など原価率の高いメニューはあるが、他のメニューは原価低め。
* ワインは**「希望小売価格」+ 1000円**という値付けなので、実はそんなに安くない

料理人としては勉強するものが無かったということで彼は転職していましたが、私は興味津津でした。職人気質のエンジニアにはきっと肌が合わないのですが、均質なサービスを提供できる仕組みは凄いと思います。

ちなみに、俺のシリーズは最初並んでた人から飽きられてきたのか、閉店する店も出たりしているようです。

先日、同様のちょっぴり高級店に行く機会があったのですが、料理は素人がやってるのが手に取るようにわかる出来でがっかりしました。それに比べると「俺の〜」グループは運営レベルが素晴らしいです。

そんな残念な高級店で儲けが出るわけですから、素人に毛が生えたようなスタッフでも、マネジメント次第でそこそこ戦力として使っていけると再認識しました。

# GYAOのオフショアの秘密は「Ruby on Rails」開発

現時点で、オフショア開発に最も適したフレームワークだと断言します（個人的見解）
さらにこれから説明する学習プランは、日本人にとっても最短かつ最強かと思います（さらに個人見解）

利点：

* 教育資料がしっかりしていること
* 各言語を見渡しても最良に近いベスト・プラクティスの英語オンライン資料があること
* 強力な機能、なおかつMITライセンスのライブラリ群
* コード記述量が圧倒的に少ない
* テストの仕組みがデフォルトでカッチリ整備されてる
* RubyMineが超強力
* 日本語のQiitaの資料が山のようにあること（笑）PHPは5,000+, Railsは9,000+


上にあげた条件を見ると良いことづくめに見えるのですが、技術のコモディティ化は既存のエンジニアを幸せにするとは限りません。

欠点：

* 教育資料がしっかりしていること -> エンジニアの腕の差が出なくて評価に困る
* 各言語を見渡しても最良に近いベスト・プラクティスのオンライン資料があること -> 腕の差がでなくて評価に困る
* 強力な機能、なおかつMITライセンスのライブラリ群 -> 自分にしかできない腕の差がでなくて困る
* コード記述量が圧倒的に少ない -> 仕事してないと思われてします
* テストの仕組みがカッチリ整備されてる -> 自分以外でもメンテ出来ると、仕事を他人にとられる可能性がある


オフショア開発では、作業者による品質のブレをいかに無くすかがポイントで、「素晴らしいものを作るよりも、そこそこの品質のものを外れなしに作る」事が重要なのです。どうせ、凄腕ハッカーでは無い凡人である私には、素晴らしいものなんか作れませんから（苦笑）


レストランに例えればミシュラン三つ星じゃなくてサイゼリアです。一流店を食べ歩ける上級エンジニアからするとサイゼリアなんて絶対嫌、と思うでしょうが、私みたいな一般エンジニアからすると「あたりもないけど、味が外れることは無いしコスパは悪くない、普段使いに良い店」という認識です。嘘だとおもったら、会社あがりにサイゼリアで飲んでみませんか？1000円代で飲めて、そこそこ満足してしまいます。

でも、サイゼリアのほうが高級レストランよりよっぽど多くの人を幸せにしてるんです。
centos7 ansible2.0 環境を構築する Vagrantfile

# 手間をかけて ansible 2.0 系をインストールする意義

get_url を SNI に対応させるためです。
詳細は[こちら](http://qiita.com/sugiyasu-qr/items/db25c5233d98f4fd5e63)を参照してください。


# Vagrantfile

* 192.168.33.74 はお好みのアドレスに変更してください。
* proxy 配下でない場合は proxy についての記述を削除ください。

```
# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure(2) do |config|
  config.vm.box = "centos7"

  config.vm.network "private_network", ip: "192.168.33.74"

  if Vagrant.has_plugin?("vagrant-proxyconf")
     config.proxy.http = "http://your_proxy_host:your_proxy_port"
     config.proxy.https = "http://your_proxy_host:your_proxy_port"
     config.proxy.no_proxy = "localhost,127.0.0.1"
   end

  config.vm.provision "shell", inline: <<-SHELL
    # yum proxy
    cat >> /etc/yum.conf  <<EOF
proxy=http://your_proxy_host:your_proxy_port 
EOF
    
    # install ansible v2
    yum -y update
    yum install -y epel-release
    yum install -y rpm-build python2-devel python-setuptools  PyYAML python-jinja2 python-paramiko  python-six python-httplib2 python-keyczar sshpass

    cd /usr/src
    wget https://github.com/ansible/ansible/releases/download/v2.0.0.1-1/ansible-2.0.0.1.tar.gz
    tar xvf ansible-2.0.0.1.tar.gz
    cd ansible-2.0.0.1
    make rpm OFFICIAL=yes
    rpm -Uvh ./rpm-build/ansible-*.noarch.rpm
    
    # install python 2.7.11
    mkdir /opt/python
	cd /usr/src
	wget https://www.python.org/ftp/python/2.7.11/Python-2.7.11.tgz
	tar xvf Python-2.7.11.tgz
	cd Python-2.7.11
	./configure --prefix=/opt/python
	make
	make install
  SHELL
  
end
```