2015年3月31日火曜日

Cygwin 上に jq をインストールする方法

概要

jqはコマンドラインで簡単にJSONを整形することができるツールです
Cygwin上でも動作させることができたのでインストール方法を紹介します

環境

  • Windows 7 64bit
  • Cygwin 1.7.32
  • jq 1.4

インストール方法

Cygwin環境下で以下のコマンドを実行すればOKです

cd /usr/bin && wget http://stedolan.github.io/jq/download/win64/jq.exe

P.S 20150928
URLが変わっていました

cd /usr/bin && wget https://github.com/stedolan/jq/releases/download/jq-1.5/jq-win64.exe
mv jq-win64.exe jq.exe
chmod 755 jq.exe

バージョンを確認します

  • jq -V
jq-1.4

使い方

使い方は簡単
基本はパイプに食わせる感じです

echo '{"key":"value"}' | jq '.'

例えばJSON形式で取得できるREST-APIみたいなのがあったら

curl 'https://mb.api.cloud.nifty.com/' 2> /dev/null | jq '.'

とすることで

{
  "code": "E404002",
  "error": "None service."
}

こんな感じで取得できます

改行コードを変更したい場合はsedと組み合わせると好きな改行コードで出力できます

curl 'https://mb.api.cloud.nifty.com/' 2> /dev/null | jq '.' | nkf -Lu

自分はemacsユーザなのですがemacsと組み合わせると以下のようなこともできるようです
これは便利です

あとはわからないことがあれば公式を読めばOKかと思います

2015年3月27日金曜日

CentOS に Go 言語をインストールして boom で負荷テストをやってみた

概要

boomはGo言語で書かれた負荷かけツールです
ApacheBench(ab)と同じ感覚で使えます
abだとHTTP Methodを指定して実行できなかったのでboomを使ってPOST Methodのテストを実施してみました

環境

  • CentOS 6.6 64bit
  • go 1.4.2
  • boom (revison:372ea3b0e6cb084657d1db7eacccdfae929af5b9)

Goのインストール

以下はすべてrootで作業しています

cd /var/tmp
wget https://storage.googleapis.com/golang/go1.4.2.linux-amd64.tar.gz
tar zvxf go1.4.2.linux-amd64.tar.gz
mv go /usr/local/
mkdir /root/gocode
echo "export PATH=$PATH:/usr/local/go/bin" >> ~/.bashrc
echo "export GOPATH=/root/gocode" >> ~/.bashrc
source ~/.bashrc

boomのインストール

go get github.com/rakyll/boom

で完了、簡単

テストしてみる

./gocode/bin/boom -n 10000 -c 100 -m POST 'http://localhost/'

「-n」送信する全リクエストの数
「-c」はその全リクエストをはいくつの同時並列で実行されるか
(なので-cを増やしても全リクエスト数は変わりません)
「-m」でHTTP Methodを指定できます

結果は以下のような感じ

10000 / 10000 Boooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo! 100.00 %

Summary:
  Total:        1.6549 secs.
  Slowest:      0.0373 secs.
  Fastest:      0.0053 secs.
  Average:      0.0164 secs.
  Requests/sec: 6042.6406
  Total Data Received:  2730000 bytes.
  Response Size per Request:    273 bytes.

Status code distribution:
  [404] 10000 responses

Response time histogram:
  0.005 [1]     |
  0.008 [32]    |
  0.012 [10]    |
  0.015 [5098]  |????????????????????????????????????????
  0.018 [1387]  |??????????
  0.021 [2715]  |?????????????????????
  0.024 [702]   |?????
  0.028 [31]    |
  0.031 [7]     |
  0.034 [0]     |
  0.037 [17]    |

Latency distribution:
  10% in 0.0131 secs.
  25% in 0.0138 secs.
  50% in 0.0148 secs.
  75% in 0.0197 secs.
  90% in 0.0210 secs.
  95% in 0.0217 secs.
  99% in 0.0230 secs.

ヒストグラムでレスポンスタイムの分布を出してくれるのが見やすくてGood

最後に

abの2.4.10以降だとboom同様に「-m」オプションでMethod指定ができるみたいなんですが
Apacheの2.4.12をソースインストールしてみたらabのバージョンだけ2.4.9だったのでboomを使った次第です
結果的にはabより良いツールだということがわかったので今後はboomを使ってみたいと思います

2015年3月26日木曜日

mosquitto / lib / util_mosq.c の mosquitto_topic_matches_sub の Java 実装を作ってみました

概要

mosquittoで実装されているACLのチェック機構がC言語で実装されていたのでJavaで書きなおしてみました
ソースファイル全体ではなくACLをチェックする一部のメソッドだけ書きなおしています

環境

  • mosquitto 1.4
  • Java 1.8.0_25

ソースコード

package test;

public class Test {

    public static void main(String[] args) {
        Test t = new Test();
        String acl, topic;
        acl = "aaa"; topic = "aaa"; // -> true
        System.out.println(t.checkMatchingACLWithTopic(acl, topic));
        acl = "#"; topic = "test"; // -> true
        System.out.println(t.checkMatchingACLWithTopic(acl, topic));
        acl = "+/aaa"; topic = "aaa/aaa"; // -> true
        System.out.println(t.checkMatchingACLWithTopic(acl, topic));
        acl = ""; topic = "test"; // -> false
        System.out.println(t.checkMatchingACLWithTopic(acl, topic));
        acl = "test"; topic = "test2"; // -> false
        System.out.println(t.checkMatchingACLWithTopic(acl, topic));
        acl = "+"; topic = "test"; // -> true
        System.out.println(t.checkMatchingACLWithTopic(acl, topic));
        acl = "a/+/c"; topic = "a/b/c"; // -> true
        System.out.println(t.checkMatchingACLWithTopic(acl, topic));
        acl = "a/+/+"; topic = "a/b"; // -> false
        System.out.println(t.checkMatchingACLWithTopic(acl, topic));
    }

    /**
    * ACL とアクセスしたいトピックがマッチするかチェックする
    * これは mosquitto/lib/util_mosq.c の mosquitto_topic_matches_sub を Java に 書き換えたものである
    *
    * @param sub トピックに対するユーザのACL情報
    * @param topic アクセスしたいトピック
    * @return trueならばACLの中にアクセスしたトピックのパターンが含まれている
    */
    public boolean checkMatchingACLWithTopic(String sub, String topic) {
        int slen, tlen;
        int spos, tpos;
        boolean multiLevelWildCard = false;

        if (sub == null && topic == null) {
            return false;
        }
        slen = sub.length();
        tlen = topic.length();
        if (slen >= 0 && tlen >= 0) {
            if ((sub.startsWith("$") && !topic.startsWith("$")) || (!sub.startsWith("$") && topic.startsWith("$"))) {
                // $始まりだった場合
                return false;
            }
        }
        spos = 0;
        tpos = 0;
        // sub, topic ともに全文字列をチェックする
        while (spos < slen && tpos < tlen) {
            if(sub.charAt(spos) == topic.charAt(tpos)) {
                if (tpos == tlen -1) {
                    if (spos == slen - 3 && sub.charAt(spos + 1) == '/' && sub.charAt(spos + 2) == '#') {
                        // # で 終わる sub だから true を返却
                        return true;
                    }
                }
                spos++;
                tpos++;
                if (spos == slen && tpos == tlen) {
                    // お互い最後の文字だった場合
                    return true;
                } else if (tpos == tlen && spos == slen - 1 && sub.charAt(spos) == '+') {
                    // topic が最後の文字で sub もあと2文字で今の文字が「+」だった場合
                    return true;
                }
            } else {
                if (sub.charAt(spos) == '+') {
                    spos++;
                    // sub が「+」の場合
                    while (tpos < tlen && topic.charAt(tpos) != '/') {
                        // 次の / 移行の topic に移動する(ACLで + なのでその階層はなんでも許可するため)
                        tpos++;
                    }
                    // 移動した結果どちらも最終文字だった場合
                    if (tpos == tlen && spos == slen) {
                        return true;
                    }
                } else if (sub.charAt(spos) == '#') {
                    // sub が「#」ワイルドカードの場合
                    multiLevelWildCard = true;
                    if (spos + 1 != slen) {
                        // sub が最後から1文字目でない場合(要するに # のあとに何かを指定しちゃっている場合)
                        return false;
                    } else {
                        // # のあとに何も指定していない場合はすべてを許可する
                        return true;
                    }
                } else {
                    // それ以外の文字の場合はマッチしない
                    return false;
                }
            }
        }
        // 最終的に # が使われていないかつ sub または topic の文字列が最後まで達していない場合
        if (multiLevelWildCard == false && (tpos < tlen || spos < slen)) {
            return false;
        }
        // 該当がない場合はエラーにする
        return false;
    }

}

一応CJavaで同じテストを実施して同じ結果になることは確認しています
mosquittoでは更にこれをコールしている上位のメソッドがあってこのメソッドの返り値を見て更に ACC という値と比較して Topic へのアクセス可否を判断していました

2015年3月25日水曜日

Eclipse で C 言語の開発環境を構築してみた

概要

調べてみるとCDT (C/C++ Development Tools) というプラグインを使うのが一般的っぽかったので今回はこれをインストールして実行するところまでやってみました

環境

  • Windows7 64bit
  • Eclipse 4.4 Luna
  • CDT (C/C++ Development Tools) 8.4
  • Cygwin 1.7.32

プラグインのインストール

今回はEclipse Marketplace からCDTをインストールしました

Help -> Eclipse Marketplace

でSearchに「CDT」と入力して検索します
以下のプラグインが一覧に表示されるので「Install」をクリックします
cdt_install.png

同意してインストールしたらEclipseを再起動してインストールを完了します

プロジェクトの作成

Package Explorer で右クリックして「New」-> 「Other」と選択します
C/C++配下に「C Project」があるので選択してNextと進みます
create_project.png

プロジェクト名を入力するダイアログになるので入力して「Finish」をクリックしてプロジェクトを作成しましょう
他にも「Project type」や「Toolchains」など選択できるところがありますがとりあえずデフォルトでOKです

サンプルコードの作成

コードを管理するフォルダとソースファイルの作成

まずはソースを管理するフォルダを作成しましょう

プロジェクトを右クリックして

New -> Source Folder

を選択してください
フォルダ名に「src」と入力して作成を完了します

このsrcフォルダ配下にCのコードを配置していきます
srcフォルダを右クリックして

New -> Source File

を選択します
ファイル名を入力してソースファイルを作成しましょう
今回は「main.c」としました

コードを書く

作成されるとコメント欄だけ自動生成されていると思います
ここに動くコードを追記していきましょう
今回は簡単なprint文を実行するサンプルを作成しました

#include <stdio.h>

void main() {
    printf("hello c world\n");
}

実行してみる

ではサンプルを記載したソースファイルを実行してみましょう
と、その前にC言語なのでコンパイルして実行できる形式に変換してあげる必要があります

プロジェクトを右クリックして

Build Project

を選択してソースファイルをビルドしましょう
するとコンソールビューにビルドの結果が表示されます
build_result.png
こんな感じで表示されればOKです

これでソースファイルを実行できるようになります
再度プロジェクトを右クリックして

Run As -> Local C/C++ Application

と選択します
するとダイアログが表示されるので先ほどビルドして作成された.exeファイルを選択してOKをクリックします
一度実行すると実行の構成に追加されるので、次回以降はツールバーにある実行ボタンから実行することもできます(ビルド+実行を一度に実施してくれます)

実行されるとコンソールビューにprintfの結果が表示されればOKです

Tips

上記の方法でコンソールにうまくprintfの内容が表示されない場合は以下を参考にしてみてください

それでも面倒な場合は直接.exeファイルをCygwin上で実行してもOKです

$ ./Debug/test-c.exe
hello c world

プロジェクトを作成する際にCygwin上のgccを指定したのでCygwin上で実行できるのだと思います
project_tree.png

プロジェクトのコンパイラにMinGw上のgccを選択した場合、MinGw上で.exeファイルを実行してみてください

最後に

コードを書く上であとはコード補完があれば何とかなるような気がします
CDTであればEclipseのコード補完を使えました
ほぼEclipse上で問題なさそうですが、やはりコンソールにバグがあるのでデバッグが大変そうです

2015年3月24日火曜日

emacs で clipborad を共有する方法

概要

emacsの「-nw」で起動した状態でクリップボードを共有する方法を紹介します

環境

  • emacs 24.4.1
  • Max OS X 10.10.2 or Cygwin 1.7.32

elisp

.emacsに以下を書けばOKです
Githubで公開している.emacsに記載しているので最新版はそっちで管理しています

以下は一部抜粋のサンプル

; for clipborad
(setq sysname system-type)
(if (eq sysname 'darwin)
    (progn
      (defun copy-from-osx ()
    (shell-command-to-string "pbpaste"))
      (defun paste-to-osx (text &optional push)
    (let ((process-connection-type nil))
      (let ((proc (start-process "pbcopy" "*Messages*" "pbcopy")))
        (process-send-string proc text)
        (process-send-eof proc))))
      (setq interprogram-cut-function 'paste-to-osx)
      (setq interprogram-paste-function 'copy-from-osx)
    )
    (message "This platform is not mac")
)
(if (eq sysname 'cygwin)
    (progn
      (defun paste-from-cygwin ()
        (with-temp-buffer
          (insert-file-contents "/dev/clipboard")
          (buffer-string)))
      (defun cut-to-cygwin (text &optional push)
        (with-temp-file "/dev/clipboard"
          (insert text)))
      (setq interprogram-cut-function 'cut-to-cygwin)
      (setq interprogram-paste-function 'paste-from-cygwin)
   )
   (message "This platform is not cygwin")
)

emacsでプラットフォーム情報を取得できるので、それに応じてクリップボードを使うコマンドを分けています
Windows上で開いているターミナルアプリでSSHログインした先のLinuxサーバで起動上で動作しているemacsとクリップボードを共有する方法が知りたい
そもそもできるのだろうか

2015年3月23日月曜日

Github で初めての pull - request (プルリクエスト)

概要

Github にあるプルリクエストという機能は非常に強力で便利な機能です
簡単に言ってしまえば「あなたのコード修正してあげたから、そっちに適用してね」とお願いする行為になります
ただ、やり方がちょっと複雑だったり英語で文章を作ったりと大変です
今回はそんなプルリクエストをGithubでやってみたいと思います

環境

  • git 2.3.0
  • Github 2015/03/20時点

他のアカウントのリポジトリにプルリクエストを送ってみる

それでは実際にやってみます

forkする

これがプルリクエストへの第一歩です
forkとはリポジトリをコピーすることです
forkは必ず「自分でない誰かのリポジトリ」をforkしなければなりません
今回はテスト用のプルリクエストを実施するので、もしあるなら適当なリポジトリをforkしてください
ない場合は私のリポジトリのどれでもOKです

やり方は簡単で作成したリポジトリの右上にある「fork」ボタンをクリックしてください
fork.png
するとforkがはじまります
自分のアカウントにコピーしているので多少時間がかかります
forkが完了したリポジトリを見ると誰からforkしたリポジトリなのかとアイコンが「Y」みたいなforkを示すアイコンに変わります
forked_repo.png
これでforkが完了しました

ブランチを作成する

自分が修正するためのブランチを作成しましょう
ブランチは作成しなくてもいいですが、作成したほうがいいです
理由としてはブランチ名を見るだけでどういうことをしたいのかというのを表すことができるからです

まずはforkしたブランチをcloneしてきます

git clone https://github.com/kakakikikeke-fork/cookbooks-emacs.git

cloneが作成したらブランチを作成してみましょう

git branch fix_let_to_progn

ブランチを移動しましょう

git checkout fix_let_to_progn

ブランチの作成と移動はこれでOKです
この作成したブランチに修正を入れていきます

修正する

作成したブランチ上のファイルに対して、何でもいいのでファイルを修正してみます
今回は明らかにバグを見つけているのでそのバグを直してみたいと思います
バグの箇所はcookbooks-emacsfiles/default/dot_emacsの最後の方です

diffの内容は以下の通り

  • git diff
diff --git a/files/default/dot_emacs b/files/default/dot_emacs
index 05d0389..9dbddc6 100755
--- a/files/default/dot_emacs
+++ b/files/default/dot_emacs
@@ -61,7 +61,7 @@
 ; for clipborad
 (setq sysname system-type)
 (if (eq sysname 'darwin)
-    (let
+    (progn
       (defun copy-from-osx ()
        (shell-command-to-string "pbpaste"))
       (defun paste-to-osx (text &optional push)

diff を確認できたらgit add -> git commitをしていきます

修正をブランチにコミットする

ここでコミットするのはまだ自分のforkしたリポジトリのブランチなので、fork元にアカウントのリポジトリには何も変更を加えないので安心して実行してください

git add files/default/dot_emacs
git commit -m "fix let to progn"

コミットメッセージは簡潔に、かつわかりやすくしましょう
また、commit する前に.git/confignameの部分がちゃんとGithubのアカウントになっているか確認しましょう
適当な状態で commit するとコミットした名前とメールアドレスが作業マシンごとに自動生成されてしまいGithub上でアイコン等がちゃんと表示されないで注意してください

ではpushしてみます

git push -u origin fix_let_to_progn

origin は自分を表しています
fix_let_to_prognはpushしたいブランチ名を指定します
アカウント名とパスワードが聞かれるので入力してください
認証が成功すれば無事pushされるはずです

認証に失敗する場合は.git/configの設定を確認してください
[remote "origin"]urlの設定が自分のリポジトリを指しているか確認してみましょう
これが、fork元のアカウントのリポジトリになっていると認証で失敗してしまいます(勝手にfork元のリポジトリにはpushできないので)

Github上でコミット内容を確認する

forkした自分のリポジトリを確認してみます
すると以下のような感じの表示が追加されています
can_pull_req.png
プルリクエストはここから作成することができます

またbranchs等のタブを確認するとローカルにあったブランチがちゃんとGithub上にも登録されていることがわかると思います

では、本題のプルリクエストを作成してみましょう

プルリクエストの文章を作成する

先ほどの緑色のボタンをクリックするとプルリクエストを作成する画面に遷移します
プルリクエストを送信するのに必要な最低限の内容は以下の3つです

  • どの自分のブランチをどの相手のブランチにマージしてほしいか選択する
  • タイトルを入力する
  • 内容を記載する

create_pull_req.png

タイトルの部分はコミットログの内容が自動的に入力されます

正直ここのタイトルと内容の部分がマージされるための肝と言ってもいいかもしれません
タイトルは変えてもOKです
内容の部分は今回のように少しの修正であれば、そこまで細かく必要はないです
機能の追加や設定項目等があれば、まずはざっくりと何ができるのかを「Abstract」という見出しで記載して、詳細は「Detail」や「Configuration」「How to use」といった見出しを作成して具体的な設定方法や使い方を記載するといいと思います
Markdownも使うことができます
Markdownを使ったらプレビューで確認してからプルリクエストを送るようにしましょう

この辺の書き方は本当に人それぞれです
適当に書いてもマージしてくれる方もいれば、そうでない方もいるといった感じです

無理に英語で書く必要もないですが、できれば英語がいいです
fork元のリポジトリの言語に合わせるでもいいと思います

必要な内容を記載できたら「Create pull request」でプルリクエストを作成しましょう

このあとは

プルリクエストの作業自体はこれで完了です
あとはマージされるのを待ちましょう
これもユーザによってまちまちですが、すぐにマージしてくれる人もいれば、全く応答がなく放置されてしまう場合もあります
どうしてもプルリクエストをマージしてほしい場合は他のアカウントが「+1」などしてくれる場合もあります

また送信したプルリクエストに対して自分で催促することも可能です
可能ですがあまりしつこく催促するとクローズされてしまうこともあるので注意しましょう

最後に

簡単ですが、プルリクエストを実施する手順を紹介しました
ボクが一番大変だと思うのはやっぱりプルリクエストの文章を作成するところだと思います
特に初プルリクエストの場合はそのリポジトリ、アカウントの活動や雰囲気もわからないので、どこまでフランクに書けばいいのか判断するのが難しいかなと思います
まぁでも割りと適当でも結構快く受け入れてくれる人が多いかなと思いますw

プルリクエストはOSS開発では非常に便利な機能なのでぜひ使ってみてください

2015年3月21日土曜日

We can't automatically merge this pull request.

概要

GithubとかGitBucketとかPull Request (p-r) があるサービスで p-r をマージしたいのに「We can’t automatically merge this pull request.」という感じで緑のボタンが押せないときの対応方法です

環境

  • GitBucket 2.7
  • git 2.1.1

手動でマージする

ボタンが押せない場合は手動でマージします
今回はmasterにマージする場合を想定しています

git checkout master

masterに移動します、すでにmasterなら実施しなくてOKです

git pull

p-r で作成されたブランチをローカルに持ってきます
git branch -aで見ると p-r で作成されたブランチが見えるようになると思います(ここは git fetch でOK?)
今回は p-r で作成されたブランチを created_branch とします

git merge created_branch

これで created_branch を master ブランチにマージすることができます
Conflictが発生した場合は自力で頑張って修正します(ここが一番大変かも)

git push -u origin master

マージに成功するとマージ用のコミットが残るのであとは master push すればOKです

とりあえずこれで p-r をマージすることはできました

ボタンを押してブランチを削除する

上記を実施したあとにリポジトリの p-r の画面に行くと緑のボタンが押せるように復活していると思います
基本はポチポチしていけばOKです
マージしてチケットをクローズしてブランチを削除の流れです

最後に

いつもボタンが押せないと焦って手順忘れるのでメモしておきます

2015年3月20日金曜日

git marge した内容を確認する方法

概要

git merge されたコミットログはgit log -pとかで見てもコミットされた内容を確認できません
そんなときにコミットの内容を確認する方法です

環境

  • git 2.1.1

やり方

git show [revision]

でOK
[revision]はgit logで確認できる commit 移行のランダムの文字列を指定すればOKです

それでも表示されない場合はgit logのマージコミットに表示されるMergeの欄の後ろのリビジョン番号でgit showをかけましょう

commit dc35cc7ac6944a20ecee8272331ef4af885469e0
Merge: c3e5e37 492a481
Author: Jon Mountjoy <jon@heroku.com>
Date:   Wed May 28 13:04:29 2014 +0100

    Merge pull request #1 from dzuelke/docrootfix

    move (fixed) htaccess to web/

の場合は

git show 492a481

でマージした内容が表示されます

2015年3月19日木曜日

CentOS 6.6 に Tomcat を yum を使ってインストールしてみた

概要

Tomcatのインストールはアーカイブをダウンロードして解凍して配置して終了という感じで実施していたのですが、yumでもインストールできるのでやってみました
設定ファイルやデプロイ先も自動で設定されるのでその辺も確認しました

環境

  • CentOS 6.6 Final
  • Tomcat 7.0.33
  • Java 1.8.0_31

インストール作業

yumを使って各種インストールしてみます

Tomcatのインストール

yum -y install tomcat

でTomcatの 7.0.33というバージョンがインストールされました

これは、バージョン7系のバージョンとしてはだいぶ古いです
バージョンで7系の最新版は 2015/03/18 時点では v7.0.59 でした
v7.0.33は 2012-11-21 12:07 頃にリリースされたバージョンです

tomcat version

Server version: Apache Tomcat/7.0.33
Server built:   Apr 30 2014 09:16:58
Server number:  7.0.33.0
OS Name:        Linux
OS Version:     2.6.32-358.el6.x86_64
Architecture:   amd64
JVM Version:    1.8.0_31-b13
JVM Vendor:     Oracle Corporation

Server builtを見ると割りと最近(それでも1年以上前)ですがおそらくこれはrpmパッケージとしてビルドされた時期なのでTomcatのリリースとは別になると思います

P.S 2015/03/24

すいません、tomcatの7系はCentOS6.6のbaseリポジトリでは公開されていませんでした
知らぬ間にepelのリポジトリを追加していたみたいです
上記を実施するにはまず以下を実施してください

rpm -Uvh http://ftp.riken.jp/Linux/fedora/epel/6/i386/epel-release-6-8.noarch.rpm

JVMについて

もし自分の環境にTomcatがまだインストールされていない状態だと一緒にJavaもインストールされます
インストールされるJavaはOpenJDKになります(Oracle版ではないです)
最終的に自分の環境で動作させたJavaは1.8になります

実はTomcatをyumインストールするとそのバージョンに依存したJavaのRPMパッケージも自動でインストールされます
Tomcat7.0.33の場合、一緒にインストールされたJavaのバージョンは1.7.0.75でした

これは既にJavaの1.8がyumがインストールされていても強制的にインストールされるようです
同時にインストールされたRPMパッケージ名はjava-1.7.0-openjdk-1.7.0.75-2.5.4.0.el6_6.x86_64で詳細を確認したい場合は

rpm -qli java-1.7.0-openjdk-1.7.0.75-2.5.4.0.el6_6.x86_64

でOKです

JVMを切り替える

既に1.8がインストールされている状態だと使用するJavaのバージョンが1.7で上書きされてしまいます
実際にjava -version辺りを実行すると1.7 になっていることがわかると思います
1.8を使いたい場合はalternativesコマンドを使うと簡単に切り替えることができます

コマンドの流れとしては以下の通りです

java -version

java version "1.7.0_75"
OpenJDK Runtime Environment (rhel-2.5.4.0.el6_6-x86_64 u75-b13)
OpenJDK 64-Bit Server VM (build 24.75-b04, mixed mode)

まだ1.7の状態でalternativesコマンドを利用してバージョンを切り替えます

alternatives --config java

3 プログラムがあり 'java' を提供します。

  選択       コマンド
-----------------------------------------------
   1           /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.31-1.b13.el6_6.x86_64/jre/bin/java
   2           /usr/lib/jvm/jre-1.5.0-gcj/bin/java
*+ 3           /usr/lib/jvm/jre-1.7.0-openjdk.x86_64/bin/java

Enter を押して現在の選択 [+] を保持するか、選択番号を入力します:1

使用したいバージョンの番号を入力すればOKです
切り替えたあとに再度バージョンを確認しましょう

java -version

openjdk version "1.8.0_31"
OpenJDK Runtime Environment (build 1.8.0_31-b13)
OpenJDK 64-Bit Server VM (build 25.31-b07, mixed mode)

これでTomcatが利用するJVMを切り替えることができます
もしyumでJavaをインストールしている場合はお好きなバージョンに切り替えてください

起動方法

yumでインストールした場合はinit.d配下に起動スクリプトが作られるので service コマンド経由で起動することができます

service tomcat start

init.d経由なので chkconfig で自動起動をONにすることもできます
Tomcat起動中にJavaのバージョンを切り替えて停止しようとするとうまく停止することができないので、Javaのバージョンを変更したい場合は起動 -> 停止をしてから変更してください

管理画面をインストール

Tomcatの管理画面は別途yumインストール必要がありました

yum -y install tomcat-admin-webapps

でインストールできます
これでTomcatを再起動するとhttp://localhost:8080/manager/htmlにアクセスできるようになります

アクセスするとユーザ名とパスワードが聞かれます
デフォルトだと管理UIにアクセスできるユーザは存在しないのでアクセスしたい場合は設定ファイルにユーザを追加しましょう

  • vim /etc/tomcat/tomcat-users.xml
<role rolename="admin-gui"/>
<role rolename="manager-gui"/>
  <user username="tomcat" password="tomcat" roles="admin-gui,manager-gui"/>

上記をtomcat-usersタグ内に記載しましょう
これで管理画面にアクセスすることができます

設定の確認

設定ファイルのパスやデプロイパスを確認します

設定ファイルのパス

まず、インストールしたTomcatの詳細情報を確認してみましょう

rpm -qli tomcat-7.0.33-4.el6.noarch

上記のコマンドでインストールされたファイルやパスがすべて表示されます

その中で設定ファイルは以下のパスで管理されるようです

/etc/tomcat/

このパスの実態は/usr/share/tomcat/confになっており、ここからシンボリックリンクがはられている感じになります
設定変更したい場合は/etc/tomcat配下にある設定ファイルを変更すればOKです

デプロイ先のパス

デプロイ先は以下でした

/var/lib/tomcat/webapps

これは/usr/share/tomcat/webappsからシンボリックされています

ログ

ログは以下に出力されます

/var/log/tomcat

これは/usr/share/tomcat/logsからシンボリックされています
なので、log4jなので FileAppenderを使う場合は./logs/hoge.logと書いておけば上記にログが吐かれるようになります

最後に

yumだと簡単にインストールできます
ただ設定ファイルのディレクトリやログのディレクトリも勝手に決まるのでその辺をインストール後に自分で確認する必要があります
起動スクリプトが自動で生成されるのも嬉しいポイントかなと思います

ただ、デメリットもやはりあり最新版がインストールされないことや管理UI用のRPMを別途インストールしなければいけないなど若干手間になる作業もあります

アーカイブ版とyum版を比較すると個人的にはyumインストールでいいかなと思っています
もしアップデートやセキュリティパッチが出たらyumコマンドで簡単に適用できます
最新版を絶対使う必要がなければyumをおすすめします

それでも最新版を使いたいのであればアーカイブ版方式でインストールするしかないかなと
もしくは自分でrpmbuild等を使ってrpmファイルを作成すればrpmコマンドでインストールでされるのでパッケージ管理システム配下で管理することはできるようになります

2015年3月13日金曜日

Outlook 365 でマクロ入門

概要

Outlook365でマクロを動作させる手順をまとめてみました
簡単なサンプルマクロが動作するところまでやってみたいと思います

環境

  • Windows7 64bit
  • Outlook365
  • Microsoft Visual Basic for Applications 7.1

マクロ実行の準備

デフォルトのままだとマクロを実行することができません
「開発」というタブを表示する必要があります

ファイル -> オプション -> リボンのユーザー設定 -> メインタブ

を選択しメインタブの一覧の中に「開発」があると思いますのでそれにチェックを入れます
setup_dev_tool.png

チェックしてOKをクリックするとタブの一覧に「開発」が表示されるようになります

サンプルマクロの作成

マクロを作成してみましょう
先ほど表示されるようにした開発タブから

開発 -> マクロ -> マクロ

をクリックします
select_macro.png

するとダイアログが開くのでマクロ名の部分に作成するマクロの名前を適当に入力します
入力した右側の「作成」をクリックします
create_macro.png
するとマクロのエディタである「Microsoft Visual Basic Applications」が開くのでここでマクロを開発します
(エクセルでマクロをゴリゴリ書いている人は見なれたエディタだと思います)

今回は超簡単なサンプルを書いてみます
マクロ名はtest_macroとします

Sub test_macro()
  MsgBox "Hello World!"
End Sub

と入力して保存します

サンプルの作成はこれで完了です
作成できたので実行してみましょう

実行してみる

Microsoft Visual Basic for Applications のツールバーに緑色の三角形があるのでこれをクリックすると実行できます
execute.png

F5を押しても実行できます
実行するとHello World!と書かれたダイアログが表示されると思います

エディタ上で動作することが確認できたのでOutlook365から実行してみたいと思います

マクロを保存した段階でOutlook365にも組み込まれているので実行するだけでOKです

開発 -> マクロ

と進むと先ほど作成したtest_macroが選択肢に増えているのでtest_macroをクリックします
すると先ほどと同じようにダイアログが表示されると思います

ThisOutlookSession

ここから本題かもしれません
Outlook365のオブジェクトを触ったマクロを書く方法です
先ほど作成したサンプルは

標準モジュール -> Module1

という場所に保存されています
マクロとしてはここでも動作するのですがOutlook365が提供するマクロを使用することはできません

Microsoft Visual Basic for Applications の左メニューに「Microsoft Outlook Objects」というフォルダがあり、その下に「ThisOutlookSession」というOutlookのアイコンがあると思います
このアイコンにマクロを書くことでOutlook365が提供するマクロが書けるようになります
macro_for_outlook.png

「ThisOutlookSession」をダブルクリックすると右ペインにエディタが開きます
開いたら以下のコードを入力してください

Private Sub Application_NewMailEx(ByVal EntryIDCollection As String)
  Dim objItem
  Set objItem = Session.GetItemFromID(EntryIDCollection)
  If objItem.MessageClass = "IPM.Note" Then
    MsgBox "Hello World!"
  End If
End Sub

簡単にポイントを説明すると超重要なのがApplication_NewMailExというサブセットでこれがOutlook365が提供するマクロで、こいつを定義するとメールが受信された際に毎回実行されます
IPM.Noteは電子メールを表すオブジェクトで受信したオブジェクトが電子メールであった場合にMsgBoxを実行するようにしています

記載が完了したら保存しましょう
エディタを閉じてしまって再度編集したい場合は「ThisOutlookSettion」をダブルクリックすれば保存したマクロが表示されます

実行してみる

サンプルマクロのように三角マークをクリックしても何も起きません
というかクリックするとマクロの作成ダイアログが立ち上がってしまいます
なので Microsoft Visual Basic for Applications 上でテストすることはできません

Outlook365に戻って動作を確認するしかありません
ツールバーの左上にあるOutlookボタンを押すかCtrl + TAB でウィンドウを切り替えてください
メールが来ないという場合は自分宛にメールを作成してテストしてみてください
受信時にダイアログが表示されればOKです

このテストは文字通り受信時に毎回ダイアログを出すので頻繁にメールを受信する方はすぐに停止したほうがいいと思います
停止する場合は再度エディタで「ThisOutlookSettion」を開いてコメントアウトするなりコードを削除するなりして上書き保存してください

最後に

基本構文は Visual Basic なのでif文やらfor文やらも使えます
なので Visual Basic を勉強しておくと更に書きやすくなると思います
Outlook365のマクロではメールや受信トレイなどに触れるオブジェクトが用意されており、それを使ってOutlook365用のマクロを作成する感じになります

基本メールを読むのが嫌いなのでこれで本当に必要なメールだけを読むようにするとかできそうです

参考サイト

2015年3月12日木曜日

Eclipse + STS で Spring Framework の WebAPI を作成してみた

概要

前回はMaven + Springで簡単なWebアプリを作成しました
今回もMaven + Springではあるのですが前回は「spring-boot-starter-web」という仕組みを使っていて、これはjarを生成するだけでWebアプリが作成できるという仕組みです
「spring-boot-starter-web」では一般的なJavaのWebアプリの構造にはなっておらず、Webサーバ(TomcatやJBOSSなど)上で動作させようとするとちょっと面倒です

今回はWebサーバ上で動作するSpringアプリをSTS(Spring Tool Suite)というツールを使ってやってみました

環境

  • Mac OS X 10.10.2
  • Eclipse Luna 4.4.1
  • Spring Tool Suite 3.6.4
  • Java 1.8.0_31
  • Tomcat 8.0.20

各種インストール

必要なプラグインなどをインストールしていきます

STS(Spring Tool Suite)のインストール

Eclipse Marcketplaceから簡単にインストールできます

Help -> Eclipse Marcketplace -> Searchタブ -> Findに「spring」と入力して検索

とするとSTSが表示されるので「Install」をクリックして同意してEclipseを再起動することでインストールできます
install_sts.png
※上記はインストール済みのEclipse Marcketplaceでの表示

Tomcatのインストール

今回はTomcat上で動作させてみます
公式からで問題ないのでTomcatをインストールしてください
HomebrewでもOKです

brew install tomcat

TomcatをインストールしたらEclipse上に実行用のサーバとして登録します
Eclipseを起動して

Package Explorer上で右クリック -> New -> Other -> Server -> Server

と選択しNextをクリックして

Aapche -> Tomcat v8.0 Server -> Next

で「Tomcat Installation directory」にTomcatをインストールしたディレクトリを指定します
Homebrewでインストールしたのであれば/usr/local/Cellar/tomcat/8.0.20/libexec的なパスを記載します

入力したら「Finish」をクリックしてServerの作成は完了です

プロジェクトの作成

サンプルのプロジェクトを作成します
今回はSTSを使ってWebアプリ用のサンプルプロジェクトを作成します

Package Explorer上で右クリック -> New -> Other -> Spring -> Spring Starter Project

を選択しNextをクリックします

select_spring_project.png

プロジェクトの内容を設定するダイアログが表示されるので以下を入力および選択します

  • Project name・・・任意のプロジェクト名を入力します
  • Templates・・・「Spring MVC Project」を選択します

あとはそのままでOKです
入力できたらNextをクリックします
config_spring_project.png

「Spring MVC Project requires a download of 16608 bytes」という警告がでますが、Yesを選択します

次にパッケージ名を入力するダイアログが表示されるので任意のパッケージ名を入力します
最低限、3階層のパッケージ名を入力する必要があります
input_package_name.png
あとはFinishをクリックすればプロジェクトが作成されます
作成されたあとのプロジェクトのディレクトリ構成は以下のとおりです
list_project.png
サンプルプロジェクトの作成ができたら早速動かしてみましょう

Tips

  • Errors running builder ‘Faceted Project Validation Builder’ on project ‘spring-test’.

みたいなエラーが出る場合は

Help -> Install New Software

を開き

を選択し「Web, XML, Java EE and OSGi Enterprise Development」を選択しインストールしてください
Lunaの選択項目がなければ追加すればOKです
Lunaでないバージョンを使っている場合は、適宜バージョンにあったリポジトリを選択してください
結構量が多いのでインストールには時間がかかります

で、この「Web, XML, Java EE and OSGi Enterprise Development」をインストールするのにエラーになる場合は一旦STSをアンインストールしてから、先に「Web, XML, Java EE and OSGi Enterprise Development」をインストールしてください
その後STSを再インストールします

私の場合は「Web, XML, Java EE and OSGi Enterprise Development」をインストールするのに以下のエラーに悩まされました

No repository found containing: osgi.bundle,org.aspectj.runtime.source,1.7.0.20120703164200

Webで調べてみるとリポジトリの情報をリロードしてくださいという記事が多かったのですが原因はそこではなかったようです

アプリ起動

インストールしたTomcat上で動作させてみます

起動

プロジェクトを右クリックして

Run As -> Run on Server

をクリックします
Tomcatインストール時にEclipse上に作成したTomcatサーバがあると思いますのでそれを選択します
select_server.png
選択したらFinishでアプリを起動します
※注意点としてはすでに8080でTomcatや別のアプリサーバが起動している場合は停止してから実施してください

Eclipseのコンソールに起動ログがずらーっと出てくると思います
長いので一部抜粋ですが、以下のように表示されればOKです

・・・

INFO : org.springframework.web.servlet.DispatcherServlet - FrameworkServlet 'appServlet': initialization completed in 1248 ms
3 12, 2015 1:35:19 午後 org.apache.coyote.AbstractProtocol start
情報: Starting ProtocolHandler ["http-nio-8080"]
3 12, 2015 1:35:19 午後 org.apache.coyote.AbstractProtocol start
情報: Starting ProtocolHandler ["ajp-nio-8009"]
3 12, 2015 1:35:19 午後 org.apache.catalina.startup.Catalina start
情報: Server startup in 3995 ms
INFO : com.sample.sample.HomeController - Welcome home! The client locale is ja_JP.

動作確認

http://localhost:8080/sample
にアクセスして「Hello World !」と表示されることを確認しましょう
ここで出力されている情報はsrc/main/webapp/WEB-INF/views/home.jspの内容を表示しています
jsp の内容を直接書き換えれば、Tomcatを再起動しないでも内容を修正できます

最後に

やはり環境を構築するところでつまづきました
Javaだけではないですが、本質的なことをする前の部分でこけるとやる気がなくなります
そして特にJava周りの環境構築ではつまづきやすい気がします

とりあえずSpringFrameworkを使ってアプリサーバ上で動作させることができました
ちゃんとしたWebアプリを作るのであれば最初からSTSをベースに開発したほうがいいかもしれません

あとは実際にwarを作成してデプロイしてみたり、maven経由でアプリを実行できるようになると更に便利かなと思いました
ちなみにこの状態でもmvn packageでwarファイルを作成できるところまでは確認しました

Eclipse + STS で Spring Data Redisをやってみた

概要

前回からの続きです
この状態からRedisと接続できるようにしてWebアプリとして動作できるようにします

環境

  • Mac OS X 10.10.2
  • Eclipse Luna 4.4.1
  • Spring Tool Suite 3.6.4
  • Java 1.8.0_31
  • Tomcat 8.0.20
  • Redis 2.8.19
  • Jedis 2.6.2
  • common-pool2 2.3

コード実装

既存のコードを修正して動作させるようにします

pom.xml修正

プロジェクトのディレクトリ直下にあります
/path/to/project/pom.xml

<dependencies>タグ内に以下を追記します

<dependency>
  <groupId>org.springframework.data</groupId>
  <artifactId>spring-data-redis</artifactId>
  <version>1.4.2.RELEASE</version>
</dependency>
<dependency>
  <groupId>org.apache.commons</groupId>
  <artifactId>commons-pool2</artifactId>
  <version>2.3</version>
</dependency>
<dependency>
  <groupId>redis.clients</groupId>
  <artifactId>jedis</artifactId>
  <version>2.6.2</version>
</dependency>

pom.xmlが長いので追記する部分だけ記載します
<!-- Spring -->というコメントがあるのでその付近を参考に記載すればOKです
公式のクイックスタートとかみるとこの辺の情報が不足していてcommon-pool2が必要とかjedisが必要とか記載されていないので困りました
これらの記述がないとNoClassDefFoundErrorになってしまいます

servlet-context.xml修正

結構深い階層にあります
/path/to/project/src/main/webapp/WEB-INF/spring/appServlet/servlet-context.xml

2箇所追記します

1つ目は先頭箇所でxmlnsを追加します

xmlns:p="http://www.springframework.org/schema/p"

2つ目はbeansの定義を追加します

<beans:bean id="jedisConnFactory"
    class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
    p:use-pool="true" />

<beans:bean id="stringRedisTemplate"
    class="org.springframework.data.redis.core.StringRedisTemplate"
    p:connection-factory-ref="jedisConnFactory" />

他にもbeansの定義が記載されていると思うのでその階層の並びに記載すればOKです
全文は長いので省略しますが特に迷うことなく追記できると思います

RedisController.javaの作成 

新規でコントローラとなるクラスを追加します
/path/to/project/src/main/java/com/sample/sample/RedisController.java

ソースの全貌は以下の通り

package com.sample.sample;

import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

@Controller
public class RedisController {

    private static final Logger logger = LoggerFactory.getLogger(RedisController.class);

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @RequestMapping(value = "/redis/get", method = RequestMethod.GET)
    public void get(@RequestParam(value = "key", required = true) String key, HttpServletResponse response) {
        logger.debug("/redis/get");
        String value = stringRedisTemplate.opsForValue().get(key);
        response.setStatus(200);
        response.setHeader("result", value);
    }

    @RequestMapping(value = "/redis/set", method = RequestMethod.GET)
    public void set(@RequestParam(value = "key", required = true) String key, @RequestParam(value = "value", required = true) String value, HttpServletResponse response) {
        logger.debug("/redis/set");
        stringRedisTemplate.opsForValue().set(key, value);
        response.setStatus(200);
    }

    @RequestMapping(value = "/redis/del", method = RequestMethod.GET)
    public void del(@RequestParam(value = "key", required = true) String key, HttpServletResponse response) {
        logger.debug("/redis/del");
        stringRedisTemplate.delete(key);
        response.setStatus(200);
    }

}

動作確認

curl + redis-cli で動作を確認します
まず起動します
プロジェクトを右クリックしてRun on Serverで起動します
起動後ターミナルで以下のコマンドを実行して動作確認します

  • set
curl 'http://localhost:8080/sample/redis/set?key=key-test&value=value-test'
127.0.0.1:6379> get key-test
"value-test"
  • get
curl -v 'http://localhost:8080/sample/redis/get?key=key-test'

ヘッダにRedisから取得したvalue情報があることを確認する

< result: value-test

  • del
curl 'http://localhost:8080/sample/redis/del?key=key-test'
127.0.0.1:6379> get key-test
(nil)

最後に

いかがでしたでしょうか

自分のググり不足+英語力不足なのですが、SpringDataRedisに関する情報はあまりWebにないような気がします
もしくは情報が古くて最新版だと動かないというケースが多いような気がします

とりあえずWebAPI + RedisをSpringFrameworkで実現することができました
JavaからRedisを使うだけならJedisを直接使うのでも全然簡単なのでいいのですが、Spring越しに使うことでSpringが用意したテンプレートやコネクションプーリングの機能を実装する必要がないので面倒な部分を省略できます
そもそもここまで来ることが非常に面倒でありますが

あとは、エラーハンドリングやらレスポンスボディやらは全く考慮できていないので、その辺は実装が必要です

Tips

2015年3月9日月曜日

ZabbixのAPIを使ってhistoryの一覧を取得してみた

概要

特定のホストに紐づくアイテムの履歴は「ヒストリ」と呼ばれる機能で提供されます
WebUIでヒストリ情報を確認したい場合、過去1,000個分のヒストリしか確認することができません
アイテムを30秒間隔で取得している場合には

30 * 1000 = 30,000 sec = 500 min = 8.3 hour

しか履歴を確認することができません

ZabbixAPIを使えばヒストリをすべて取得できそうだったので試してみました
言語はPHPを使用しています
PHPを使ってZabbixAPIをコールする方法の準備は済ませておいてください

環境

  • CentOS 6.3 64bit Final
  • Zabbix Server 2.0.5
  • Zabbix API 1.4
  • PHP 5.3.3

ヒストリ取得スクリプト

さっそくスクリプトを紹介します
使うためにはソース上の設定部分を直接修正します
次で使い方を紹介します

  • get_history.php
<?php

require 'ZabbixApi.class.php';

try {
    $hostid='10116';
    $itemid='28908';
    $history=3; // 0 - float; 1 - string; 2 - log; 3 - integer; 4 - text.

    $api = new ZabbixApi('http://hostname/api_jsonrpc.php', 'your user name', 'your uesrs password');
    $res = $api->historyGet(
      array(
        'history' => $history,
        'output' => 'extend',
        'hostids' => array (
          $hostid
        ),
        'itemids' => array (
          $itemid
        )
        #,'limit' => 10
      )
    );
    foreach ($res as $result) {
      $value = $result->value;
      $clock = $result->clock;
      echo $value . "," . date("Y/m/d H:i:s", intval($clock)) . "\n";
    }
} catch (Exception $e) {
    echo $e->getMessage() . "\n";
}

?>

使い方

今回は取得したいヒストリ情報は「指定したホストに紐づくアイテムのヒストリ」とします

サンプルで修正する箇所は以下の通り

  • $hostid・・・ホストのIDを記載します、IDはWebUIでホスト設定画面を表示すればURLに記載されます
  • $itemid・・・取得したいヒストリのアイテムIDを記載します、これもWebUIからアイテムの設定画面を表示すればURLに記載されています
  • hostname・・・ZabbixServerが起動しているサーバのホスト名を記載します
  • username・・・サンプルソースの「your user name」の部分を変更してください、WebUIにログインするためのユーザ名を記載すればOKです
  • password・・・サンプルソースの「your users password」の部分を変更してください

最低限上記を修正してください
必要に応じて以下も修正してください

  • $history・・・ヒストリとして保存されているアイテムの型を指定します、ここで型の指定が間違っているとうまくレスポンスが取得できず空が返却されてしまいます、デフォルトでは「3」のintegerが設定されています
  • limit・・・ヒストリがあまりにありすぎる場合、APIがタイムアウトしてしまいます、その場合はlimitを調整してください、もしくは開始時間(time_from)と終了時間(time_till)を指定して件数を削減してください

で実行は

php get_history.php

でOKです
結果は時系列順に「値,タイムスタンプ」のcsv形式で標準出力されます
表示形式等は必要に応じて変更していただければと思います

一応自分の場合はこれで2万弱のヒストリをlimitなしで取得することができました
APIのタイムアウトを調整できれば1回のリクエストで大量のヒストリを取得できると思います

参考サイト

2015年3月6日金曜日

zabbix-getコマンドだけインストール

概要

あれなぜか「zabbix-get」コマンドがないという場合に使えます

環境

  • CentOS 6.3 64bit Final
  • Zabbix Agent 2.0.5

インストール

公式で配布されているrpmを使います
ポイントはすでにインストールされているZabbixAgentと同じバージョンのrpmをインストールすることです

wget http://repo.zabbix.com/zabbix/2.0/rhel/6/x86_64/zabbix-get-2.0.5-1.el6.x86_64.rpm
rpm -ivh zabbix-get-2.0.5-1.el6.x86_64.rpm

今回はCentOS6系なので「el6」をダウンロードしています
CentOS5系の場合は別途「el5」も配布されているのでそちらをダウンロードしてください

動作確認

インストールされるパスは/usr/bin/zabbix_getです

zabbix_get --version

でバージョンが表示されればOKです

2015年3月5日木曜日

今更ながらHerokuを試してみた

logo_heroku.png

概要

herokuは自分が作ったアプリケーションをデプロイして動作させることのできるPlatform as a Service (PaaS)です
今回はサンプルのPHPアプリを動作させるところまでやってみました

環境

  • Heroku 2015/03/05 時点のサービス
  • Mac 10.10.2
  • PHP 5.6.6
  • Composer 1.0.0-alpha9
  • Homebrew 0.9.5

アカウントの作成

アカウントがない場合は作成します
メールアドレスさえあれば登録することができます
トップ画面から「Sign up」をクリックすれば登録画面に遷移するので必要な項目を入力して「Create Free Account」でアカウントを作成します
regist_account.png
アカウントの作成ができたらHerokuのダッシュボードにログインできることを確認してください
dashboard.png

開発環境の準備

Herokuと連携するためのツールやPHPアプリを開発するためのツールをローカル環境に構築していきます

heroku-toolbelt のインストール

heroku-toolbelt というHerokuにアプリをデプロイしたりすることのできるコマンドラインツールをインストールします
Homebrewがあるならば

brew install heroku-toolbelt

でOKです

Homebrewない場合はここのダウンロードボタンをクリックするとpkgファイルがダウンロードできます
download_toolbelt.png
pkgファイルを起動するとheroku-toolbeltをインストールするためのインストーラが起動するのでポチポチしてインストールしていきます
/usr/local/herokuに必要なコマンド等がインストールされました

最終的にherokuコマンドが使えるようになっていればOKです

heroku --version

heroku-toolbelt/3.28.2 (x86_64-darwin10.8.0) ruby/1.9.3
You have no installed plugins.

herokuへのログイン

インストールしたherokuコマンドを使ってコマンドからherokuにアクセスできるようにログインします
heroku loginというコマンドを使います
実行するとダッシュボードにログインするためのメールアドレスとパスワードを聞かれるので入力します

heroku login

Enter your Heroku credentials.
Email: xxxxxxxxx@gmail.com
Password (typing will be hidden): 
Authentication successful.

「Authentication successful.」と出ればOKです

PHP関係のインストール

サンプルを動作させるのに必要になるのはphpcomposerです
Homebrewを使ってインストールしました
ない場合はそれぞれの公式サイトにインストール方法が記載されているので適宜インストールしてください

  • PHP
brew tap homebrew/php
brew install php56
php -v

PHP 5.6.6 (cli) (built: Feb 25 2015 17:07:38) 
Copyright (c) 1997-2015 The PHP Group
Zend Engine v2.6.0, Copyright (c) 1998-2015 Zend Technologies
  • Composer
brew install composer
composer -v

Composer version 1.0.0-alpha9 2014-12-07 17:15:20

サンプルアプリの作成

PHPアプリを開発できる環境が整ったらサンプルアプリを作成していきましょう
作成するといってもすでにあるサンプルアプリを持ってくるだけです
gitで持ってきましょう

git clone https://github.com/heroku/php-getting-started.git

持ってきたらローカルで動作するか試してみます

cd php-getting-started
composer udpate
foreman start web

http://localhost:5000/にアクセスしてみましょう
「Hello」と表示されるサンプルのアプリが表示されると思います

ローカルので動作が確認できたら次にHeroku上にデプロイしてみます

Tips

  • Could not fetch https://api.github.com/authorizations, enter your GitHub credentials to go over the API rate limit
    composer update時に上記が出たときにUsernameとPasswordを求められると思います
    GithubのAPIをcomposer上でコールしており、もしGithubのアカウントがあるならばGithubのUsernameとPasswordを入力してください
    入力後一旦Ctrl+cで抜けて再度composer updateすれば問題なく動作すると思います

  • foreman
    唐突に出てきましたがRuby製のツールでProcfileを読み込み複数のプロセスを管理してくれます
    コマンド自体はheroku-toolbeltをインストールした際に同時にインストールされています
    ただ、今回の場合サンプルアプリを動作させるのにhttpdコマンドが必要になるのでインストールされていない場合は別途インストールしてforemanコマンドを実行してみてください
    また、mod_proxy, mod_proxy_fcgi, mod_rewrite の拡張モジュールも必要になるので有効にする必要があります

brew tap homebrew/apache
brew install httpd24

sed -i -e 's/\#LoadModule proxy_module libexec\/mod_proxy.so/LoadModule proxy_module libexec\/mod_proxy.so/g' /usr/local/etc/apache2/2.4/httpd.conf
sed -i -e 's/\#LoadModule proxy_fcgi_module libexec\/mod_proxy_fcgi.so/LoadModule proxy_fcgi_module libexec\/mod_proxy_fcgi.so/g' /usr/local/etc/apache2/2.4/httpd.conf
sed -i -e 's/#LoadModule rewrite_module libexec\/mod_rewrite.so/LoadModule rewrite_module libexec\/mod_rewrite.so/g' /usr/local/etc/apache2/2.4/httpd.conf

apachectl stop
apachectl start

Heroku上にデプロイ

早速サンプルアプリをデプロイしてみましょう

アプリの作成

herokuコマンドを使って作成します

heroku create

Creating shielded-citadel-7646... done, stack is cedar-14
https://shielded-citadel-7646.herokuapp.com/ | https://git.heroku.com/shielded-citadel-7646.git
Git remote heroku added

上記の場合「shielded-citadel-7646」というアプリがHeroku上に作成されています
ダッシュボードで確認してみるといいと思います
create_app.png

アプリ名を変更する場合は「heroku apps:rename changed-app-name」でできます
「changed-app-name」に好きなアプリ名を入力してください
アプリ名はHeroku上で一意である必要があるのですでに使われている場合は使用できません
アプリ名の変更はダッシュボード上からでも可能です(アプリ選択 -> Settings -> Name)

アプリのデプロイ

gitコマンドを使ってデプロイすることができます

git push heroku master

これだけです
デプロイが完了したら
https://shielded-citadel-7646.herokuapp.com/
にアクセスしてみましょう(私のアプリの場合)

URLは https://your-app-name.herokuapp.com/ の命名規則でアクセスすることができます
デプロイ時のログにもアクセスURLが記載されていると思います
もしくはもっと簡単に開く方法として

heroku open

があります

その他便利なコマンド

  • heroku logs –tail
    サーバ上のアクセスログを確認することができます
  • heroku apps
    存在するアプリの一覧を表示することができます
  • heroku apps:destroy –app shielded-citadel-7646 –confirm shielded-citadel-7646
    指定したアプリをHeroku上から削除します
    普段は使いませんが、テストで繰り返しアプリを作成し直したい場合に便利です
  • heroku apps:info
    アプリの詳細を確認することができます

最後に

詳細に説明しているので長くなっていますがやっていることは単純なので、簡単に導入できると思います
同じやり方で既存のPHPアプリもデプロイできそうなので、次回は自分が作成したサンプルアプリでも動かしてみようと思います

無料でここまで使えるのは素晴らしいですね

参考サイト

2015年3月4日水曜日

ニフティクラウドmobile backendでPush通知できるRubyスクリプト

P.S 20150914
POST スクリプトも gist で公開しました
https://gist.github.com/kakakikikeke/ef34c3a0180961262607
同時に curl コマンドを出力できるようにしました

概要

ニフティクラウドmobile backendのプッシュ通知をコンパネからではなくRubyスクリプトからできるようにしてみました

環境

  • Mac OS 10.10.2
  • Ruby 2.2.0p0

スクリプト

  • post_push.rb
require 'rest_client'
require 'json'
require 'time'
require 'hmac'
require 'hmac-sha2'
require 'base64'
require 'openssl'

APPLICATION_KEY='Please input your apps application key'
CLIENT_KEY='Please input your apps client key'
ENDPOINT='mb.api.cloud.nifty.com'
VERSION='2013-09-01'
SIG_METHOD='HmacSHA256'
SIG_VERSION=2
PATH='/push'

def main
  post_push
end

def post_push
  timestamp = get_timestamp
  signature = create_signature(
    "POST",
    ENDPOINT,
    VERSION,
    PATH,
    CLIENT_KEY,
    "X-NCMB-Application-Key" => APPLICATION_KEY,
    "X-NCMB-Timestamp" => timestamp,
    "SignatureMethod" => SIG_METHOD,
    "SignatureVersion" => SIG_VERSION,
  );
  params = {
    'immediateDeliveryFlag' => true,
    'target' => [
      "ios"
    ],
    'message' => timestamp
  }
  response = RestClient.post( "https://#{ENDPOINT}/#{VERSION}#{PATH}",
    params.to_json,
    {
      :content_type => 'application/json',
      'X-NCMB-Application-Key' => APPLICATION_KEY,
      'X-NCMB-Timestamp' => timestamp,
      'X-NCMB-Signature' => signature
    })
  json = JSON.parse(response)
  puts json
end

def create_signature(method, endpoint, version, path, client_key, options = {})
  application_key = options["X-NCMB-Application-Key"]
  timestamp = options["X-NCMB-Timestamp"]
  canonical_querystring = options.sort.collect { |key, value| [key, value].join('=') }.join('&')
  string_to_sign = "#{method}\n#{endpoint}\n/#{version}#{path}\n#{canonical_querystring}"
  hmac = HMAC::SHA256.new(client_key)
  hmac.update(string_to_sign)
  signature = Base64.encode64(hmac.digest.to_s).chomp
  return signature
end

def get_timestamp
  return Time.now.utc.xmlschema.gsub("Z", ".456Z")
end

main
  • Gemfile
source "https://rubygems.org"

gem "rest-client", ">= 1.7.3"
gem "ruby-hmac", ">= 0.4.0"

実行方法

bundle install && bundle exec ruby post_push.rb

bundlerを使って実行していますがGemfileに書かれている必要なgemをインストールしてruby post_push.rbでもOKです

解説

必ずやらなければいけない設定はAPPLICATION_KEYCLIENT_KEYをコントロールパネルのアプリ設定から取得したキーに書き換えるくらいです
あとは必要に応じて実施すればOKです

プッシュのパラメータはparams変数で管理しています
即時配信でプッシュに送信されるメッセージは送信時のタイムスタンプが表示されます
対象はiOSだけなので必要であればandroid も配列に追加してください
その他のパラメータはここを参照してください
例えばsearchConditionを使って特定のデバイスにのみ送信したい場合はparams変数を以下のように変更します

params = {
  'immediateDeliveryFlag' => true,
  'searchCondition' => {
    'deviceToken' => 'hoge deviceToken'                                    
  },
  'target' => [
    "ios"
  ],
  'message' => timestamp
}

searchConditionパラメータはオブジェクト型なのでハッシュで設定しています
各パラメータに応じた適切な型を設定してあげないとうまくAPIをコールできないので注意してください

あとあくまでもこれが使えるのはプッシュ通知に必要な設定を実施しているのが前提です
プッシュ通知自体をまだ設定していないという場合は過去にやり方を紹介しているのでご覧ください

GET版も作ってみたのでよければ見てください

2015年3月3日火曜日

Cygwin上のgitで「error: cannot fork() for index-pack: Resource temporarily unavailable」

概要

Cygwin上のgitを使ってgit pullしようとしてもエラーとなってpullできない現象が発生したので解決方法を紹介します
エラーの内容は以下のとおり

remote: Counting objects: 809, done.
remote: Compressing objects: 100% (372/372), done.
      0 [main] git 3984 fhandler_disk_file::fixup_mmap_after_fork: requested 0x6FFBFD10000 != 0x0 mem alloc base 0x0, state 0x10000, size 1096254554112, Win32 error 1455
    310 [main] git 3984 C:\cygwin64\usr\libexec\git-core\git.exe: *** fatal error in forked process - recreate_mmaps_after_fork_failed
   1335 [main] git 3984 cygwin_exception::open_stackdumpfile: Dumping stack trace to git.exe.stackdump
      0 [main] git 9004 fork: child -1 - forked process 3984 died unexpectedly, retry 0, exit code 0x100, errno 11
error: cannot fork() for index-pack: Resource temporarily unavailable
fatal: fetch-pack: unable to fork off index-pack

環境

  • Windows7 64bit
  • Cygwin 1.7.32
  • git 2.1.1

対処方法

エラーの内容でいろいろとググってみたのですが、原因はconflict等ではなくPC上のリソースにありそうだとわかりました
メモリが少ないとかPATHが通っていないのでは、といった記事を多くみかけました
自分の場合は以下で対応できました

  • git上のリポジトリをEclipseで開いていたのでEclipseを終了したら正常にpullできた

まさかと思ってやってみたら本当にできたのでビックリしました
Eclipseは結構メモリを食うのでメモリ消費が原因だったのかもしれないですが
できないときは試してみるのもありかもしれません