OmniAICreator/Qiita-1.07M huggingface dataset:
PHP でのバッチ処理のパフォーマンス向上に限界を感じたので Go を検討する

この記事は個人的な考えをまとめているだけなので、他の誰かの役にたつ知見はないと思うのでご注意ください。
(ここを起点にノウハウを貯めて個別に記事にしていければとは思っています)

# 問題

私は PHP で作られたアプリケーションを開発していて、業務内容 (≒コードベース) は年々増え、ユーザ数の増加に伴い扱うデータ量も増える一方です。特に大量のデータ処理を行うバッチプログラムでは実行時間をいかに短縮するかが問題になっています。

PHP でできることとしては、以前には以下のようなことをやってきました。

* [PHP 5.2 で並列数を保ちつつ非同期 HTTP 処理](http://blog.yuyat.jp/archives/1987)
* [PHP/MySQL でレコードを N 件ずつバルクインサート](http://blog.yuyat.jp/archives/2018)

これらはこれらでうまく機能し、ナイーブな実装で試算したら 20 時間以上かかるような処理を 2 時間未満で実行できるようになりました。

ところが作って 2 年半経ってみれば、実行時間はいつの間にか 3 時間までになっていました。
これはまだ致命的な問題になっていませんが、そうなるのも時間の問題です。
もっと別の方法を考える必要に迫られてきました。

いろいろな方法があるとはいえ、やはり PHP は並列処理が得意な言語ではありません。
並列処理はまだましで、並行処理についてはかなりの努力を要します。

# 解決案

そこで、この問題を解決するために Go の採用を検討しています。
以下の方針で進めていきます。

* PHP で作ったコンポーネントは Web API 化によりなるべく再利用する。
* Go はそれらを利用したり、データベースにデータを保存する程度にする。ビジネスロジックは書かない。

これまでに作ってきたコンポーネントはそれなりに複雑な処理を行っており、かつ量も多いので、これを丸ごと置き換えるのは現実的ではありません。
ですが、それらは社内の別サービスへの機能提供のためにそれなりに Web API 化していましたし、できていないものについても Web API 化は簡単にできるようなフレームワークができています。
(元々 Microservices 的なアプローチを部分的に取り入れていました)

また、パフォーマンスが問題とはいえ、PHP という処理系の処理速度自体が問題になっているわけではないと考えています。
実行時間の大半は Web API やデータベースの待ち時間なので、処理系の性能自体による伸びしろには期待できないはずです。

# Go を採用する上で解決していくべき課題

単純に Go を採用するだけで問題が解決するわけではありません。
今わかっている課題に分解してみました。

## 並列・並行処理のやり方を学ぶ

PHP は並列・並行処理が苦手です。
対して、Go は goroutine や channel を使ってそれらを上手くやることができるとされています。

* エラーハンドリング: プロセス全体でのエラー回数が一定数に達したら強制終了、といったことも考慮が必要
* 並列数の制御: 単一の Web API に負荷をかけすぎないよう、一定の並列数を保つ必要がある

## リトライ

Web API へのリクエストを行う場合、リトライ機構があると問題が起きてもリカバリしやすくなるでしょう。
ライブラリを探して、なければ作ってみる必要がありそうです。

## MySQL へのバルクインサート

現状のプログラム同様にできる必要があるでしょう。
SQL の組み立てをベタに実装しても良いですが、他でも使いやすそうなのでなるべくライブラリを使うようにしたい。
Install Scala and sbt on Ubuntu 14.04

全く関係ないですがQiitaの使い方メモ
[Markdown記法 チートシート]
(http://qiita.com/Qiita/items/c686397e4a0f4f11683d)

# Install JDK and Scala

```
$ sudo apt-get -y install default-jdk
$ sudo apt-get -y install scala
```

# Scala syntax highlight on Vim (Option)

### Install Vim and Neobundle
```
$ sudo apt-get install vim
$ sudo apt-get install git
$ mkdir -p ~/.vim/bundle
$ git clone https://github.com/Shougo/neobundle.vim ~/.vim/bundle/neobundle.vim
```

### Write something on .vimrc for syntax highlight
```vim:.vimrc
set nocompatible
filetype off

if has('vim_starting')
	set runtimepath+=~/.vim/bundle/neobundle.vim
	call neobundle#begin(expand('~/.vim/bundle/'))

	NeoBundle 'Shougo/unite.vim'
	NeoBundle 'derekwyatt/vim-scala'

	call neobundle#end()
endif


filetype plugin on
filetype indent on

```

# Install sbt
Ref: [Install sbt] (http://stackoverflow.com/questions/28543911/sbt-install-failure-with-aptitude-on-ubuntu-14-04)

> ~~If you install Spark, you don't need to install sbt.~~
> ~~sbt is in Spark.~~

```
$ wget https://dl.bintray.com/sbt/debian/sbt-0.13.7.deb
$ sudo apt-get update
$ sudo dpkg -i sbt-0.13.7.deb
$ sbt
```
($sbt takes a time for first run)

### sbt file structure
Ref: [sbt file structure](http://yomi322.hateblo.jp/entry/2013/02/01/195846)

```
src/
  main/
    resources/
       <files to include in main jar here>
    scala/
       <main Scala sources>
    java/
       <main Java sources>
  test/
    resources
       <files to include in test jar here>
    scala/
       <test Scala sources>
    java/
       <test Java sources>
```

away from sbt, backspace doesn't work correctly. Use Delete.
(now i using mobaxterm)

[シェル](http://www.atmarkit.co.jp/ait/articles/0202/05/news001.html)
[シェル引数](http://shellscript.sunone.me/parameter.html)

```
$ touch scalaproj.sh
$ chmod u+x scalaproj.sh
$ vim scalaproj.sh
```




## Shell script to create Scala project on sbt format

```bash:scalaproj.sh
#!/bin/sh
if [ $# -ne 1 ]; then
  echo "It need 1 argument" 1>&2
  exit 1
fi

mkdir $1
mkdir $1/src
mkdir $1/src/main
mkdir $1/src/test
mkdir $1/src/main/resources
mkdir $1/src/main/scala
mkdir $1/src/main/java
mkdir $1/src/test/resources
mkdir $1/src/test/scala
mkdir $1/src/test/java
```

```
$ ./scalaproj.sh hello
```

## Command about sbt
Type command at project name directory
In this case, in "hello" directory.

```
$ sbt run
$ sbt compile
$ sbt test
```

# memos
ref
http://mobaxterm.mobatek.net/documentation.html#6_8_7
http://www.scala-sbt.org/0.13/tutorial/ja/Manual-Installation.html

Settings
X11
toggle Unix-compatible keyboard

couldn't ... let's use delete key

scala unit test
http://yomi322.hateblo.jp/entry/2013/02/01/195846
deploy files
 ex. build.sbt


create file to test
https://etorreborre.github.io/specs2/website/SPECS2-3.1/quickstart.html



reference
install
http://bach.istc.kobe-u.ac.jp/lect/ProLang/org/scala.html
syntax
http://blog.pg1x.com/entry/2014/08/13/115730-scala-syntax-highlight-with-vim

install neobundle
http://keyamb.hatenablog.com/entry/2013/06/13/164725
new version of neobundle
http://qiita.com/musclemikiya/items/58edc801264aca151446
the place of .vimrc
http://suntree.orsp.net/blog/?p=153
アジャイル開発＆スクラム開発

##アジャイル開発

**概要**
全体のシステムを各機能ごとに分けて、[システム工程](http://qiita.com/ymiyamae/items/c5937520fc8af43ef663)順開発を進めていく。


**特徴**
①最初に想定した機能を全て作らない=リリース時に最高の製品を目指す
②仕様変更の対応に強い
③短期のPDCAサイクルにより、反省を次の周期に活かせる
④顧客満足度の向上
⑤ドキュメントを極限まで省くため、スピーディーに開発できる


例)
機能が３つ,機能A,機能B,機能Cがあるシステムを開発する。

アジャイル開発では、機能ごとにシステム工程の順番で進めていく。今月は機能Aの要件定義から結合テストまで。来月は機能Bの要件定義から結合テストまで。こうすることによって、途中で機能Aの仕様変更が起きた場合にも、機能B,機能Cの作業を少し先送りにして対応することができるのである。

要するに
####「WEBサービス・アプリケーションにはアジャイル開発が向いている」
ということである。






##スクラム開発
**概要**
チームで仕事の進めるためのフレームワーク
　
**メリット**
*フレームワークなのでカスタマイズしつつ導入が可能。
*短周期なので、変更に柔軟になる。
*進捗状況を管理しやすい


**役割**

プロダクトオーナー:プロダクト・バックログの作成と優先順位付けの最終責任を持つ。
　　　　　　　　　 チームが生み
出す成果物の方向性をを決める
スクラムマスター:チームの仕事を妨げている障害物を取り除き、解決へ促す
開発チーム:2週間のスプリントを通して機能追加を行い、動作するソフトウェアをオーナーに届ける

**工程**
プロダクトオーナー:バックログにストーリーを作成。チームに対して、プロダクトとして実現したい価値を定義し、優先順位を決める。
　　　　　　　　　　　　⬇︎

開発チーム:チームは2~4週間のスプリントを通して、機能追加を行い動作するソフトウェアをオーナーに届ける
　　　　　　　　　　　　⬇︎

プロダクトオーナーからの要求に対して、2~4週間の期間内に実現可能な範囲に計画し、タスクに分解する
　　　　　　　　　　　　⬇︎

　　　　　　　　　　　　デモ
これを繰り返す。
 

###**バックログ**
スクラムでは２つのバックログを定義
**プロダクト・バックログ**
*プロジェクトを完了するために必要なすべての機能が優先順位付けされた常に変化するマスターリスト
*プロダクトの全体の進捗状況への影響の把握・伝達がスムーズになる

**スプリント・バックログ**
*プロダクト・バックログを元にスプリントで実現する仕様をまとめたリスト
*期間内にタスクを終わらせられるかを検討

**対応ツール**
*Redmine
Xcode, Swiftで環境変数を設定し、参照する方法

## 設定

[1] Product > Scheme > Edit Scheme を選択

[2] Environment Variablesの項目で任意のKeyとValueを設定

![environment_variable_1.png](https://qiita-image-store.s3.amazonaws.com/0/30253/4e0ea4bf-d763-8de3-db30-98a8ec37cfce.png)


## 参照

```Swift
  
        let env = NSProcessInfo.processInfo().environment
        if let value = env["設定したKey"] as? String {
            println(value) //=> 1234
        } else {
            // Environment variable not set (or not a string)
        }
```
plenv+perl-build環境の設定

---

### 本体のインストール
- plenv
>$ git clone git://github.com/tokuhirom/plenv.git ~/.plenv

- ~/.zshenvの設定
>$ sudo vim ~/.zshenv

 以下の内容を設定する。
 
 <pre>
export PATH=$HOME/.plenv/bin:$PATH
eval "$(plenv init -)"
 </pre>

- 設定を反映させる
> $ source ~/.zshenv

- Perlをビルドするためにperl-buildをインストールする
>$ git clone git://github.com/tokuhirom/Perl-Build.git ~/.plenv/plugins/perl-build/

- インストール可能なPerlを確認する
>$ plenv install -l


 <pre>
Available versions:
 5.6.0
 5.6.1-TRIAL1
 5.6.1-TRIAL2
 5.6.1-TRIAL3
(省略)
 5.21.5
 5.21.6
 5.21.7
 5.21.8
 5.21.9
</pre>

#### Perlのバージョン変更

- 現在のバージョンの確認

 >$  perl -v
 
 <pre>
This is perl 5, version 20,
subversion 1 (v5.20.1) built for armv7l-linux
Copyright 1987-2014, Larry Wall

 Perl may be copied only under the terms of either the Artistic License or the
GNU General Public License, which may be found in the Perl 5 source kit.

 Complete documentation for Perl, including FAQ lists, should be found on
this system using "man perl" or "perldoc perl".  If you have access to the
Internet, point your browser at http://www.perl.org/, the Perl Home Page.
 </pre>
 
 v5.20.1だということがわかる。
- 現時点の最新版v5.21.9をインストールする
>$ plenv install 5.21.9 -Dusethreads

- デフォルトで使用するバージョンとして設定する
>$ plenv global 5.21.9

- バージョンが変わったことを確認する
>$ perl -v

 <pre>
This is perl 5, version 21, subversion 9 (v5.21.9) built for armv7l-linux-thread-multi
(with 1 registered patch, see perl -V for more detail)

 Copyright 1987-2015, Larry Wall

 Perl may be copied only under the terms of either the Artistic License or the
GNU General Public License, which may be found in the Perl 5 source kit.

 Complete documentation for Perl, including FAQ lists, should be found on
this system using "man perl" or "perldoc perl".  If you have access to the
Internet, point your browser at http://www.perl.org/, the Perl Home Page.
</pre>
EC2でsudoersの設定に失敗し、sudoが使えなくなったときの対応


# Goal

* オペレーションミスによりEC2でsudoが使えなくなった問題を解消する
* ちなみに、以下の条件でsudoのデッドロック状態が起こる
	* rootパスワードが分からない
	* /etc/sudoersまたは/etc/sudoers.d以下のファイルがシンタックスエラーになっている
	* /etc/sudoersまたは/etc/sudoers.d以下のファイルの編集権限がrootユーザのみ
		* sudoがエラーになるため、rootユーザになることができない
		* sudoers設定を変更しようにも、問題のファイルを変更も削除もできない

常識とは思いますが、この問題を避けるために`visudo`または、`visudo -f /etc/sudoers.d/{sudo設定ファイル名}`を使うべきです.
今回はプロビジョニング作業のため設定操作が手続き処理なので、visudo使うのが比較的難易度高いため/etc/sudoers.d以下にファイルを直接配置してしまってました.
（visudoのコマンドを使って、ChefできればItamaeでコマンド実行できるいい方法ご存知のかたいれば教えてください）

# Manual

※ 対象サーバの停止が必須の手順です
※ 作業用のインスタンス１機の起動が必須です

![スクリーンショット 2015-04-05 17.46.18.png](https://qiita-image-store.s3.amazonaws.com/0/36978/e5a9642f-18fc-a788-6009-b172e566fae3.png "スクリーンショット 2015-04-05 17.46.18.png")

EC2 production: sudo不可になった問題のサーバ
EC2 inspection: sudoers修正するための作業用サーバ
EBS1 : 問題のsudoersファイルを抱えたブロックストレージ
EBS2 : 作業用サーバがデフォルトでマウントしているブロックストレージ

## (1), (2)EBS1をEC2 inspectionにアタッチする

* EC2 productionをShutdown
* EC2 productionからEBS1をデタッチ
	* EC2管理画面のサイドバー Volumes > 対象のボリューム(EBS1)を選択 > Detach Volume
	* Detach前に、サーバが認識しているブロックデバイス名を確認しておく（/dev/xvda,/dev/sda1など）
* EC2 inspectionを用意し、起動しておく
* EC2 inspectionにEBS1をアタッチ
	* EC2管理画面のサイドバー Volumes > 対象のボリューム(EBS1)を選択 > Attach Volume
	* アタッチされたときのブロックデバイス名を確認しておく（/dev/xvdf1など）

## (3)EC2 inspectionでファイルシステムにアクセスできるようマウント

```
# root@EC2 inspection

ls -l /dev/xvdf1
  # 新しいデバイスが認識されていることを確認
mkdir /emergency_mount
  # マウント先を作成しておく

mount -t ext4 /dev/xvdf1 /emergency_mount

mount
  # /emergency_mountにマウントされたことを確認
df
  # /emergency_mountにマウントされたことを確認
ls -l /emergency_mount/
  # ファイルツリーが見えていることを確認
```

## (4)sudoersファイルを修正する

```
# root@EC2 inspection

vi /emergency_mount/etc/sudoers.d/test
  # 問題のファイルを修正する
```

## (5),(6)EC2 productionとEBS1をひもづけ直す

* EC2 inspectionからEBS1ブロックデバイスをumount

```
# root@EC2 inspection

umount /emergency_mount

mount
  # /emergency_mountがアンマウントされたことを確認
df
  # /emergency_mountがアンマウントされたことを確認
```

* EC2 inspectionにアタッチしていたボリュームをデタッチ
* EC2 productionに作業前と同じブロックデバイス名（/dev/xvda,/dev/sda1など）でアタッチし直す
	* これが間違っているとサーバ起動できません

# Reference

http://ubuntuforums.org/showthread.php?t=2193540
Object#tryの逆が欲しい

レシーバが`nil`のときになにかしたいのが`Object#try`。

```rb
# a.b.c.try(:d)
if a.b.c
  a.b.c.d
else
  nil
end
```

逆に、レシーバを使ってなにかの処理をした結果が`nil`のときに、`nil`じゃなくてレシーバにするのが欲しい。

```rb
if a.b.c.test?
  a.b.c.d
else
  a.b.c
end
```

`Object#return`（仮名）というのはどうか。

```rb
a.b.c.return {|x| x.d if x.test? }
a.b.c.return(:d)
a.b.c.return(:d, if: :test?)
```

最初のパターンはこんな感じ。

```rb
class Object
  def return
    yield(self) || self
  end
end
```
fluentdをインストールしてみたメモ


CentOS6.5環境にfluentdを導入して試したメモ

##1.vagrantで環境用意

こんな感じで環境を用意（boxは事前にCentOS6.5を用意）

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

# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
VAGRANTFILE_API_VERSION = "2"

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
  config.vm.box = "centos65x86_64"
  # config.vm.network :private_network, ip: "192.168.33.10"
end
```

あとはお決まりのように

```
$ vagrant up
$ vagrant ssh
```

確認とアップデート

```
$ cat /etc/redhat-release 
CentOS release 6.5 (Final)

$ sudo yum update
```

##2.fluentdのインストール

[nstalling Fluentd Using rpm Package](http://docs.fluentd.org/articles/install-by-rpm) を参考に、td-agentをインストール（実行内容が知りたい場合は、シェルスクリプトの内容を直接見ればいい）。

```
$ curl -L http://toolbelt.treasuredata.com/sh/install-redhat-td-agent2.sh | sh
```

##3.td-agent起動と動作確認

インストールができているのか起動して、簡単な動作確認を行う。
起動は、以下から

```
$ sudo /etc/init.d/td-agent start
Starting td-agent:                                         [  OK  ]

$ sudo /etc/init.d/td-agent status
td-agent (pid  2691) is running...
```

`/etc/td-agent/td-agent.conf`がデフォルトの設定が記述されており、sourceディレクティブがtype:httpの8888ポートとなっている。
また、matchディレクティブはタグが「debug.**」で、type:stdout（`/var/log/td-agent/td-agent.log`に出力）となっているので、これを使って動作確認をしてみる。

```
$ curl -X POST -d 'json={"json":"message"}' http://localhost:8888/debug.test

$ tail -1 /var/log/td-agent/td-agent.log
2015-04-05 07:30:14 +0000 debug.test: {"json":"message"}
```

確認できた。ただ、時刻が気になる場合は、以下のように設定する。

```
$ sudo cp /usr/share/zoneinfo/Japan /etc/localtime
$ cat /etc/sysconfig/clock
ZONE="Asia/Tokyo"
```
SoftLeyerのベアメタルサーバー(BMS)をISOブートする



SoftLeyerのベアメタルサーバー(BMS)をISOブートする手順である。
通常、特にSoftLeyerに何も依頼しなくてもユーザーでISOブートが可能である。

まず、起動するISOを入手する。今回は起動してメモリーをテストするだけの[Memtest86+のISO](http://www.memtest.org/#downiso)を利用する。これなら小さいしホスト区画に影響を与えない。
もちろん、導入用ISOなら、今回の手順で導入可能である。

![ISOの入手](https://qiita-image-store.s3.amazonaws.com/0/71995/6ddaef53-cf3a-bcb3-0a43-4f87c008f408.png)

http://www.softlayer.com/VPN-Access から好きなアクセスポイントを選んでSSL-VPNを確立してPrivate Netoworkにアクセスできるようにする。内部で転送されるのでマシンがあるDCと接続先は違って構わない。
これで、Private IPで提供されるベアメタルのIPMIもにアクセスできるようになる。

![SoftLayer VPN-Access](https://qiita-image-store.s3.amazonaws.com/0/71995/064593ae-12ef-3762-a36b-a4cf67eb0062.png)

[Device → Device List](https://control.softlayer.com/devices)でデバイスの一覧を出し、デバイス名をクリックしてDevice Detailsの画面にする。Remote MgmtのタブにManagement IPとしてIPMIのアドレスが表示されている。アクセス用のユーザーID、パスワードもここから確立できる。

![IPMI情報の確認](https://qiita-image-store.s3.amazonaws.com/0/71995/044081d1-0f95-5805-b0f4-9967bc295919.png)

ブラウザーでManagement IPにアクセスする。ポータルで確認したIDとパスワードでログインする。

![IPMI ログイン](https://qiita-image-store.s3.amazonaws.com/0/71995/f941f3c6-8350-3c99-a431-bb45e63ed5ef.png)

IPMIの管理画面が表示されるので Remote Console Preview をクリックする。Java Web Startでコンソールが起動する。

![IPMIの管理画面](https://qiita-image-store.s3.amazonaws.com/0/71995/c865f79f-ef83-9c0f-9088-68ab79010bfa.png)

ツールバーのVirtual MediaからVirtual Storageを選ぶ。

![irtual MediaからVirtual Storageを選択](https://qiita-image-store.s3.amazonaws.com/0/71995/90a81c23-2c19-4437-d3c7-47766145550f.png)

ローカルPCのISOファイルを利用するときは、タイプとしてISO Fileを選択する。

![1.png](https://qiita-image-store.s3.amazonaws.com/0/71995/aed47ccf-71d4-fb1b-d2a6-f3c7b8ae57d2.png)

Open imageでローカルPCのISOファイルを選択後、忘れずにPlug Inを押す。

![ISOファイルのPlug In](https://qiita-image-store.s3.amazonaws.com/0/71995/5408a11c-7262-49ac-319d-af6974c1bfc7.png)

Power ControlでSet Power Resetする。

![Set Power Reset](https://qiita-image-store.s3.amazonaws.com/0/71995/c6c2bfac-9902-b1ea-b1ee-8d88339b4f4b.png)

Rebootしてくる。この画面はシステムによって異なるらしい。

![ロゴ画面](https://qiita-image-store.s3.amazonaws.com/0/71995/6b57a6ac-16ff-9180-5c41-1591a68321fd.png)

しばらくすると、ISOから起動してくる。導入用CDであれば、ここから導入できる。

![1.png](https://qiita-image-store.s3.amazonaws.com/0/71995/794a753c-279f-997c-a305-daa249919abf.png)

もとに戻すのは、Virtual StorageでPlug Outして、Set Power Resetする。これで通常通りHDから起動してくる。
RedShiftでよくつかったpsqlコマンド


psqlから接続している場合、postgresqlとほぼ同じコマンドを使用することが可能です。


- ユーザーの一覧
``\du``
 
- 権限の一覧
``\dp``
- テーブルの一覧
``\dt``
 
- カラムの一覧（sortkey、distkey、encodingの表示は無し）
 ``\d テーブル名``

 　
 上記以外にも、使えるコマンド（オプション）はありますので是非お試しあれ 　


 ---
 
 
ちなみに、コマンドではないですが、以下のSQLで詳細な情報を見る事が出来ます。

- ↓各テーブルのカラム構造を取得できます
``SELECT * FROM pg_table_def``
 
- ↓sortkeyやencodeの効果も確認できます
``SELECT * FROM SVV_TABLE_INFO``
fizzbuzzについて、パターンが増える場合に対応するケースを作ってみた

haskellの勉強を始めたので投稿してみた

```FizzBuzz.hs
module FizzBuzz where

import Data.Monoid

-- | fizzbuzzについて、パターンが増える場合に対応するケース

type ModCondition = Int
type Message = String
type FBPattern = [(ModCondition, Message)]

-- | 3:fizz 5:buzz 7:woof
-- >>> fb 1
-- "1"
-- >>> fb 3
-- "fizz"
-- >>> fb 5
-- "buzz"
-- >>> fb 7
-- "woof"
-- >>> fb 15
-- "fizzbuzz"
-- >>> fb 21
-- "fizzwoof"
-- >>> fb 35
-- "buzzwoof"
-- >>> fb 105
-- "fizzbuzzwoof"
fb :: Int -> Message
fb n = case foldl1 mappend [conv n | conv <- fbMessConvert] of
	""    -> show n
	mess  -> mess

fbMessConvert = map getMess fbPatterns

getMess (c,m) n
	| n `mod` c == 0 = m
	| otherwise = mempty

fbPatterns :: FBPattern
fbPatterns = [(3,"fizz"),(5,"buzz"),(7,"woof")]

main :: IO()
main = print $ map fb  [1..100] 
```
sublime textでのコメント行のReindentについて

例えばこんなコードを書いて


```rb
namespace :db do
	desc "Fill database with sample data"
	task populate: :environment do
		admin = User.create!(name: "Example User",
			email: "example@railstutorial.jp",
			password: "foobar",
			password_confirmation: "foobar",
			admin: true)

		#  User.create!(name: "Example User",
		#  email: "example@railstutorial.jp",
		#  password: "foobar",
		#  password_confirmation: "foobar")

	99.times do |n|
			name  = Faker::Name.name
		email = "example-#{n+1}@railstutorial.jp"
			password  = "password"
			User.create!(name: name,
				email: email,
				password: password,
				password_confirmation: password)
		end

		users = User.all(limit: 6)
		50.times do
			content = Faker::Lorem.sentence(5)
			users.each { |user| user.microposts.create!(content: content) }
		end
	end
end
```

Reindentしたら、こうなると思ったけど。

```rb
namespace :db do
	desc "Fill database with sample data"
	task populate: :environment do
		admin = User.create!(name: "Example User",
			email: "example@railstutorial.jp",
			password: "foobar",
			password_confirmation: "foobar",
			admin: true)

		#  User.create!(name: "Example User",
		#  email: "example@railstutorial.jp",
		#  password: "foobar",
		#  password_confirmation: "foobar")

		99.times do |n|
			name  = Faker::Name.name
			email = "example-#{n+1}@railstutorial.jp"
			password  = "password"
			User.create!(name: name,
				email: email,
				password: password,
				password_confirmation: password)
		end

		users = User.all(limit: 6)
		50.times do
			content = Faker::Lorem.sentence(5)
			users.each { |user| user.microposts.create!(content: content) }
		end
	end
end
```

実際はこうなった

```rb

namespace :db do
	desc "Fill database with sample data"
	task populate: :environment do
		admin = User.create!(name: "Example User",
			email: "example@railstutorial.jp",
			password: "foobar",
			password_confirmation: "foobar",
			admin: true)

		#  User.create!(name: "Example User",
		#  email: "example@railstutorial.jp",
		#  password: "foobar",
		#  password_confirmation: "foobar")

99.times do |n|
	name  = Faker::Name.name
	email = "example-#{n+1}@railstutorial.jp"
	password  = "password"
	User.create!(name: name,
		email: email,
		password: password,
		password_confirmation: password)
end

users = User.all(limit: 6)
50.times do
	content = Faker::Lorem.sentence(5)
	users.each { |user| user.microposts.create!(content: content) }
end
end
end
```

どうも関数呼び出しを複数行で書いてコメントアウトすると起こるらしい

一行に書き直すとちゃんとインデントできた。むずかしい。
Spring MVC integration for Swaggerのバージョン２をSpringBootで実行する

##はじめに
Spring MVC integration for Swagger(https://github.com/springfox/springfox )のversion2のチュートリアル(https://github.com/springfox/springfox/blob/master/transitioning-to-v2.md )が分かりにくいので補足用のメモ。

##利用ライブラリ
mavenリポジトリとして http://oss.jfrog.org/artifactory/oss-snapshot-local/ を設定。現在のところsnapshotしかないので、snapshotの設定を利用します。

##SpringのConfig
SwaggerSpringMvcPluginを使う方式から、Docketというクラスを使う方式に変更されている。SpringSwaggerConfigは不要になっています。
Configファイルで使うアノテーションは、@EnableSwagger2になっています。
Docketには、API一覧を作る対象を設定するpathsを設定します。これはサンプルでは分かりにくいですが、Google GuavaのPredicateを使って記述するようになっています。com.google.common.base.Predicatesをstaticインポートすると、基本的な構文(orなど）が使えるようになりますので、これでパスを設定します。
またサンプルにある、Docket#groupName("business-api")という設定ですが、これはグループ分けができる機能で、URLパラメータに?group=business-apiとすることで、指定のDocketに対するAPI一覧を取得することができます。

ApiInfoですが、引数が増えていますのでv1からの移行であれば適当にString型の引数を足します。

```java
import static com.google.common.base.Predicates.containsPattern;
import static com.google.common.base.Predicates.or;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

import com.google.common.base.Predicate;

@Configuration
@EnableSwagger2
public class Swagger2Config {

	@Bean
	public Docket swaggerSpringMvcPlugin() {
		return new Docket(DocumentationType.SWAGGER_2)
				.select().paths(paths()).build().apiInfo(apiInfo());
		//groupName("business-api")でURLパラメータ?group=businessでアクセスできる
	}

	@SuppressWarnings("unchecked")
	private Predicate<String> paths() {
		return or(containsPattern("/*"));
	}

	private ApiInfo apiInfo() {
		ApiInfo apiInfo = new ApiInfo("My API", "",
				"terms of service", "", "", "", "");
		return apiInfo;
	}
}
```

##アクセスURL
以前はhttp://localhost/api-docsでしたが、version２からは http://localhost/v2/api-docs になっています。Docketに対してgroupNameメソッドでグループ指定した場合は、 http://localhost/v2/api-docs?group=グループ名 でアクセスします。
MACにHomebrewをインストールした時の備忘録

#はじめに
手持ちのmacにzshをインストールしようとしたら
-bash: brew: command not foundとなり
Homebrewをインストールしたときの備忘録

#Homebrewのインストール

`$ ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"`

#インストール出来たか確認

`$ brew -v`

バージョンが表示されれば完了
【初級】AngularJS導入

【初級】AngularJS導入

AngularJSを試したい時、最低限必要なパッケージ及び導入手順を記述する。※ 2015年時点

## 前提条件
AngularJS 1.3(Versionが違うと全然違う)
Mac or Linux?

## 必要なもの
Homebrew
> OS X用パッケージマネージャー
> 今回はインストールを割愛する為
> 以下のURL参考
> http://brew.sh/index_ja.html

AngularJS
> 今回、目的としているFramework
> https://angularjs.org

node.js
> サーバサイドJavaScript
> http://nodejs.jp

webpack
> 静的なファイルの依存関係を解決し結合したり分割するツール
> http://webpack.github.io

npm
> Node.jsのモジュールを管理するためのツール
> https://www.npmjs.com

glup
> Node.js上で動くタスク自動化のためのビルドツール
> http://gulpjs.com

bower
> フロントエンド用のパッケージマネージャ
> npmからフロントエンド用を分けるために使用
> npmに全部混ぜて活用も可能
> http://bower.io

karma-cli
> karma用のコマンドラインインターフェース

karma
> テスト自動環境環境
> http://karma-runner.github.io/0.12/index.html

yeomen
> ビルドツール(AngulerJS推奨?)
> http://yeoman.io

Chrome
> Batarangツール使用の為、ブラウザ固定

## 導入順番
1. node.js
2. npm
3. bower
4. プロジェクトごとに管理する
5. mkdir test
6. yeomen
7. webpack 
8. karma-cli
9. npm init
10. bower init
11. karma
12. AngularJs

## コマンド
* node.js<br>homebrewを用いてインストールする<br>(Linuxはyumとかでよろしく)

```bash
%brew install node
%node -v
v0.10.36
```

* npm<br>homebrewを用いてインストールする<br>(Linuxはyumとかでよろしく)

```bash
%brew install npm
%npm -v
2.3.0
```

* bower<br>npmを用いてインストールする<br>グローバル環境にインストール

```bash
%npm install -g bower
May bower anonymously report usage statistics to improve the tool over time? (Y/n) Y or N ←どっちでも可
%bower -v
1.4.1
```

* yeomen<br>npmを用いてインストールする<br>グローバル環境にインストール<br>yo -vやると色々聞かれる

```bash
%npm install -g yo
```

* webpack<br>npmを用いてインストールする<br>グローバル環境にインストール<br>ローカルでもいいかも

```bash
%npm install -g webpack
```

* karma-cli<br>npmを用いてインストールする<br>グローバル環境にインストール

```bash
%npm install karma-cli -g
```


* karma<br>npmを用いてインストール<br>ローカル環境にインストール

```bash
%npm install karma
```

* AngularJs<br>bowerを用いてインストール<br>ローカル環境にインストール

```bash
%bower install angular
```

以上。
Cordova プラグインを Meteor プロジェクトに追加する方法


# Cordova プラグインの追加

```bash
# * <Plugin ID>: Cordova プラグインの識別ID
# * <GitHub Repository>: Cordova プラグインのソースコードが置いてある GitHub リポジトリURL
# * <Commit Hash>: 追加する Cordova プラグインの git Commit のハッシュ値

meteor add cordova:<Plugin ID>@<GitHub Repository URL>/tarball/<Commit Hash>
```

## 例1: [nl.x-services.plugins.actionsheet](http://plugins.cordova.io/#/package/nl.x-services.plugins.actionsheet) プラグインを追加する

```bash
meteor add cordova:nl.x-services.plugins.actionsheet@https://github.com/EddyVerbruggen/cordova-plugin-actionsheet/tarball/f956c492eb7ca565afef662e206244b0b2d5f407
# => added cordova plugin nl.x-services.plugins.actionsheet
```


## 例2: [com.unarin.cordova.beacon](http://plugins.cordova.io/#/package/com.unarin.cordova.beacon) プラグインを追加する

```bash
meteor add cordova:com.unarin.cordova.beacon@https://github.com/petermetz/cordova-plugin-ibeacon/tarball/98d246f966a654cdba06a2bf63976272ebbd9df4
#=> added cordova plugin com.unarin.cordova.beacon
```

# 参考URL

* [meteor - How to add cordova plug that haven't registration on plugins.cordova.io? - Stack Overflow](http://stackoverflow.com/questions/26624649/how-to-add-cordova-plug-that-havent-registration-on-plugins-cordova-io)
Raspberry Pi の OpenCV で顔検出をしたら Mac より 40倍〜80倍遅かった話（報告）


#始めに
掲題の件, Raspberry Pi で顔検出をやってみると、もの凄く遅く lena_color_512 で 3.2 秒もかかってしまいました
![lena_color_512.jpg](https://qiita-image-store.s3.amazonaws.com/0/46544/eb3e53d9-43fc-ef1d-a5af-595a096dfca4.jpeg "lena_color_512.jpg")

↑これを、↓のように認識するのに 3.2秒かかりました

![face_lena_color_512.jpg](https://qiita-image-store.s3.amazonaws.com/0/46544/5ee448bc-13df-df6c-0902-42759b388406.jpeg "face_lena_color_512.jpg")

Mac で実行した結果と比較すると、40倍〜80倍ほど遅いようです

![スクリーンショット 2015-04-05 15.32.06.png](https://qiita-image-store.s3.amazonaws.com/0/46544/7a234cbc-b6b6-52aa-0cb0-a6bccb47dae9.png "スクリーンショット 2015-04-05 15.32.06.png")

Mac は Core i5 1.3GHz で OSX 10.9.4 です
RPi は A+ です。サンプルピクチャを SD 上ではなく、 RAMDISK に置いた環境 （上の RPi-RD）でも試してみましたが、結果はあまりかわっていませんので入出力ネックではないようです

# やったこと
ついこのあいだ発行された MagPi の [Issue32](http://www.raspberrypi.org/magpi/issues/32/)  P48 〜 P49 の”FACE DETECTION WITH OPENCV”の解説記事のサンプルプログラムfacedetect.py をそのまま使い、サンプルピクチャーとして
[standard test images](http://www.imageprocessingplace.com/downloads_V3/root_downloads/image_databases/standard_test_images.zip) を tif -> jpg に変換したもので実行してみました。

facedetect.py はフォルダ内の各 jpg ファイルについて、顔と認識した領域の有無に加えて処理に要した時間をだしてくれます。

さらに、 facedetect.py の下から7行目あたりの haarcascade のパスを私の Mac でのパス（私の場合は /usr/local/Cellar/opencv/2.4.10/share/OpenCV/haarcascades/）に変更し、同様に Mac で実行してみました


# 終わりに
CPU性能が違うとはいえ、なぜ二桁も差がでるのか不思議でした。ご意見、および方法や考察等の間違いのご指摘等、なにかありましたらごご遠慮なくコメントをいただければ大変ありがたいです
rails4でGithubにpushする時に大苦戦



<b>1.getgubの使い方を見て真似ていた所、error発生。

githubは前々からLibraryの質問等で使っていたものの、railsアプリをpushすることが無かった。今回初めてpushしようとしたら大苦戦したの巻。

memo.yomukaku.net

このサイトが、情報は古いものの、簡潔明快であったために参考にする。

最後、以下のコマンドをポチっと...あれ

$ git push origin master

error: failed to push some refs to 'https://github.com/XXXX/YYYY.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

--help見てなんとかしてくれ的な、非常に納得のいかないerror。

<b>2.これは兄貴御立腹です。
https://youtu.be/DEWIKYrQ4B0
GARLICBOYS - 兄貴御立腹 - YouTube

<b>3.対策は作業用ブランチを一度かますこと（初回だけ）

git branch temp1
git checkout temp1
temp1というブランチを作成する。

git pull origin +master:temp1
この時点でoriginからファイルがすっぽり消えるけど、落ち着いて作業

git diff temp1 master
temp1とmasterを比較する。全くもって不毛な作業。

git checkout master
git marge temp1
temp1からmasterにmergeする作業。意味なし。

この後pushすると行けるようになる。何故なんだろう。

$ git push origin master

<b>4.なぜブランチを初回だけかます必要があるのが、git不勉強につき不明です。

御指南ご鞭撻を宜しくお願いします。
参考サイト：
http://d.hatena.ne.jp/snaka72/20100602/1275496817
SE・プログラマ必見！~システム開発とはなんぞや~


今回はウォーターフォールモデル開発とアジャイル開発に使われる工程に沿って紹介します。

##工程の流れ
![koutei.jpg](https://qiita-image-store.s3.amazonaws.com/0/74135/3071d201-355a-28b2-56d1-b6a73678db81.jpeg "koutei.jpg")



##要件定義

要件定義において、ユーザーの意見というのはザックリした考えが多い。そこで、ユーザーの不完全な意見をベンダー側で積極的にガイドする必要がある。少ない人数の中で、多くのアイデアを必要とするのでブレーンストーミングするのも良い方法である。



**システム要件定義**:ユーザにヒヤリングを行い、システム化する範囲や対象業務を明確にし、新システムに必要な機能を検討する。

**ソフトウェア要件定義(外部設計)**:画面のレイアウトと画面操作時の動作、画面上にどのような入力欄,ボタンを配置するのか、その処理について定義して文書化する。
帳票に何を印刷するのか、どのようなレイアウトで印刷するのかなどを決める。データのやりとりについての設計




##基本設計
**システム方式設計**:ハードウェアの構成、調達するソフトウェアパッケージ、システムの処理方式など、要件定義書に記載された機能の実現に必要なシステムの構成を決める。

**ソフトウェア方式設計(内部設計)**:外部設計で設計した内容を、具体的にどのように実装するかを設計する。
システム開発者の為の設計なので、システム開発担当者だけで行うのが一般的である。
**ソフトウェア詳細設計(プログラム設計)**:実装の直前に、各プログラムの動作や処理の流れを詳細に定義する。

##開発
**プログラミング**:モジュールごとにプログラミングを作成。
**単体テスト**:作成したモジュールごとに、バグがないか検証。

##結合テスト
単体テストをクリアしたモジュールを結合し、各設計書に定義された機能要件どおりに動作するか
詳細はこちら　→http://gihyo.jp/lifestyle/serial/01/ipa-terminology/0013

##システムテスト
システム全体を対象に行われるテスト。製品として完成したものを本番とほとんど同じ環境でテストを行う。

銀行では第３者に数十日間のテストを行ってもらうのこと。

システムテストも最終的な結合テストといえますが、結合テストは設計・構造の妥当性を確認する － 要求とそれに対するシステムの妥当性を確認するものです。 結合テストは対象物の内部構造に焦点を合わせ、システムテストでは人と対象物に焦点を合わせます

##運用・保守
**移行**:実際の稼働環境へシステムを移す。
*一斉移行:ある時点でシステムから新システムへ一気に切り替える
*順次移行:システムの機能や支店・部門などの単位ごとに新システムへ切り替えていく

**保守**:一度完成したシステムも、ハードウェアの故障への対応や、業務の変化に伴う修正などの保守が随時行われる。
*予防保守:障害の発生を事前に防ぐために定期的に行われる
*事後保守:障害発生後に行われる
Ubuntu(x64) on VirtualBox 環境構築 Tips


#環境：Ubuntu 14.10


## 新規に ｘ64 VM が作れない
新規で Linux 選んでも、バージョンの一覧には 32 bit しか選択肢がない。

利用しているシステムの UEFI で 「Intel VT（ Intel Virtualization Technology ）」を有効にする。

## Ubuntuインストール中に画面が崩れる
以下を参照して解決した。

[Ubuntu14.10 を VirtualBox 環境にインストールしようとしたら画面が砂嵐だった件](http://mayoneez.hatenablog.com/entry/2014/11/14/022157)

## 解像度が VGA から切り替えられない
デバイスメニュー｜ Guest Additions の CD イメージ挿入..
Guest Additions のインストールが済んだら、再起動。
これで解像度が切り替えられるようになっているはず。

## クリップボードが共有できない
VirtualBox Managaer の設定で「クリップボード共有」を設定する。

![スクリーンショット 2015-04-05 15.00.54.png](https://qiita-image-store.s3.amazonaws.com/0/30578/4a84dc05-8b6b-d13c-aa97-7212c2975da6.png "スクリーンショット 2015-04-05 15.00.54.png")

## （必要なら）32 bit プロセスが動くかか確認
カーネルのコンパイルオプションは /boot 直下にある config で始まるファイルにある。
以下のように、CONFIG_IA32_EMULATION=y となっていれば、大丈夫。
![スクリーンショット 2015-04-05 15.06.03.png](https://qiita-image-store.s3.amazonaws.com/0/30578/0c01443f-6fb2-4545-a415-6546177a963b.png "スクリーンショット 2015-04-05 15.06.03.png")
BPMN エンジン camunda のサンプルを日本語化

BPMN 2.0プロセスエンジン の一つに [camunda](https://camunda.com/) があります。
[camunda のオンラインデモ](http://camunda.com/bpm/demo/online/)

その[チュートリアル](http://docs.camunda.org/latest/guides/getting-started-guides/developing-process-applications/) をなぞるとともに、少しだけ日本語化してみました。
[https://github.com/katoy/camunda-sample](https://github.com/katoy/camunda-sample)

## スクリーンショット
![shot-005-2015-04-05.png](https://qiita-image-store.s3.amazonaws.com/0/14958/7505e3b0-3caf-6173-5251-d2f7b69190ce.png)

## 環境
- MacOSX 10.2.2
- eclipse Kepler Service Release 2
- Apache Tomcat/7.0.5  [camunda-bpm-tomcat-7.2.0.tar.gz](http://camunda.org/release/camunda-bpm/tomcat/)
- Java SE 7 (1.7.0_55)
- Apache Maven 3.3.1

camunda についての情報は、日本語のものは少ないです。
すこしでも参考になれば幸いです。
Unity5.0系+Parse+iOSで発生するエラーを取る方法

こちらを参考に１つのファイルを作成すれば解決できます。
http://forum.unity3d.com/threads/unity-5-parse-ios-nsurlerrordomain-error-1012.308569/

引用
"Assets/Plugins/iOS/CustomConnection.mm"　を作成する
これだけでUnity5.0系+Parse+iOSで発生するエラーがなくなる。

> #include "Unity/WWWConnection.h"
> @interface UnityWWWCustomRequestProvider : UnityWWWRequestDefaultProvider
> {
> }
> + (NSMutableURLRequest*)allocRequestForHTTPMethod:(NSString*)method url:(NSURL*)url headers:(NSDictionary*)headers;
> @end
>  
> @implementation UnityWWWCustomRequestProvider
> + (NSMutableURLRequest*)allocRequestForHTTPMethod:(NSString*)method url:(NSURL*)url headers:(NSDictionary*)headers
> {
>     NSMutableURLRequest* request = [super allocRequestForHTTPMethod:method url:url headers:headers];
>    
>     // let's pretend for security reasons we dont want ANY cache nor cookies
>     request.cachePolicy = NSURLRequestReloadIgnoringLocalCacheData;
>     [request setHTTPShouldHandleCookies:NO];
>    
>     return request;
> }
> @end
>  
> @interface UnityWWWCustomConnectionDelegate : UnityWWWConnectionSelfSignedCertDelegate
> {
> }
> @end
>  
> @implementation UnityWWWCustomConnectionDelegate
> - (NSCachedURLResponse*)connection:(NSURLConnection*)connection willCacheResponse:(NSCachedURLResponse*)cachedResponse
> {
>     // we dont want caching
>     return nil;
> }
> - (void)connection:(NSURLConnection*)connection didReceiveResponse:(NSURLResponse*)response
> {
>     [super connection:connection didReceiveResponse:response];
> }
> @end
>  
> IMPL_WWW_DELEGATE_SUBCLASS(UnityWWWCustomConnectionDelegate);
> IMPL_WWW_REQUEST_PROVIDER(UnityWWWCustomRequestProvider);
SpringBootでEmbeddedWebContainerを起動させない

もともとSpringBootでWebアプリとして実装していたものに、一部Serviceクラスやモデルクラスを流用したバッチ処理を加えたい時、バッチ用のMainクラスを以下のように作成しても、内蔵のWebコンテナが起動してしまいます。

```java
public static void main(String[] args) throws Exception {
  SpringApplication.run(BatchMain.class, args);
}
```

これは、SpringApplicationクラスの初期化コードに、クラスパス上にjavax.servlet.Servletもしくはorg.springframework.web.context.ConfigurableWebApplicationContextがあるかどうかを確認して、webEnvironmentというboolean変数にtrueを入れてしまうからです（このフラグがtrueだと、Webコンテナが動く）

このため、初期化後にフラグをfalseにすることで、Webコンテナが動作しないようにできます。

```java
public static void main(String[] args) throws Exception {
  SpringApplication application = new SpringApplication(BatchMain.class);
  application.setWebEnvironment(false);
  application.run(args);
}
```
foreachとmapの使い分け

どうもforeachとmapの違いがわからなかったので整理

どういう時に使うか
foreachは配列の要素数だけ要素を使った処理を行いたいときと、その配列自身を操作したいときに使う
mapはある配列から新しい配列を作りたいときに使う

機能的な違いは？
foreach：配列を巡回して、値、インデックス、配列自信をもとに関数を実行する。返り値は特に無し
map：配列を巡回して値を元に関数を実行する。実行関数の返り値から新しい配列を作る

見返してみると英語の意味がそのままですね。
CentOS 7 に vsftpd を入れたが動きません！

いろいろググってみましたが、デフォルトの設定ではまず動かないようです。こんなメッセージが出て起動できません。

    Job for vsftpd.service failed. See 'systemctl status sftpd.service' and 'journalctl -xn' for details.

vsftpd.conf を下のように設定したら無事起動できました。
`
listen=NO
listen_ipv6=YES
`
これって変な設定です。今の環境では、ipv6 は使ってないし、listen=NO というのも変です。

さらにログインしようとすると 530 Permission denied. と出てしまいました。

これは、

userlist_enable=YES
userlist_deny=NO

となっていたせいで、/etc/vsftpd/user_list に使用するユーザを追加していなかったためです。

`\# vsftpd userlist`
`\# If userlist_deny=NO, only allow users in this file`
`\# If userlist_deny=YES (default), never allow users in this file, and`
`  中略`
`games`
`nobody`
`user  \# <== 追加 (実際のユーザidに変えること)`

起動方法ですが

    sudo systemctl start vsftpd.service

とします。

もし、localhost 以外からアクセスできなければファイアウォールではじかれているかもしれません。下のようにしてファイアウォールをOFFにして試してみます。

    sudo systemctl stop firewalld

さらに、デフォルトでブート時に自動起動されないので次のコマンドで自動的に起動するように設定します。

    sudo systemctl enable vsftpd.service

自動的に起動されているかは、ブート後に下のようにしてポート21 が LISTEN になっているかで確認できます。

`[user@localhost ~]$ ss -nat
State       Recv-Q Send-Q               Local Address:Port                 Peer Address:Port
LISTEN      0      50                               *:3306                            *:*
LISTEN      0      128                              *:22                              *:*
LISTEN      0      100                      127.0.0.1:25                              *:*
ESTAB       0      0                     192.168.1.70:22                   192.168.1.83:49882
LISTEN      0      128                             :::80                             :::*
LISTEN      0      32                              :::21                             :::*
LISTEN      0      128                             :::22                             :::*
LISTEN      0      100                            ::1:25        `                     :::*

動作確認がOKだったら、下のようにしてファイアウォールで FTP を許可します。

    sudo firewall-cmd --add-service=http --zone=public

これでOKかと思ったらさらに問題が発生しました。

550 Failed to open file.
553 Could not create file.

FFFTP で上のようなエラーが出てしまい GET も PUT もできません。これは、SELinux でftpd_full_access が OFF になっているためだそうです。次のようにして SELinux 自体を無効化すれば解決します。

    sudo setenforce Permissive

ftpd_full_access を ON にする方法もありますが、実運用のサーバでなければこれで十分です。

[同じ記事](http://bonk.red/show.php?id=36)
この記事は上の記事のパクリではありません(作者が同じ)。
keychainでsshのprivate鍵パスワード入力回数を減らそう

## インストール

```bash:インストール
apt install keychain
```

## 起動

```bash:
keychain ~/.ssh/id_rsa
```

```bash:複数鍵がある場合は追記
keychain ~/.ssh/id_rsa ~/.ssh/work_id_rsa
```

## 利用方法

```bash:
source ~/.keychain/srv1-sh
```

```bash:接続してみる
ssh myhome
```

鍵のパスワード入力が省略されていることを確認。


# keychainを使わない場合

```bash:
ssh-agent bash
ssh-add
ssh-add ~/.ssh/work_id_rsa

ssh myhome
```

# zshの場合

参考: [CentOSでkeychain - とほほのN88-BASIC日記](http://d.hatena.ne.jp/hide-K/20081209/1228800441)

~/.zshrcに以下追記

```bash:~/.zshrc
/usr/bin/keychain \
  $HOME/.ssh/id_rsa \
  $HOME/.ssh/id_rsa_home \
  $HOME/.ssh/id_rsa_work

source $HOME/.keychain/$HOSTNAME-sh
```

## bashの場合

```diff:~/.bashrc
 if [ -d "$HOME/bin" ] ; then
     PATH="$HOME/bin:$PATH"
 fi
 export LANG=ja_JP.UTF-8
 export TERM=xterm-256color
+/usr/bin/keychain ~/.ssh/id_rsa ~/.ssh/work/id_rsa
+source $HOME/.keychain/$HOSTNAME-sh

```
yumで良く使うコマンド

* インストールされているか確認

```linux
yum list installed | grep xxxxx
```

* 外部リポジトリを有効化

```linux
yum --enablerepo=remi,epel install xxxxx
````

* パッケージがダウンロード可能か確認

```linux
yum search xxxxx
yum --enablerepo=remi,epelsearch xxxxx
```
phpbrew install時OpenSSLが見つからない場合

# 現象

    $ phpbrew install 5.6.6 +default +mysql

で php5.6.6をインストールしてみようと試みたところ

    configure: error: Cannot find OpenSSL's libraries

とインストールログにOpenSSLが見つからないと言われました

# 現象が起きた環境

    $ cat /etc/redhat-release
    CentOS Linux release 7.1.1503 (Core)
    $ arch
    x86_64

## OpenSSLのロード先

phpbrewのデフォルトのロード先は確か

    /usr/lib/

だった気がするので
読み込み先を指定するようにしてあげます。
yumかつ64bit環境でOpenSSLを入れている場合付加するパラメータは下記の通り
※ 自分でコンパイルして導入したひとは任意の値に変更してください

    +openssl=/usr -- --with-libdir=lib64

## パスを指定してインストールを行う

```
    $ phpbrew install 5.6.6 +default +mysql +openssl=/usr -- --with-libdir=lib64

　　　　　　　　# brew で入れてる人向け
    $ phpbrew install 5.6.6 +default +mysql +openssl=$(brew --prefix openssl)
```

    ===> phpbrew will now build 5.6.6
    ===> Loading and resolving variants...
    Checking distribution checksum...
    Checksum matched: b198117ee1d44c8143e030cee15f1b52
    ===> Distribution file was successfully extracted, skipping...
    Found existing build.log, renaming it to /home/dimgraycat/.phpbrew/build/php-5.6.6/build.log.1428205834
    ===> Configuring 5.6.6...
    ...(中略)...
    Congratulations! Now you have PHP with 5.6.6 as php-5.6.6
    To use the newly built PHP, try the line(s) below:
    
        $ phpbrew use php-5.6.6
    
    Or you can use switch command to switch your default php to php-5.6.6:
    
        $ phpbrew switch php-5.6.6

    Enjoy!

ということで、インストール成功です

2016.12.05: 追記)
かれこれ１年以上たつみたいですが、まだこの減少は起きてるのかな？

2017.08.08: 追記)
macな人はbrewでopensslのリンクが貼れなくなっているので、
`+openssl=$(brew --prefix openssl)` にすることで対応できます。
Sinatra で 'undefined method join for string' によりエラー内容が確認できない場合


http://route477.net/d/?date=201502

```
gem 'sinatra', git: 'https://github.com/sinatra/sinatra.git',
               ref: '5f6168bfc92280892e819df524d4508cf9032f6d'
               # for https://github.com/sinatra/sinatra/issues/961
```
こちらでOKとなりました。ありがたい。
Visual Studio2012, 2013のdebug高速化

1. 「マイコードのみを有効にする」にチェック
![SnapCrab_NeighborhoodOp - Microsoft Visual Studio (管理者)_2015-4-5_11-38-30_No-00.png](https://qiita-image-store.s3.amazonaws.com/0/13567/74dcaebc-f8fa-812b-6a7f-a42f5c418bcc.png)
***

2. 「Microsoftシンボルサーバー」にチェック
「このディレクトリにシンボルをキャッシュ」に任意のフォルダを指定。
![SnapCrab_NeighborhoodOp - Microsoft Visual Studio (管理者)_2015-4-5_11-33-55_No-00.png](https://qiita-image-store.s3.amazonaws.com/0/13567/bac28691-317a-7af0-2236-7495d03a3e26.png)
***

3. アプリケーションをデバッグ実行
すると「すべてのシンボルを自動的に読み込む」ボタンが活性化するので、クリック。読み込みが開始される。
![SnapCrab_NeighborhoodOp (実行中) - Microsoft Visual Studio (管理者)_2015-4-5_12-4-37_No-00.png](https://qiita-image-store.s3.amazonaws.com/0/13567/55b916ec-66d2-6e2b-e04c-742f629adb90.png)
***
4. 2でチェックした「Microsoftシンボルサーバー」のチェックを外す

VisualStudio2012とVisualStudio2013express for Webにて確認済みです。
MVCやEntity Frameworkなどで高速化を実感しました。
すぐにというよりは徐々に効いてきたような感覚でした。
Rubyでのメソッドの委譲方法をまとめてみた

※ この記事は[江の島エンジニアBlog](http://blog.enogineer.com/)の「[Rubyでのメソッドの委譲方法をまとめてみた](http://blog.enogineer.com/2015/03/26/ruby-delegate/)」の転載です。

Rubyでは委譲の方法がいくつかあるのでまとめてみました。インスタンスメソッドの委譲方法とクラスメソッドの委譲方法をまとめています。チームで開発している場合はあらかじめ方法を統一しておくと良いと思います。

## インスタンスメソッドを委譲する

まずはインスタンスメソッドを委譲する方法をいくつか紹介します。

### `delegate`を使う

```ruby
class User
  delegate :name, :age, to: :info
end
```

ここでは`name`と`age`メソッドを`info`に委譲しています。

### `Forwardable.def_delegators`を使う

```ruby
class User
  extend Forwardable
  def_delegators :info, :name, :age
end
```

同じ例を`Forwardable`の`def_delegators`を使って書くとこんな感じになります。

### `Forwardable.def_delegator`を使う

```ruby
class User
  extend Forwardable
  def_delegator :info, :name, :info_name
end
```

`def_delegator`を使うとメソッド名をカスタマイズすることもできます。

この例では`info_name`で`info.name`を参照できるようにしています。

`def_delegators`と引数の扱いが違うので気をつけましょう。

## クラスメソッドを委譲する

クラスメソッドを委譲する方法もいくつかあります。

### `class << self`を使う

```ruby
class User
  class << self
    delegate :log, to: :instance
  end
end
```

`class << self`と`delegate`を使って委譲します。

### `SingleForwardable`を使う

```ruby
class Logger
  extend SingleForwardable
  def_delegators :instance, :log
end
```

`Forwardable`の代わりに`SingleForwardable`を使えばクラスメソッドを委譲出来ます。

もちろん`def_delegators`を使ってもOKです。

### まとめ

ということでRubyで委譲をする方法をいくつかご紹介しました。
MySQLでクエリの実行時間を手っ取り早く計測する

:::note info
この記事は[haracane.github.io](https://haracane.github.io/)の「[MySQLでクエリの実行時間を手っ取り早く計測する](https://haracane.github.io/2015/03/26/mysql-time/)」のTL;DRです。
:::

## TL;DR

    $ time ((for i in $(seq 1 100000); do echo "SELECT * FROM records;";done) | mysql -u mysql database > /dev/null)

詳しくは以下のブログ記事をご覧ください。

https://haracane.github.io/2015/03/26/mysql-time/
MySQLでインデックスや外部キー制約をリネームする

:::note info
この記事は[haracane.github.io](https://haracane.github.io/)の「[MySQLでインデックスや外部キー制約をリネームする](https://haracane.github.io/2015/03/26/mysql-rename-index/)」のTL;DRです。
:::

## TL;DR

5.6系だとRENAME INDEXができないので以下のSQLを実行する。

```sql
ALTER TABLE posts
  ADD KEY index_posts_on_category_id(category_id),
  ADD UNIQUE KEY index_posts_on_url(url),
  DROP KEY new_index_posts_on_category_id,
  DROP KEY new_index_posts_on_url,
  ADD CONSTRAINT
    posts_blog_id_fk
      FOREIGN KEY(blog_id)
      REFERENCES blogs,
  DROP FOREIGN KEY new_posts_blog_id_fk;
```

詳しくは以下のブログ記事をご覧ください。

https://haracane.github.io/2015/04/05/mysql-deadlock/
S3に置いたGzip圧縮済みCSVファイルをRubyで読み込んでみた

※ この記事は[江の島エンジニアBlog](http://blog.enogineer.com/)の「[S3に置いたGzip圧縮済みCSVファイルをRubyで読み込んでみた](http://blog.enogineer.com/2015/03/25/load-s3-gz-csv/)」の転載です。

Rubyでaws-sdkを使ってS3に置いたGzip圧縮したCSVファイル読み込む手順をご紹介します。

## S3のキーを設定する

S3にアクセスするためにまずキーの設定を行います。

```ruby
AWS.config(
  access_key_id: 'アクセスキーID',
  secret_access_key: 'シークレットアクセスキー'
)
```

## AWS::S3オブジェクトを作る

キーを設定したら`AWS::S3`を使ってS3からデータを読み込むクライアントを作ります。

```ruby
s3 = AWS::S3.new
```

## バケットを取得する

続いてバケット名前を指定してバケットオブジェクトを取得します

```ruby
bucket = s3.buckets['my-bucket']
```

## ファイルを取得する

次はバケット内のファイルを取得します。

```ruby
file = bucket.objects['books.csv.gz']
```

## ファイルを読み込む

取得したファイルをパイプストリームに書き込みます。

```ruby
reader, writer = IO.pipe

file.read { |chunk| writer.write chunk }

writer.close
```

## Gzip圧縮データを解凍する

読み込んだデータはGzip圧縮してあるので`GzipReader`を使って解凍します。

```ruby
require 'zlib'

text = Zlib::GzipReader.new(reader).read
reader.close

```

## おまけ: Gzip圧縮した文字列を解凍する

上の例のように圧縮データはストリームに書き込むのが基本ですが、サイズが小さければ連結して`StringIO`経由で解凍してもOKです。

```ruby
data = ''

file.read { |chunk| data << chunk }

text = Zlib::GzipReader.new(StringIO.new(data)).read
```

## 解凍したCSVデータを読み込む

解凍したデータはCSV形式になっているので`CSV.parse`で読み込みます。

```ruby
CSV.parse(text).each do |row|
  puts row.inspect
end
```

これで無事読み込めました。

今回はこれでおしまいです。
Vagrant を CentOS 6.5 で環境構築

## 環境
* OS X Yosemite 10.10.1
* Vagrant 1.7.2


## 前提
* [Vagrant](https://www.vagrantup.com/) の インストール
* [VirtualBox](https://www.virtualbox.org/) の インストール
* [Vagrant Cloud](https://atlas.hashicorp.com/) のユーザー登録(この投稿ではBoxは[ここ<Discover Vagrant Boxes>](https://atlas.hashicorp.com/boxes/search)で探す)

## この投稿のゴール
Vagrant で CentOS 6.5 を立てるところまでとし、Webサーバー云々は他の投稿で書くよ

## Box を手に入れる
```
$ vagrant login

In a moment we will ask for your username and password to HashiCorp's
Atlas. After authenticating, we will store an access token locally on
disk. Your login details will be transmitted over a secure connection, and
are never stored on disk locally.

If you do not have an Atlas account, sign up at
https://atlas.hashicorp.com.

Atlas Username: XXXXXXXXXXXX
Password (will be hidden):
You are now logged in.

```

的な感じでログインをし、

```
$ vagrant box add centos6.5 chef/centos-6.5 
```

的な感じで Box を手に入れる。

## Vagrant 初期化
```
$ mkdir Sample
$ cd Sample
$ vagrant init centos6.5
A `Vagrantfile` has been placed in this directory. You are now
ready to `vagrant up` your first virtual environment! Please read
the comments in the Vagrantfile as well as documentation on
`vagrantup.com` for more information on using Vagrant.
```

## Vagrant 起動
```
$ vagrant up
```

## もしかしたらこんなエラーがでるかも

```
Failed to mount folders in Linux guest. This is usually because
the "vboxsf" file system is not available. Please verify that
the guest additions are properly installed in the guest and
can work properly. The command attempted was:

mount -t vboxsf -o uid=`id -u vagrant`,gid=`getent group vagrant | cut -d: -f3` vagrant /vagrant
mount -t vboxsf -o uid=`id -u vagrant`,gid=`id -g vagrant` vagrant /vagrant

The error output from the last command was:

/sbin/mount.vboxsf: mounting failed with the error: No such device
```

ちなみに Windows7 ではでなかったみたいorz

## 予防 (2015.04.14 追記)

もし、vagrant destroy が出来る状態で環境を作り直せるのなら以下のようにする


```
$ cd ~/.vagrant.d/

vim Vagrantfile
```
Vagrantfile はなかったら作成しちゃいましょう。このファイルにはこのように書き込んでください

```
Vagrant.configure("2") do | config |
	config.vbguest.auto_update = false
end
```


## 対処

もし vagrant destroy が出来ない状態ならば

```
$ vagrant ssh
Last login: Fri Mar  7 16:57:20 2014 from 10.0.2.2
[vagrant@localhost ~]$ sudo yum update -y kernel
```

## 再起動
```
$ vagrant reload
```
【PyCharm】Djangoテンプレートのコード補完がきかなくなった時のメモ

Djangoテンプレートの補完が利かなくなり、悲しい気持ちになった。

#確認： show.live.templates.in.completion
* [Help]->[Find Action]をたどる

* Registryを入力

* 「show.live.templates.in.completion」を探して、チェックが入っていることを確認する。
* 入ってなければチェックを入れる


#実施： Enable Django Supportの無効化&有効化
* [File]->[Settings]->[Languages & Frameworks]->Djangoとたどる。

* Enable Django Supportのチェックがあるので、一度チェックをはずして、「Apply」をクリック。

* もう一度、Enable Django Supportにチェックを入れて「Apply」をクリック

![Django設定.png](https://qiita-image-store.s3.amazonaws.com/0/28404/7f41a6b2-5905-34ee-b8fe-894ce5f8c1d2.png)

無事に復活。おめでとう、ありがとう。
簡便なSafariとChromeのメモリ使用量の測定方法

結局どちらがメモリ使用量が低いの？！ということでしばらく監視することに。

以下の様なシェルスクリプトを書きました。

```bash:safari_vs_chrome.sh
#!/bin/bash

logfile="./safari_vs_chrome.log"

while sleep 1; do

    now=`date +%S`
    surplus=`expr $now % 10`
    if [ $surplus -eq 0 ];then
        echo 'Date                Safari  Chrome' > $logfile
    fi

    echo `date "+%Y-%m-%d %H:%M:%S"` \
    `ps aux | grep Safari | awk '{sum += \$6}END{print sum}'` \
    `ps aux | grep Chrome | awk '{sum += \$6}END{print sum}'` > $logfile
done
```

これを以下のように実行して、

```bash:
$ sh safari_vs_chrome.sh &
```

以下のように見ましょう。

```bash:
$ tail -f safari_vs_chrome.log
```


こんなかんじで出てきます。

```
2015-04-05 11:04:14 926424 874976
2015-04-05 11:04:15 926372 874972
2015-04-05 11:04:17 926380 874952
2015-04-05 11:04:18 926412 874952
2015-04-05 11:04:19 926456 874952
Date                Safari  Chrome
2015-04-05 11:04:20 926536 874952
2015-04-05 11:04:21 926484 874944
2015-04-05 11:04:22 926628 874960
（以下続く）
```

測定だけはこれで可能だけど、開いているページや数によって大きく変わってくるので、実験はきちんと条件を揃えないといけませんね。
Python 3.4.3でgmail経由でメールを送る


個人的なメモ程度です。

```python

#!/usr/bin/python

import smtplib
from email.mime.text import MIMEText
from email.header import Header
from email.utils import formatdate

class Gmail:
    """
    Gmail with smtp client
    """
    def __init__(self, login_addr, passwd, encoding='utf-8'):
        self._encoding = encoding
        self._login_addr = login_addr
        self._passwd = passwd

    def send(self, to_addr, from_addr, subject, body):
        """
        Send a mail via gmail
        """
        msg = self._format_email(to_addr, from_addr, subject, body)
        with smtplib.SMTP('smtp.gmail.com', 587) as smtp:
            stmp.ehlo()
            stmp.starttls()
            stmp.ehlo()
            stmp.login(self._login_addr, self._passwd)
            stmp.sendmail(from_addr, to_addr, msg.as_string())

    def _format_email(self, to_addr, from_addr, subject, body):
        msg = MIMEText(body, 'html', self._encoding)
        msg['Subject'] = Header(subject, self._encoding)
        msg['From'] = from_addr
        msg['To'] = to_addr
        msg['Date'] = formatdate()

        return msg

    def bulk_send(self, emails):
        """
        Send multiple mails at one time via gmail
        """
        with smtplib.SMTP('smtp.gmail.com', 587) as smtp:
            smtp.ehlo()
            smtp.starttls()
            smtp.ehlo()
            smtp.login(self._login_addr, self._passwd)
            for email in emails:
                msg = self._format_email(email['to_addr'], email['from_addr'],
                                         email['subject'], email['body'])
                smtp.sendmail(email['from_addr'], email['to_addr'],
                              msg.as_string())


if __name__ == "__main__":
    gmail = Gmail('hoge@gmail.com', 'foo')
    gmail.send('foo@gmail.com', 'bar@gmail.com', 'test', 'test')
    addr = 'baz@gmail.com'
    mails = [{'to_addr': addr, 'from_addr': addr, 'subject': 'test', 'body': 'test'}] * 10
    gmail.bulk_send(mails)




```