2014年12月23日火曜日

SastrutsのInterceptor機能を試してみる

概要

前回のチュートリアルでは主に「Action」と「Form」と「Dto」という機能について学びました
今回は「Interceptor」という機能について学んで行きます
Interceptorは共通処理を実行させるのに適した機能になります

環境

  • Windows7 64bit
  • Eclipse Luna 4.4.1
  • Apache Tomcat 7.0.56(設定はデフォルト)
  • JDK 1.8.0_25

サンプルコード

前回やったチュートリアル用のプロジェクトを使って話を進めていきます

パッケージを作る

tutorial.interceptorというパッケージを作成します
これは必須ではないですが今回はInterceptorクラスをこのパッケージで管理します

Actionクラスの確認

前回使ったtutorial.action.TestAction.javaをそのまま使います
特に拡張はしませんが動作することを確認しておいてください

Interceptorクラスを作成する

先ほど作成したtutorial.interceptorパッケージ配下にTestInterceptor.javaを作成します
TestInterceptor.javaはAbstractInterceptorクラスを継承してください
AbstractInterceptorクラスを継承すると自動的にinvokeメソッドを実装する必要があります

invokeメソッド内で引数のinvocationオブジェクトを使ってinvocation.proceed();をコールします
すると、Actionクラスのindex()メソッドが実行されます
つまりinvocation.proceed();の前後に処理を書くことでAction実行前後で決められた処理を自動的にコールすることができるようになります

package tutorial.interceptor;

import org.aopalliance.intercept.MethodInvocation;
import org.seasar.framework.aop.interceptors.AbstractInterceptor;

public class TestInterceptor extends AbstractInterceptor {

    /**
     * 識別番号
     */
    private static final long serialVersionUID = 1L;

    public Object invoke(MethodInvocation invocation) throws Throwable {
        System.out.println("before");
        // これが実行されるとAction.index()メソッドが実行される
        Object object = invocation.proceed();
        System.out.println("after");
        return null;
    }

}

app.diconに追記する

作成したTestInterceptorを有効にするにはapp.diconに定義を追加する必要があります
<components>...</components>タグ内に以下の1行を追加してください

<component name="testInterceptor" class="tutorial.interceptor.TestInterceptor"/>

customizer.diconに追記する

面倒ですがもう1つのdiconファイルに設定を追記します
先ほどのapp.diconはcomponentを定義してcustomizer.diconでそのcomponentをどこで使うかの定義を記載する感じです
追加する部分は<component name="actionCustomizer" class="org.seasar.framework.container.customizer.CustomizerChain">...</component>内に記載します

<initMethod name="addCustomizer">
    <arg>
        <component class="org.seasar.framework.container.customizer.AspectCustomizer">
            <property name="interceptorName">"testInterceptor"</property>
            <property name="useLookupAdapter">false</property>
            <initMethod name="addClassPattern">
                <arg>"tutorial.action"</arg>
                <arg>"TestAction"</arg>
            </initMethod>
        </component>
    </arg>
</initMethod>

addClassPatternを使うことで特定のパッケージのクラスにのみInterceptorを適用することができます
addClassPatterは内部的にはメソッドとして扱われており<arg>で引数を2つ取ります
1つ目の引数がパッケージ名で2つ目の引数がクラス名になります、この2つの引数は必須になります
クラス名やパッケージにはワイルドカードが使えるほか、複数指定する場合はカンマ区切りで指定してください

動作を確認する

Tomcatを一旦再起動しましょう

http://localhost:8080/sa-struts-tutorial/test/?message=helloにアクセスしてみましょう
ブラウザ上ではメッセージが表示されますがEclipse側のコンソールに「before, after」が表示されていると思います

紹介は以上です
Interceptorのだいたいの動きがわかったかと思います
メインロジックであるActionの前後で実施したい処理がある場合には重宝される機能だと思います

2014年12月22日月曜日

device not found

概要

Eclipse + Androidで開発をしていてEclipseのコンソールで

[2014-12-16 22:06:57 - DDMS] device not found
com.android.ddmlib.AdbCommandRejectedException: device not found
    at com.android.ddmlib.AdbHelper.setDevice(AdbHelper.java:774)
    at com.android.ddmlib.AdbHelper.executeRemoteCommand(AdbHelper.java:396)
    at com.android.ddmlib.AdbHelper.executeRemoteCommand(AdbHelper.java:347)
    at com.android.ddmlib.Device.executeShellCommand(Device.java:610)
    at com.android.ddmuilib.SysinfoPanel$1.run(SysinfoPanel.java:209)
    at java.lang.Thread.run(Thread.java:745)

みたいなエラーが出てEclipse側にlogcatが流れなくなった場合の対応方法を紹介します
昔のこの状態になったら諦めてエミュレータ+Eclipseを再起動していました

環境

  • Mac OS X 10.8.5
  • Eclipse Kepler 4.3
  • ADT 23.0.2

対応方法

Eclipseから

Window -> Open Perspective -> Other -> DDMS

open_ddms.png
を選択

「Devices」というViewを見つけて下矢印を選択
「Reset adb」という選択肢があるのでクリック
choice_reset_adb.png

するとエラーが出ますが無視
error.png
このときコンソールのログを見ると

[2014-12-19 18:59:07 - DeviceMonitor] Connection attempts: 11

みたいなログが出ています
これが止まるまで待ちます、たぶん12くらいで止まると思います

そしたら再度「Devices」Viewにあるプロセスを一個選択(何でもいい)
touch_some_one.png

ってやるとLogcatにダーっとログが流れ始めると思います

これでEclipseの再起動を待つあの時間からも開放されました

2014年12月21日日曜日

Biglobeで申し込んだWiMAX2が来たのでセットアップしてみた

概要
Biglobeで申し込んだWiMAX2が届いたので送付物とそのセットアップ方法を紹介します
接続できた後に管理画面から詳細に設定する方法も紹介します

環境

  • WiMAX2 Wi-Fi WALKER NAD11
  • Mac OS X 10.8.5

設定

送付物一覧

入っていたもの概要は以下の通り

  • au SIMカード
  • WiMAX2本体(ACアダプター)
  • クレードル
  • 書類(保証書、説明書)

まずは箱今回は赤を選んだので箱も赤でした
box.jpg

以下のものはこの箱の中に全部入っていました
まずはSIMカード
sim.jpg
特にないです、auのSIMを使うんですね

次に本体一式
**enter image description here**
大きさはスマホよりちょっと小さいくらい
重さもスマホよりちょっと軽いくらい

書類
写真は省略
設定方法が記載されている説明書やSSIDの情報が記載されているシールがあります

クレードル
cradle.jpg
これは別で同梱されていたものです、箱の中には入っていませんでしたが一応紹介します
いわゆる立てかけ用のアダプタです
今回は使わないかもです

以上、あとは納品書とかあったけどそれはいいかなと思い省略

セットアップ方法

本体を組み立てる

早速セットアップしていきます
まずはSIMカードを外します、押せば普通に取れます
take_off_sim.jpg

次に本体にSIMカードを取り付けます
説明しにくいですが本体の中にSIMカードを入れる部分があるのでそこにいれます
入れる方向に注意してください
ちゃんと入ると「カチッ」っていうのでそこまで押し込んでください

電池も取り付けます
これは特に問題ないと思います、そのまま付けてください
take_on_sim_battery.jpg

SIMと電池パックを取り付けたら背面を取り付けます
これも向きがあるので注意してください
complete.jpg

そして完成
complete2.jpg

電源を入れる

電源を入れます
ACアダプターを袋から取り出してコードとプラグ部分を接続します
そしたらMicroUSBとアダプターを接続します
付属のアダプターのコードの長さが短かったので今回自分は別のMicroUSBのコードを使用しました
joint_code.jpg

ACアダプターを繋いで充電し始めたら側面にある銀のボタンを押して電源を入れます
すると正面の液晶に「Please wait」と表示されるのでちょっと待ちます
液晶画面が電波の画面になれば起動完了
start.jpg

あとはPCから接続テストして完了です

PCから接続してみる

今回はMac Book Airから接続してみます
接続するにはSSIDという接続するための識別番号を探す必要があります
SSIDを知るには付属の書類にシールみたいなのがあってそれにk記載されています
「プライマリSSID」というのが記載されているのでそれに接続します

Mac本体のWi-FIをONにすると勝手にSSIDを探してくれるのでSSIDが見つかったらそれを選択します
おそらくですが、同じNAD11系を買えばSSIDも「nad11-」から始まっていると思います

パスワードも書類に記載されているので、それを入力してください
input_password.png
認証が完了すればOKをです
(自分はあとでSSIDを変更するので特にマスクしないで出しちゃってます)

とりあえずこれでネットにつなぐことができるようになると思います
普通に使いたいだけならこれでOKですが、更に詳細にネットワークに接続したい場合は管理画面で設定する必要があります

詳細設定

いろいろできます
ので今回は自分が設定した項目を紹介します
ここからの作業は必須ではないので実施したい方は参考にしてみてください

管理UIに接続

ifconfigで自分のプライベートIPを調べます
おそらくそれの末尾「.1」にブラウザでアクセスすると管理UIが表示されると思います
自分の場合は「http://192.168.179.1/」でアクセスできました
admin_ui.png

基本設定

  • 管理ユーザのパスワードを変更
    おそらく初回に設定変更する場合にパスワードの設定を求められると思います
    これは管理UIで設定変更するためのパスワードなのでSSIDに認証するパスワードとは別物になります
    設定後は忘れずに保存しておいてください

ネットワーク設定

  • 通信量カウンター

    詳細設定Topへ -> ネットワーク設定 -> 基本設定 -> 通信量カウンター

    • 最大データ通信量設定を100GBに設定します
    • カウントするネットワーク(WiMAX)にチェックを入れます

無線LAN設定

  • ネットワーク名の変更

    詳細設定Topへ -> 無線LAN設定 -> 無線LAN設定 -> ネットワーク名(SSID)

  • パスワードの変更

    詳細設定Topへ -> 無線LAN設定 -> 無線LAN設定 -> WPA暗号化キー(PSK)

上記を変更して設定をクリックすれば即時反映されると思います
SSID変更後はPC側で接続するSSIDを変更してください
また、パスワード変更後はSSIDに認証する際のパスワードの設定を変更してください

その他メモ

  • プライベート側のIPアドレス帯は変更できる模様、DHCPサーバのリースタイムも設定できる

    トップページ > 詳細設定 > LAN側設定

  • ポートの開放はポートマッピング設定から実施する

    トップページ > 詳細設定 > ポートマッピング設定> エントリ追加

  • パスワードの設定はメンテナンスから

  • いろいろ設定を変更するのは詳細設定でできる(VPNとか)
  • Macだけかもしれないですが、急にループバックIP(169.254から始まるIP)を振る場合があります、その場合はルータを管理画面から再起動してみてください
  • P.S 20151229 ネットワークの不安定を改善する方法
    • トップページ > 無線LAN設定 > 無線LAN設定 -> 暗号化 -> 暗号化キー更新間隔(分) -> 0
    • トップページ > 無線LAN設定 > 無線LAN設定 -> 拡張設定 -> 無線優先制御機能 -> 使用するのチェックを外す
    • トップページ > 無線LAN設定 > 無線LAN設定 -> 拡張設定 -> 送信出力 -> 50%
    • トップページ > 無線LAN設定 > 無線LAN設定 -> 拡張設定 -> マルチキャスト伝送速度(Mbps) -> 5.5

2014年12月20日土曜日

Mavenでmainメソッドを実行する方法

概要

src/main/java … に作成されたクラス内にmainメソッドを書いて実行させる方法を紹介します

環境

  • CentOS release 5.10 (Final)
  • Maven 3.1.0
  • exec-maven-plugin 1.2.1

設定

exec:javaというゴールを指定してmvn実行します

pom.xml設定

<build>
  <plugins>
    <plugin>
      <groupId>org.codehaus.mojo</groupId>
      <artifactId>exec-maven-plugin</artifactId>
      <version>1.2.1</version>
      <configuration>
        <mainClass>com.kakakikikeke.sample.App</mainClass>
      </configuration>
    </plugin>
  </plugins>
</build>

変更すべき箇所は<mainClass>です
環境に合わせてパッケージ名から指定してください
App.javaにはmainクラスが含まれる必要があります

また、上記のタグは<project>タグ直下に記載してください

実行

mvn clean compile exec:java

実行されると以下のような感じで表示されます(System.out.printlnの場合、start, endの部分)

... 略 ...

[INFO] >>> exec-maven-plugin:1.2.1:java (default-cli) @ jedis >>>
[INFO]
[INFO] <<< exec-maven-plugin:1.2.1:java (default-cli) @ jedis <<<
[INFO]
[INFO] --- exec-maven-plugin:1.2.1:java (default-cli) @ jedis ---
start
end
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 4.842s
[INFO] Finished at: Thu Dec 18 16:40:41 JST 2014
[INFO] Final Memory: 13M/206M
[INFO] ------------------------------------------------------------------------

Mavenの場合ロジック側を動かそうとするとテストかかないとダメなので、ちょっと動作させたいときにはいいかなと
めちゃくちゃ見づらいですが。。

2014年12月19日金曜日

Mavenで実行可能Jarを作成する方法

概要

「jar -jar hoge.jar」みたいな感じで実行できるjarを作成する方法です
packageのゴールを使って生成できるようにします

環境

  • CentOS release 5.10 (Final)
  • Maven 3.1.0
  • maven-assembly-plugin 2.5.2

設定

pom.xml設定

<build>
  <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-assembly-plugin</artifactId>
      <version>2.5.2</version>
      <configuration>
        <finalName>App</finalName>
        <descriptorRefs>
          <descriptorRef>jar-with-dependencies</descriptorRef>
        </descriptorRefs>
        <archive>
          <manifest>
            <mainClass>com.kakakikikeke.sample.App</mainClass>
          </manifest>
        </archive>
      </configuration>
      <executions>
        <execution>
          <id>make-assembly</id>
          <phase>package</phase>
          <goals>
            <goal>single</goal> <!-- goals == mojos -->
          </goals>
        </execution>
      </executions>
    </plugin>
  </plugins>
</build>

変更すべき箇所は<mainClass>です
環境に合わせてパッケージ名から指定してください
<finalName>で作成するJarのprefixを指定できます

また、上記のタグを<project>タグの直下に記載してください

実行

mvn clean compile package

完了するとtarget配下にtarget/App-jar-with-dependencies.jarというjarファイルができていると思います
実行する場合は

java -jar target/App-jar-with-dependencies.jar

で実行してください
実行可能jarなので必要なライブラリやクラスファイルは全部jarの中に同梱されています

2014年12月18日木曜日

Could not connect to Redis at 127.0.0.1:6379: Cannot assign requested address

概要

redis-cliを使ってHSETのデータ大量に投入しているときに発生した
データのTypeによると思うが2万件ほどデータを投入したところでタイトルのエラーが発生した
テストデータを入れるだけでエラーが出るたび毎回2万件ずつしか登録できないのは面倒だったので対応してみた

環境

  • CentOS release 5.10 (Final)
  • Redis 2.6.13 ( server, cli ともに)

対応方法

echo 1 > /proc/sys/net/ipv4/tcp_tw_reuse

を実行してから再度redis-cliを実施すると出ないはず

https://github.com/antirez/redis/issues/340
に記載してあったがkeepaliveを無効にしているみたい

連続で大量にredis-cliを実行するとコネクションが残ってしまいエラーが出ていたみたい
一応自分は検証用のマシンだったのでやったけど本番とかだとちょっと怖いかも

さらっとデータだけ入れたい場合とかに使ってみてはいかが

2014年12月13日土曜日

error loading /system/media/audio/ui/KeypressDelete.ogg

概要

自分の場合、該当エラーが出たのはエミュレータで動作テストしているときにListView各項目をタップすると発生しました

環境

  • Mac OS X 10.8.5
  • Eclipse 4.3 (Kepler)
  • Android SDK 23.0.2 (Homebrewでインストール)
  • Android 4.4.2

対応策

エミュレータの設定を変更するだけです

起動してアプリ一覧を表示して
start_emulator.png

アプリ一覧から設定を起動して
open_config.png

設定から音の設定を開いて
open_sound.png

音の設定から音量の設定を開いて
open_volume.png

3つある音量の設定を全部0にしてOKして
set_volume_0.png

音の設定の下のほうでチェックのついている項目を外します
sound_check_off.png

これで完了、
再度アプリを開いてLogcatを見て該当のエラーが出ていないことを確認してみてください
自分はこれでOKでしたが、これでもダメな場合は他にもサウンドの設定をしている箇所があるかもしれません

ちなみにAVDの設定は以下の通りです
my_avd.png

2014年12月12日金曜日

シェルスクリプトでlog4jみたいにロギングできるスクリプトがあったので試した

概要

これを試してみました

環境

  • CentOS 6.3 64bit
  • bash 4.1.2

使い方

  • 適当な場所に配置
cd /var/tmp
wget http://www.mitchy-world.jp/itmemo/shell/download/06.zip
unzip 06.zip
cd 06
  • ログの出力先を変更
    emacs common1.sh
    以下を好きなフルパスに変更してください
LOG_DIR=`pwd`"/"
  • サンプルを試す
cd /var/tmp/06
sh log4jtest1.sh
cat SHELL-001.log

SHELL-001.logというファイルができているので中身を確認するとログがでています

  • ログレベルを変更する
    emacs common1.sh
SYSTEM_LOG_LEVEL=DEBUG

で再度log4jtest1.sh実行するとDEBUGレベルのログも出力されるようになります

  • 独自のスクリプトから使ってみる
    emacs test.sh
#!/bin/bash                                     

. ./common1.sh

logDebug "app" "this is a debug log"

test.shを実行するとapp.logというファイルができていると思います
LogLevelはDEBUGに変更してから実施してください、LogLevelがINFOだとファイルが出力されません
ポイントは. ./common1.shでこれが書いていないとそもそもダメです

以上、簡単でした
common2.shというファイルもありますが結果は同じになります
関数の戻りがechoorreturnの違いでした

2014年12月10日水曜日

Zabbixのアクションでシェルスクリプトを実行する方法 その2

概要

過去にZabbix 1.8で検証していましたが
Zabbixの2系でも試してみました

環境

  • CentOS 6.3 final 64bit
  • Zabbix 2.0.3

設定

事前準備

今回前提として

  • ホストの登録(ホストグループも必要であれば)
  • アイテムの登録(テンプレートも必要であれば)
  • トリガーの登録
  • ホストとアイテムおよびトリガーの紐付け

上記が完了しているとしてアクションを作成してリモートホストにシェルスクリプトを実行させてみます
あとZabbixのインストールはChefで実施しています(Chefはソースコンパイルしてmake installしていた)

アクション作成

設定 -> アクション -> アクションの作成

といきアクションの作成画面を表示します

アクションの概要を設定

まずは「アクション」の設定です
名前は適当に入力します
リカバリメッセージは送信したいと思うのでチェックボックスをONにします
config_action_base.png

アクションの実行条件を設定

次にアクションの実行条件を設定します
ポイントは「トリガーの値 = “障害” 」を削除します
これを削除しないとリカバリメッセージが送信されません
デフォルトのアクションだと「メンテナンスの状態 期間外 “メンテナンス”」が入っていますがこれはこのままでOKです
あとは自分で追加したいトリガーを追加すればOKです
config_action_condition.png

アクションの実行内容を設定

最後に「アクションの実行内容」を設定します
ここに具体的に実行するリモートホストの情報やシェルスクリプトの情報を記載します

デフォルトは何もないので新規で登録します
実行内容の詳細を設定していきます
実行内容のタイプは「リモートコマンド」を選択します

そのすぐ下にターゲットリストがあります

新規 -> ターゲットでホストを選択 -> 選択からリモートホストを実行させるホストを指定 -> 追加

としてシェルスクリプトを実行させたいリモートホストを選択します
選択後に「追加」をクリックすることを忘れずに

次にタイプを設定します
今回はリモートホストにSSH経由でシェルスクリプトを実行したいと思います
なのでZabbixサーバからシェルスクリプトを実行するリモートホストへのSSHは通信できるように事前に設定しておいてください
認証方式は「パスワード」と「公開鍵」のどちらかが選択できますのでお好みに合わせて選択してください
※と、いいたいところなのでが自分がZabbix2.0.3で試した限りだと公開鍵を選択した場合うまくできませんでした(自分のZabbix力が足りなかっただけかもしれませんが)

ログインするためのユーザ名やパスワード、ポート番号の入力してください
そして、ここで実行するシェルスクリプトを記載します
リモートホストで実行できるシェルスクリプトであれば何でもOKです

最後にアクションの実行条件を設定します
新規から「障害対応済 = “コメントなし”」を設定します

ここまで入力できたら一番下の追加をクリックします
config_action_execute.png

アクションのすべての設定が完了したら「保存」をクリックします
これでアクションの作成が完了しました

zabbix側の設定

zabbi_serverのlibssh2を有効にする

zabbix_server.logの中に以下のように「SSH2 support NO」が出ている場合はSSH2を有効にする必要があります

 21535:20141209:130822.629 ****** Enabled features ******
 21535:20141209:130822.629 SNMP monitoring:           YES
 21535:20141209:130822.629 IPMI monitoring:            NO
 21535:20141209:130822.629 WEB monitoring:            YES
 21535:20141209:130822.629 Jabber notifications:       NO
 21535:20141209:130822.629 Ez Texting notifications:  YES
 21535:20141209:130822.629 ODBC:                       NO
 21535:20141209:130822.629 SSH2 support:               NO
 21535:20141209:130822.629 IPv6 support:               NO
 21535:20141209:130822.629 ******************************

面倒ですが、再度コンパイルしてインストールし直す必要があります
※自分の場合はchefからインストールしたのでその場合の手順ですが、rpmとかyumでイントールした人も同じような手順でいいのだろうか。。。

/etc/init.d/zabbix_server stop
cp /opt/zabbix/sbin/zabbix_server{,.back}
cd /opt/zabbix-2.0.3-server/
make clean
./configure --enable-server --with-mysql --with-libcurl --with-net-snmp --with-ssh2
make install
cp /usr/local/sbin/zabbix_server /opt/zabbix/sbin/
/etc/init.d/zabbix_server start

でzabbix_server.logに「SSH2 support NO」が出ていないことを確認します
それでもダメな場合はrpm -qa | grep libssh2がインストールされているか確認してください
インストールされていない場合はyumでインストールしてください
※普通にやっていたらこれに気がつくほうが大変、そしてlibssh2はEPELが必要。。。

zabbix_agetnd.confの設定

シェルスクリプトを実行するリモートホスト側のzabbix_agentd.confに
EnableRemoteCommands=1
が設定されているか確認してください
なければ追加してzabbix_agentを再起動してください
これがないとリモートホストでシェルスクリプトを実行する権限がなく実行に失敗します

sshd_configの設定

今回はパスワード認証を使ってSSHログインするのでログインするリモートサーバ側のユーザのpasswdは設定しておいてください
また、/etc/ssh/sshd_config

  • PasswordAuthentication yes

にしておいてください
実際にZabbixに設定するユーザ情報でログインできるか確認したい場合はZabbixサーバ上のzabbixユーザからリモートサーバにパスワードログインできるか確認してみてください
ACLや権限周りの確認もあるのでログインの確認はやっておいて損はないと思います

試してみる

トリガーの閾値などを極端に低くしたりしてトリガーに引っかかるようにしましょう
その状態にしたときにアクションが実行されるか確認してください

トラブルシューティング

  • うまくシェルスクリプトが実行されない
  • Zabbixを見るとアクションのステータスが未送信になっている
  • ACLおよび認証情報や権限周りが問題ないか再度確認する

うまく一発で想定どおりの動作をすることがあるかもしれませんが、自分の経験的には、まずありえません
うまく実行されない場合にはzabbix_server.logを確認してみましょう
その前にzabbix_server.confのDebugLevelが「4」になっているか確認しましょう
なっていないようなら4に変更してzabbix_serverを再起動してください

変更できたらログを確認します
おそらく/var/log/zabbix/zabbix_server.logがあるかと思いますがこいつが厄介でものすごい速さでログが流れて
ものすごい速さでローテートされてどんどん過去のログがなくなっていきます(5分前のログとかもすぐになくなります)
なのでログが追えないという場合にはzabbix_server.confのLogFileSize=0をzabbix_server.confに記載して再起動するとローテーションされなくなります
ただ、この場合はローテーションがされずどんどんログサイズが肥大化していきます
すぐにログの確認が終わる場合はいいですが終わらない場合に、いつの間にかファイルサイズがとんでもないことになっていてディスク逼迫している。。。なんてこともありますので気をつけてください

自分はローテーションを無効にする設定をするのも面倒だったので
while :; do tailf /var/log/zabbix/zabbix_server.log | grep 'alerts'; done;
でログを見ていて
トリガーが発砲されたときのログ(以下のようなやつ)をメモって
19675:20141209:114118.008 query [txnlev:1] [insert into alerts (alertid,actionid,eventid,clock,message,status,error,alerttype,esc_step) values (10,6,10399,1418092878,'remote_host:hostname

急いでtailfを解除して、そのときのzabbix_server.logを適当な場所にコピーします
そして、コピーしたそのファイルで「19675:20141209:114118.008」を検索してその辺りのログにシェルスクリプトが失敗しているログがあるのでそれで調べていました(超絶ださいですね)

この辺のトラブルシューティングがログを見る方法しかないのがちょっと辛いです

遭遇したエラー

  • Support for SSH script was not compiled
    --with-ssh2で再コンパイル
  • Unsupported authentication method. Supported methods: publickey
    これが一番はまった、、、秘密鍵と公開鍵の権限を変えたり、名前変えたり、パスを変えたり、、、
    結局最終的にはZabbixサーバからzabbixユーザでリモートサーバに対してパスワード認証でログインできるユーザを作成して解決しました
    バージョンとかをあげたら公開鍵認証もできるようになるのだろうか

今回は以上です
パスワード認証ではありますがSSH経由でシェルスクリプトを実行できる方法を紹介しました
SSH経由が嫌だという場合にはカスタムスクリプトという仕組みもあるのでこれを使うといいと思います

P.S 2014/12/10

カスタムスクリプトをちょっと使ってみましたがzabbix_proxyを経由していないのであれば断然これを使ったほうが楽でした。。。
zabbix_agent側でコマンドを発行してくれるのでSSHとかの設定もいらないし、権限回りもAgentをAllowRoot=1で起動しておけば問題なさそうだし。。。
カスタムスクリプトおすすめです

2014年12月5日金曜日

SAStrutsのチュートリアルをやってみた

sastruts

概要

SAStrutsの理解を少しでも深められればと思っていたら公式のチュートリアルがあったのでやってみました
大変なのはコーディングより環境構築かもしれません

環境

  • Windows7 64bit
  • Eclipse Luna 4.4.1
  • Apache Tomcat 7.0.56(設定はデフォルト)
  • JDK 1.8.0_25

設定

環境構築

過去の記事で紹介しているのでそれを参考に構築してみてください
ポイントはプラグインのインストールの部分です
Eclipseのバージョンよってはエラー地獄にハマるかもしれません
一応環境に記載されているバージョンでは問題なくインストールできました
サラーっと流していますがたぶんここが一番大変です。。。

サンプルを動かしてみる

基本はチュートリアルのページを参考に進めていきます

チュートリアルのソースコードのダウンロードとEclipseへのインポート

http://sastruts.seasar.org/download/2011-08-13/sa-struts-tutorial-1.0.4-sp9.zip
をダウンロードします
ダウンロードできたらEclipseに解凍したプロジェクトをインポートします
PackageExplorerから

Import -> Existing Projects into Workspace -> Select root directory -> Projects > Finish

と必要な箇所を入力してインポートします
「Select root directory」はダウンロードして解凍したディレクトリを選択します
インポートが完了したらTomcatを起動します
起動が完了したらプロジェクトをTomcatに認識させます

Properties -> Tomcat -> Tomcatプロジェクトにチェック -> Apply -> OK

認識されるとEclipseのコンソールにデプロイされたログが出ると思います
この状態で http://localhost:8080/sa-struts-tutorial/ にアクセスするとサンプルを確認することができます

インポートが完了してサンプルが動作した状態のPackage Explorerは以下のような感じです
sas_sample_project.png

サンプルの簡単な説明

まず http://localhost:8080/sa-struts-tutorial/ にアクセスするとtutorial.action.IndexAction.javaが実行されます
src/main/resources/convention.diconというファイルがありここにルートパッケージと呼ばれる宣言がされています

<initMethod name="addRootPackageName">
    <arg>"tutorial"</arg>
</initMethod>

tutorialをルートパッケージとしてその配下にあるactionパッケージがアクセスしたURIに合わせて自動的に呼び出されます
例えば/sa-struts-tutorial/addにアクセスするとtutorial.action.AddAction.javaが実行されます

そしてこのActionクラスの中で@Executeアノテーションがついたメソッドが自動で呼ばれます
@Executeがついたメソッドは引数なしの戻り値がStringでなければなりません
この動きがSAStrutsのアクセスしてからレスポンスが返却されるまでの王道的な一連の流れになります

パッケージの命名規則はその他の機能にも紐付いておりdtoやentityパッケージを使うとモデルデータへの自動バインドみないなことをやってくれます
またアノテーションも@ActionFrom@Resourceなどがありこれらを駆使することでコーディング量を大幅に削減することができます

では、一応サンプルは動くようになったのサンプルの話はこれくらいにして実際に自分でサンプルを作ってみたいと思います

簡単な自作アプリを作ってみる

受け取ったデータを表示する簡単なアプリを作ってみます

データ表示するためにDtoという仕組みがあります
DtoはData Transfer Objectの略でサブシステム間でデータを転送するのに使うデザインパターンです(Wikipediaより)
SAStrutsでDtoを使うとレスポンスのデータが簡単に作成できます
(今回の例だとそこまで恩地を受けれている感がありませんが、せっかくなんで使ってみます)

まずDto用のクラスを作成します
Dtoはtutorial.dto配下に作成する必要があります
今回はTestDto.javaというファイルを作成してください
クラスの内容は以下の通りです、メッセージを表示するためのフィールドと値をセットするためのコンストラクタ
それとをメッセージを表示するためのメソッドを用意します

package tutorial.dto;

public class TestDto {

    public String message;

    public TestDto() {
    }

    public TestDto(String message) {
        super();
        this.message = message;
    }

    public String showMessage() {
        return "<h3>" + message + "</h3>";
    }

}

次にリクエストのデータを受け取るためのクラスを準備します
データ受け取るための仕組みはformという仕組みがありこれを利用します
Formはtutorial.form配下に作成する必要があります
FormTest.javaというクラスを作成してください、内容は以下の通りです
リクエストのmessageを受けとるためのフィールドを用意します
あとで説明しますが、このフィールドにリクエストされたデータが勝手にバインドされます

package tutorial.form;

import org.seasar.struts.annotation.Required;

public class TestForm {

    @Required
    public String message;

}

次にこれらのFormとDtoを使うためのActionを作成します
tutorial.action.TestActoin.java を作成してください
内容は以下の通りです

package tutorial.action;

import javax.annotation.Resource;

import org.seasar.struts.annotation.ActionForm;
import org.seasar.struts.annotation.Execute;
import org.seasar.struts.util.ResponseUtil;

import tutorial.dto.TestDto;
import tutorial.form.TestForm;

public class TestAction {

    @ActionForm
    @Resource
    protected TestForm testForm;

    public TestDto testDto;

    @Execute(validator=false)
    public String index() {
        TestDto dto = new TestDto(testForm.message);
        ResponseUtil.write("message is " + dto.showMessage());
        return null;
    }

}

Fromは@ActionFrom@Resourceアノテーションが必要です
レスポンス用のTestDtoのオブジェクトをフィールドとして管理します
そしてアクセスが来た時に処理を開始するindexメソッドを@Executeアノテーション付きで作成します

ここでポイントなのがTestFormのオブジェクトで
Servletのrequestオブジェクトを操作していないのにTestFormのフィールドにリクエストされた値をバインドしてくれます
これがSAStrutsを使うと嬉しい点でリクエストのパラメータ名とFormクラスのフィールド名を紐付けて勝手にオブジェクトを作成してくれます
なのでソースコード中でいきなりtestForm.messageとやっても怒られないのです

実行してみる

Tomcatを再起動してもいいですが、SAStrutsはソースコードを書き換えるとそのままデプロイしてくれます
http://localhost:8080/sa-struts-tutorial/test?message=hello
にアクセスしてみましょう

message is <h3>aaa</h3>

と表示されると思います、HTMLがうまく解釈されていません
TestAction.javaのwriteしている部分を以下に修正してください

ResponseUtil.write("message is " + dto.showMessage(), "text/html");

再度URLにアクセスするとうまくHTMLが解釈されていると思います
?message=hogehogeの部分を変更するとブラウザに表示されるメッセージも変わると思います

だいぶ簡単なアプリでしたが紹介は以上です

最近はPlayとかSpring.ioとかもうちょっとモダンなフレームワークがあり同じようなことができます
SAStruts自体はまだStruts1を使っているようです
Struts自体はまだメンテされていて2.3まで進んでいるようです
触ってみて感じましたが構築が大変なのと仕組みも複雑でブラックボックスな部分が多い印象です(OSSなんでソース読めって感じですが。。)
あとはドキュメントがもう少し充実していると嬉しいかなと思いました
ググればある程度情報は出ましたが昔の記事が多かったかな

Tips

  • src/main/webapp/WEB-INF/classes/log4j.properties のDEBUGをINFOにするとEclipseのコンソールに表示されていたログが表示されなくなります

2014年12月4日木曜日

ZenHub.ioを使ってみた

概要

Zenhub.ioはGitHubに簡単にカンバン機能を追加することができるサービスです
Chromeの拡張機能として動作するためブラウザはChromeのみで動作します
今回はセットアップ方法と簡単な使い方を紹介します

環境

  • Mac OS X 10.8.5
  • Chrome 39.0.2171.71 (64-bit)
  • ZenHub for GitHub 1.0.6

設定

Zenhub for GitHubのChrome拡張をインストール

Chromeを開いて https://www.zenhub.io/ にアクセスします
ここの「GET ZENUB FOR CHROME」をクリックすると拡張をクリックします
access_zenhub.png

するとインストール確認のダイアログが表示されるので追加をクリックします
install_zenhub.png

インストールが完了するとChromeの右上に「ZH」というアイコンが表示されるようになります

また自動的に https://www.zenhub.io/features に遷移します
ここはチュートリアルでZenhub.ioで何ができるかが記載されています
ヘッダーに「Sign In」というリンクがあるのでここをクリックしGitHubのアカウントでZenHub.ioからのアクセスを許可するとZenHubのダッシュボードに遷移することができます
が、このダッシュボードではOrganizerの一覧しか見れないので特に何かができるわけではありません

GitHubにアクセスしてカンバンを確認してみる

Zenhub for GitHubをインストールしたChromeでGitHubにアクセスしてみましょう
自分が作成したリポジトリに遷移してください
すると右のメニュー欄に「Boards」という欄が追加されているのがわかります
access_github.png

クリックすると表示するカンバンの設定画面に遷移します
デフォルトでは3パターンあるようです
今回は一番右のKanbanを選択してみましょう
Kanbanの一番下にある「Select this Board」を選択しましょう
select_mode.png

するとカンバンの画面に遷移します
first_kanban.png
はじめは一番左のBacklogにすべてのIssueがあると思います
各項目はいわゆるパイプラインになっており、そのIssueに進捗があればどんどんIssueを右にずらしていく感じになります
一番右の項目を見ると「Deployed」となっており、これはデプロイ完了ということでIssueが本番環境に適用されたことを表すステータスになると思います
「なると思います」という表現を使っているのには理由があり、結局このパイプラインは自分で削除したり追加したりすることができます、なのでデフォルトで選択したKanbanでは一番右がDeployedになっていますが気に入らない場合はCompleteとかに名称変更してもOKなのです
名称を変更したり、パイプライン自体を削除したい場合には各パイプラインの右上に鉛筆ボタンとバケツボタンがあるのでそこを押せば変更、削除ができます
config_or_delete.png

パイプライン自体のステータスはGitHubのLabelMilestonesとは全く関係なく、Issueを右にずらしたからといってLabelMilestonesが勝手に書き換わることはありません

でいろいろずらしてみた感じが以下の通り
change_status.png

うーんこれだと全然凄みが通じないのですが。。。

結局このパイプライン上で更に Labels or Milestones or Assignee でIssueの絞込ができるのがZenHub.ioの特徴になります
なのでチームでGitHubを使って開発している場合にたくさんのContributorがいて、あるContributorの進捗状況が知りたい場合にAssigneeで絞り込んだり
Labelsがありすぎて特定のLabelsの進捗が知りたい場合にLabelsで絞りこんだりすると、その進捗がひと目でわかる
という感じになります

簡単ですが紹介は以上です
GitHub Enterpriseにも対応しているようですが、そちらは有料みたいです
30日間は無料で使えるようです
https://www.zenhub.io/enterprise

2014年12月3日水曜日

Parse.comの$inQueryというクエリについて調べてみた

概要

前回前々回と別のクエリの説明をしてきて今回は3つ目のクエリで$inQueryというクエリを説明したいと思います
$inQueryPointerで紐付いているデータ取得するためのクエリです

環境

  • Mac OS X 10.8.5
  • Parse.com(2014/12/03 時点)
  • curl

説明

$inQueryPointerという型のカラムに対して実行できます
実際にPointer型のカラムおよびデータを作成してからクエリを発行したいと思います
今回はusersクラスとuserAttributeクラスをPointerで紐付けたいと思います

UIで事前にデータを投入

データはUIから投入可能です

userAttributeクラスを作成

userAttributeクラスは自分で作成するクラスです
ダッシュボードから「+ Add Class」を選択します
するとダイアログが表示されるのでクラス名に「userAttribute」と入力して「Create Class」をクリックします

userAttributeクラスが作成できたらカラムを追加します
「+Col」をクリックするとカラムを追加するダイアログが表示されます
「Select a type」でStringを選択します
カラム名は「skill」と入力し「Create Column」でカラムを作成します
create_class.png
まだデータがない状態で上記のようになればOKです
追加したskillカラムが見つからないという場合は画面をリロードするか画面の右端にカラムが作成されていることがあるのでドラッグ&ドロップでカラムを左に持ってくればOKです

ついでにデータも登録します
「AddRow」をクリックしskillに「Java」と入力してデータを登録します
regist_data.png
これでuserAttribute(参照先)側のデータ登録は完了です
次にusers(参照元)のデータを作成していきます

usersクラスにユーザを追加する

usersにユーザを登録します
「AddRow」からユーザを登録します、usernameとpasswordを入力してユーザを登録します

またPointer型のデータを管理するカラムを追加します
「+Col」をクリックすると追加するダイアログが表示されます
「Select a type」でPointerを選択します
すると参照先のクラスを選択するための「Target class」というプルダウンが表示されるので先ほど作成したuserAttributeクラスを選択します
そしてカラム名を入力します、今回は「refSkill」という名前で作成します
add_column.png
入力した「Create Column」をクリックします

とりあえず以下のような状態になればOKです
regist_user.png

userAttributeへの参照情報をusersに登録する

先ほど作成したユーザにuserAttributeへの参照情報を追加します
UIから参照情報を登録するのは非常に簡単です
まず、userAttributeに登録したデータのobjectIdをメモしておきます
今回であればJavaというskillの「Iy5hovxqVs」がそれにあたります
この情報をusersクラスのrefSkillカラムに登録します

usersクラスを表示します
refSkillカラムのダブルクリックし編集可能状態にして先ほどのobjectIdを貼り付ければ完了です
regist_pointer_info.png
上記のようにobjectIdが表示されたボタンが作成されればOKです

上記のようにボタンにならない場合はrefSkillカラムを追加するときの型がPointerになっているか再度確認してください
String型になっている場合はボタンにはならず、ただobjectIdが表示されるだけとなります

この状態でボタンをクリックするとuserAttributeクラスの参照先のデータに飛ぶことがわかると思います

ようやく$inQueryを発行できる準備が整いました

curlでクエリを作成する

今回実行するクエリは以下の通り
このクエリの流れを説明していきます

curl -X GET \
  -H "X-Parse-Application-Id: 1234567890abcdefghijklmnopqrstuvwxyz" \
  -H "X-Parse-REST-API-Key: 1234567890abcdefghijklmnopqrstuvwxyz" \
  -G \
  --data-urlencode 'where={"refSkill":{"$inQuery":{"where":{"skill":{"$exists":true}},"className":"userAttribute"}}}' \                
  https://api.parse.com/1/users

動作の仕組み

クエリの流れは

  1. userAttributeクラスのskillカラムにデータを持つオブジェクトを検索する
    {"where":{"skill":{"$exists":true}},"className":"userAttribute"}の部分
  2. 上記の検索結果で絞りこまれたデータからobjectIdの一覧を取得する
  3. 取得したobjectIdの一覧とusersクラスのrefSkillカラムのデータを比較する
    where={"refSkill":{"$inQuery":の部分とURIで指定しているクラスの部分
  4. 一致するデータをusersクラスから取得して返却する

という流れになります
実際にクエリを投げた際のレスポンスは以下の通りです

{
    "results": [
        {
            "createdAt": "2014-12-03T05:50:27.239Z",
            "objectId": "YzXJMy6tgH",
            "refSkill": {
                "__type": "Pointer",
                "className": "userAttribute",
                "objectId": "Iy5hovxqVs"
            },
            "updatedAt": "2014-12-03T06:04:27.942Z",
            "username": "testUser"
        }
    ]
}

users側の情報が取得できていることがわかると思います
今回は1人のユーザしかいませんでしたが、refSkillを参照するユーザが複数いればレスポンスにも複数のユーザが含まれます

userAttribute側に複数のskillデータを登録して別のskillを参照するユーザを登録してあげても結果は複数のユーザが返却されます

また今回userAttribute側を検索する際のクエリ({"where":{"skill":{"$exists":true}},"className":"userAttribute"}の部分)は$exists:trueというクエリを使っています
これは指定したカラムにデータが存在するデータを取得するという条件になります
ここは自由に変更可能で例えばJavaというskillを持つユーザだけを取得したいのであれば
{"where":{"skill":"Java"}という風に書き換えればJavaに紐づくユーザだけを取得することができます

このように$inQueryを使うことで条件に合致する参照先のデータを1つクエリで取得することができるようになります
もちろん参照先のデータはPointer型で持つ必要はあります

参考サイト

2014年12月2日火曜日

Parse.comの$relatedToというクエリについて調べてみた

概要

前回$selectというクエリについて説明しました
今回は$relatedToというクエリについて紹介したいと思います
$relatedToは参照先のオブジェクト情報を取得することができるクエリです
これまた動きがわかりづらかったのでメモがてら説明します

環境

  • Mac OS X 10.8.5
  • Parse.com(2014/12/02 時点)
  • curl

説明

ポイントはAddRelationというオペレーションを使ってオブジェクトの紐付けを作ることです
AddRelationで紐付けたデータを$relatedToで取得する流れになります

curlで事前にデータを投入

AddRelationで紐付けるためのデータを投入します
UIからだと結構面倒なのでcurlを使ってデータを投入します
今回はUserとRole内のオブジェクトを紐付けたいと思います

Userの登録

まずはUserにデータを登録します
これはUIからポチポチやっても簡単に登録できます
curlの場合は以下のような感じで実行してください

curl -X POST \
  -H "X-Parse-Application-Id: 1234567890abcdefghijklmnopqrstuvwxyz" \
  -H "X-Parse-REST-API-Key: 1234567890abcdefghijklmnopqrstuvwxyz" \
  -H "Content-Type: application/json" \
  -d '{"username":"hogesuke","password":"hogePassword"}' \
  https://api.parse.com/1/users

レスポンスは以下のような感じです

{"createdAt":"2014-12-02T09:54:03.452Z","objectId":"8bZxTztWyi","sessionToken":"q4sgqSh4cErY7pNapscijj5ir"}

このレスポンスのobjectIdの欄をメモしておいてください
Roleと紐付けるときのクエリ内で使用します

UI上では以下のように登録されています
ここで表示されているobjectIdを使います
insert_user.png

Roleの登録

UserとRoleが紐づくようにデータを投入します
クエリは以下の通り

curl -X POST \
  -H "X-Parse-Application-Id: 1234567890abcdefghijklmnopqrstuvwxyz" \
  -H "X-Parse-REST-API-Key: 1234567890abcdefghijklmnopqrstuvwxyz" \
  -H "Content-Type: application/json" \
  -d '{
        "name": "testRole",
        "ACL": {
          "*": {
            "read": true
          }
        },
        "users": {
          "__op": "AddRelation",
          "objects": [
            {
              "__type": "Pointer",
              "className": "_User",
              "objectId": "8bZxTztWyi"
            }
          ]
        }
      }' \
  https://api.parse.com/1/roles

うーん、長いですね
ポイントはusersの部分でここのusers.objects.objectIdの部分で先ほど登録したユーザのobjectIdを指定します
__typeとか__opとかは決められた予約語みたいなもので
Pointer型のオブジェクトをAddRelationすることで紐付けすることができます

レスポンスは以下の通り

{"createdAt":"2014-12-02T10:00:47.223Z","objectId":"8WzqLyJChx"}

UIでもロールが作成されていることを確認します
insert_role.png
usersのカラムにView Relationsというボタンがあり、これをクリックすると先ほど作成したユーザ情報に遷移すると思います
rolesのカラムにもView Relationsがあります
これは_Roleというクラスを参照しているようで自動的に作成されるRelationのようです

これで$relatedToを実行するための準備が整いました

curlでクエリを作成する

$relatedToを発行して参照先の情報を取得してみます
まずクエリは以下の通り

curl -X GET \
  -H "X-Parse-Application-Id: 1234567890abcdefghijklmnopqrstuvwxyz" \
  -H "X-Parse-REST-API-Key: 1234567890abcdefghijklmnopqrstuvwxyz" \
  -G \
  --data-urlencode 'where={"$relatedTo":{"object":{"__type":"Pointer","className":"_Role","objectId":"6RTvQxdzgP"},"key":"users"}}' \
  https://api.parse.com/1/users

whereが非常に長ったらしいですね
ではこのクエリに関して説明していきます

動作の仕組み

まずアクセスするURIには参照先のクラスを指定します
今回は参照先のユーザの情報がほしいのでURIはhttps://api.parse.com/1/usersになります

そしてwhereの中に入るのは_Role(参照元)を検索する条件を記載します
もうちょっと言うと今回はロールで絞込をした上でその検索結果が持つ参照先の情報を取得するという流れになります
なのでwhere内でロールを絞り込みます

where内の以下の部分に関してはほぼ定形文になります

{“$relatedTo”:{“object”:{“__type”:”Pointer”,”className”:”_Role”,”objectId”:”6RTvQxdzgP”}

変更しなければいけない部分はclassNameobjectIdの部分です
classNameは参照元のクラスを記載します、今回はロールが参照元になるので_Roleを記載します
そしてロール絞り込むための条件はobjectIdになります
ここで指定しているobjectIdは先ほど作成したロールのobjectIdを指定します

そして上記の続きで以下のjsonがあります

,”key”:”users”}}

これは検索元である_Roleのどのカラムに参照先の情報があるのかを指定してします
UIでロールの情報を見るとわかりますが、usersというカラムにView Relationsというボタンがあったのでそのカラム名を指定します

つまり

  1. _RoleをobjectIdで検索して
  2. その検索結果のusersカラムが持つ参照情報を元に
  3. 参照先の情報を取得する流れ

という感じになります

使いそうなケースとしてはユーザの属性情報を別のクラスで管理したいときなどでしょうか
今回は1つのロールに対して1人のユーザしかいませんでしたが、Relationは複数紐付けできるので1つのロールに属する複数のユーザを取得したりすることもできます
今回の場合だとAddRelationするときのobjects配列に複数のユーザを登録すれば複数のユーザを取得することができるようになります

"users": {
  "__op": "AddRelation",
  "objects": [
    {
      "__type": "Pointer",
      "className": "_User",
      "objectId": "8bZxTztWyi"
    },
   {
      "__type": "Pointer",
      "className": "_User",
      "objectId": "93lVCBcNsd"
    }
   ]
}

参考サイト

2014年11月28日金曜日

MacにJavaをインストールする方法

概要

OSXのシステム自信が使用するためのJavaはデフォルトで入っているようなのですが、それがJava6まででJava7以降が必要な場合は自分でインストールします
今回はJava8ですが、方法をまとめたのでメモしておきます

環境

  • Mac OS X 10.8.5
  • JDK 8 update 25

インストール

dmgファイルのダウンロード

まずはMacにインストールするためのdmgファイルをダウンロードします
Oracleの公式サイトにMac用のdmgファイルがあります

ライセンスに同意してMac OS X x64のdmgパッケージをダウンロードします
2014/11/27現在では「jdk-8u25-macosx-x64.dmg」というファイルがダウンロードできました
mac_java_dmg.png

Macにインストールする

ダウンロードした「jdk-8u25-macosx-x64.dmg」を実行します
するとFinderで開くのでその中にある「JDK 8 Update 25.pkg」をクリックして実行します
これがインストーラになります
extract_dmg.png

実行するとインストールがはじまります
start_install_java.png

インストール先は好きなところを選択してください
途中Admin権限のパスワードを聞かれる場合はAdminユーザのパスワードを入力してください
特に問題なくインストールできると思います

確認

MacにはインストールされているJavaを一覧表示できる便利なコマンドがあります

/usr/libexec/java_home -V

実行すると以下のような結果が返ってくると思います

Matching Java Virtual Machines (3):
    1.8.0_25, x86_64:   "Java SE 8"     /Library/Java/JavaVirtualMachines/jdk1.8.0_25.jdk/Contents/Home
    1.6.0_65-b14-462, x86_64:   "Java SE 6"     /System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home
    1.6.0_65-b14-462, i386:     "Java SE 6"     /System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home

/Library/Java/JavaVirtualMachines/jdk1.8.0_25.jdk/Contents/Home
n

1.6.0はデフォルトで入っていたJavaです
今回インストールしたのは1.8.0の方になります
ポイントとかは特にないですが、自分でインストールしたJavaとデフォルトでMacにインストールされているJavaは管理上からかインストールされるディレクトリが異なっているようです

で、javaコマンド自体はどちらになっているのか確認したら

java -version

java version "1.8.0_25"
Java(TM) SE Runtime Environment (build 1.8.0_25-b17)
Java HotSpot(TM) 64-Bit Server VM (build 25.25-b02, mixed mode)

とちゃんと自分でインストールしたほうが優先されていました

あとは必要におうじて$JAVA_HOMEを設定してください
インストールしただけでは$JAVA_HOMEは設定されないようでした

2014年11月27日木曜日

WindowsサーバにRabbitMQをインストールしてみた

概要

Windows + Cygwin環境上でRabbitMQを動作させてみました

環境

  • Windows7 64bit
  • Cygwin 1.7.32-1
  • apt-cyg 0.59
  • erlang 17.3
  • RabbitMQ

インストール

erlangのインストール

erlangのダウンロードサイトから最新のerlangのインストーラをダウンロードしてきます
ダウンロードが完了したらインストーラを起動してインストールします
2014/11/26のWindows7 64bitの最新版は「OTP 17.3 Windows 64-bit Binary File (91.0 MB) 」でした

インストールに関しては特に問題ないと思います
サイズがでかくダウンロードに時間がかかるのとローカルのストレージの残容量にご注意ください

ERLANG_HOMEの設定

デフォルトだと「C:\Program Files\erl6.2」にインストールされるようです
これをERLANG_HOMEとしてWindowsのシステム環境変数に追加します

コントロールパネル -> システムとセキュリティ -> システム -> システムの詳細設定 -> 環境変数

erlang_path_config.png
必ずシステムの環境変数に設定してください
これでerlangの設定はOKです

RabbitMQのインストール

https://www.rabbitmq.com/releases/rabbitmq-server/v3.4.1/rabbitmq-server-windows-3.4.1.zip
をダウンロードします
ダウンロードしてできたzipファイルを解凍します
あとは解凍したファイルを適当なパスに配置します

mkdir -p ~/Documents/work/rabbitmq/
cd ~/Downloads/
unzip rabbitmq-server-windows-3.4.1.zip
mv rabbitmq_server-3.4.1 ~/Documents/work/rabbitmq/

これでインストールは完了です

RabbbitMQの起動

では起動するか確認してみましょう
先ほどインストールしたディレクトリに移動してbatファイルを実行します
同じターミナルで作業している場合は一旦閉じるか別のターミナルで作業をしてください
ERLANG_HOMEをターミナルに反映させるためです

cd ~/Documents/work/rabbitmq/rabbitmq_server-3.4.1
cd sbin
./rabbitmq-server.bat

で以下のように起動すればOKです

username@localhost ~/Documents/work/rabbitmq/rabbitmq_server-3.4.1/sbin
$ ./rabbitmq-server.bat

              RabbitMQ 3.4.1. Copyright (C) 2007-2014 GoPivotal, Inc.
  ##  ##      Licensed under the MPL.  See http://www.rabbitmq.com/
  ##  ##
  ##########  Logs: C:/Users/username/AppData/Roaming/RabbitMQ/log/rabbit@localhost.log
  ######  ##        C:/Users/username/AppData/Roaming/RabbitMQ/log/rabbit@localhost-sasl.log
  ##########
              Starting broker... completed with 0 plugins.

停止する場合は

./rabbitmqctl.bat stop

で停止できます

管理UIを有効にする

一旦stopした後に

./rabbitmq-plugins.bat enable rabbitmq_management

でプラグインを有効化してから、起動してください
その後http://localhost:15672/にアクセスして
guest/guestでログインすることができます(デフォルトのユーザとPWです)

紹介は以上です
意外と簡単にできました
上記のコマンドや作業はすべてCygwin上で実行しています

参考サイト

2014年11月26日水曜日

Cygwin上にRedisをインストール

概要

過去にWindows上にRedisをインストールする方法を紹介しましたが、この方法だと実はCygwin上では使えません
今回はCygwin上で実行できるRedisのインストール方法をご紹介します

環境

  • Windows7 64bit
  • Cygwin 1.7.32-1
  • apt-cyg 0.59
    • make, gcc-core
    • 事前にapt-cygでmakeに必要なパッケージをインストールしておいてください、apt-cygのインストール方法はこちらから
  • Redis 2.6.14

インストール

インストールはRedisのソースコードをmakeビルドしてインストールします

Redisインストール

まずはソースをダウンロードして解凍します

wget https://redis.googlecode.com/files/redis-2.6.14.tar.gz
tar zvxf redis-2.6.14.tar.gz

既存のソースコードをCygwin でビルドできるように修正します

cd redis-2.6.14/src/
vim redis.h

redis.hはすでに存在するファイルでこれに追記します
追記する箇所は「Data types」の上に以下を追記します
(左の番号は行数なのでコピペしないでください)

307 #ifdef __CYGWIN__
308 #ifndef SA_ONSTACK
309 #define SA_ONSTACK 0x08000000
310 #endif
311 #endif
312
313 #if defined(__CYGWIN__)
314 #define strtold(a,b)    ((long double)strtod((a),(b)))
315 #endif
316
317 /*-----------------------------------------------------------------------------
318  * Data types
319  *----------------------------------------------------------------------------*/

追記できたらあとはビルドします

make

P.S 20160822
make 時に「エラー: 不明な型名 ‘u_int’ です」となってエラーになる場合は以下のように実行してみてください
CFLAGS='-D_GNU_SOURCE'

成功すると最後は以下のようになりました
警告でまくりでしたがうまく成功しているようです

...この前にもいろいろビルドログが出ている...

...

redis-check-aof.c: 関数 ‘process’ 内:
redis-check-aof.c:118:17: 警告: 関数 ‘strcasecmp’ の暗黙的な宣言です [-Wimplicit-function-declaration]
                 if (strcasecmp(str, "multi") == 0) {
                 ^
redis-check-aof.c: 関数 ‘main’ 内:
redis-check-aof.c:177:5: 警告: 関数 ‘fileno’ の暗黙的な宣言です [-Wimplicit-function-declaration]
     if (redis_fstat(fileno(fp),&sb) == -1) {
     ^
redis-check-aof.c:198:17: 警告: 関数 ‘strncasecmp’ の暗黙的な宣言です [-Wimplicit-function-declaration]
                 strncasecmp(buf,"y",1) != 0) {
                 ^
    LINK redis-check-aof

Hint: To run 'make test' is a good idea ;)

実行するのはmakeだけでOKです(make testやmake installは不要)

動作確認

バイナリファイルが存在するか確認しましょう
redis-2.6.14/src/配下でls -ltrを実行して以下のファイルがあればOKです

-rwxr-xr-x 1 user None 2056256 11月 26 15:51 redis-server.exe
-rwxr-xr-x 1 user None 2056256 11月 26 15:51 redis-sentinel.exe
-rw-r--r-- 1 user None  139609 11月 26 15:51 redis-cli.o
-rwxr-xr-x 1 user None  424068 11月 26 15:51 redis-cli.exe
-rw-r--r-- 1 user None   52283 11月 26 15:51 redis-benchmark.o
-rwxr-xr-x 1 user None  337399 11月 26 15:51 redis-benchmark.exe
-rw-r--r-- 1 user None   44586 11月 26 15:51 redis-check-dump.o
-rwxr-xr-x 1 user None  114399 11月 26 15:51 redis-check-dump.exe
-rw-r--r-- 1 user None   23556 11月 26 15:51 redis-check-aof.o
-rwxr-xr-x 1 user None   84892 11月 26 15:51 redis-check-aof.exe

あとは

cd redis-2.6.14/src/
./redis-server.exe

でredis-serverを立ち上げて別のcygwinターミナルから

cd redis-2.6.14/src/
./redis-cli.exe

すれば問題なく使えると思います

自分の場合は何も失敗することなくスムーズにmakeビルドできましたが、makeする環境が整っていないとエラーになると思います
その場合はapt-cygがあればapt-cygで必要なライブラリやモジュールをインストールすれば問題ないと思います

参考サイト

2014年11月20日木曜日

NewRelicを使ってZabbixサーバ自信を監視してみた

概要

Zabbixにはzabbix_server自信を監視する機能がない(というか無理)なので
外部の監視システム(今回はNewRelic)を使ってZabbix自体を監視してみました

環境

  • CentOS 6.3 64bit
  • Zabbix 2.0.3
  • NewRelic 2014/11/20時点

準備

まずはNewRelicでアカウント登録

基本は無料で登録使用できます
http://newrelic.com/
にアクセスして「Sign Up for New Relic」からアカウント登録できます
regist_newrelic.png

アカウント登録画面では全部の内容を入力します
内容に不備がある場合は登録しようとしてもエラーになります
内容に不備がある部分は赤字で怒られます
regist_account.png

注意するところは特にないですが
監視するサーバのプラットフォームを選択する部分があるので「PHP」を選択してください
会社名を入力する部分がありますない方は適当でもいいかもしれません(自分は一応所属する会社名を入力しました)

設定

エージェントインストール

NewRelicで監視するサーバにエージェントをインストールします
これがないと監視することができません

まずはNewRelicが提供するレポジトリをインストールします

rpm -Uvh http://yum.newrelic.com/pub/newrelic/el5/x86_64/newrelic-repo-5-3.noarch.rpm

リポジトリがインストールできたらyumコマンドで必要なパッケージをインストールしていきます

yum install newrelic-php5
  • newrelic-php5
  • newrelic-daemon
  • newrelic-php5-common

がインストールされます
インストール時にGPG keyをインポートしますと言われるのでyesにします

Importing GPG key 0x548C16BF:
Userid : New Relic <support@newrelic.com>
Package: newrelic-repo-5-3.noarch (installed)
From   : /etc/pki/rpm-gpg/RPM-GPG-KEY-NewRelic
Is this ok [y/N]: y

エージェントをインストールする準備が整ったのでエージェントをインストールしていきます

newrelic-install install

インタラクティブモードでインストールすることになります
必要な内容を入力しながらインストールしていきます

ライセンスキーの入力

おそらくしょっぱなで入力することになります
以下が表示されたらライセンスキーを入力します

Enter New Relic license key (or leave blank):

ライセンスキーはNewRelicのARM(Application Performance Management)で取得することができます
get_license_key.png

たぶん設定するのはこれだけです
入力後にインストールが完了された旨の英語が出てくればインストール完了です

あとついでにchkconfigをONにしておきます

chkconfig newrelic-daemon on

監視状態の確認

エージェントがインストールできたら一旦zabbix_serverとhttpdを再起動します

service httpd restart
service zabbix-server restart

これで5分後くらいにARMを見ると監視が開始されていることを確認できると思います
watch_php_app.png

成功していると上図のような感じになります
Nameのリンクをクリックすると監視しているサーバの詳細な情報をグラフで確認できます
何の設定もしていないですが、Zabbixで使っているMySQLの監視も勝手にできているっぽいです

うまくいかない場合は/var/log/newrelic/newrelic-daemon.logというログを見てください
何か手がかりがあるかもしれません

ZabbixServerがダウンしたら通知するように設定

さてここからが本題です
ZabbixServerがダウンしたらメールで通知するようにしてみます

サイトの監視

所謂、80番ポート監視してみます
ARMで対象のアプリケーションを開いて左メニューから

Event -> Alerts -> Edit alert policy

を確認してみます、するとすでにアラートが設定されておりこれ利用することでサイトの監視をしてみます default_alerts.png

このアラートを見ると「1 application is missing a ping URL」という警告が出ていて、これが出ているとサイト監視ができていないことになります

左メニューから

SETTINGS -> Availability monitoring -> URL to monitor

にZabbixのURLを記載します
regist_zabbix_host.png

入力してから「Save your changes」とすれば設定完了です
再度Application alert policiesを見ると先ほどの警告が出ていないと思います
それでもアラートが出る場合はここに記載されているIPからの80番ポートアクセスをFWやiptablesに許可してみてください

この状態で試しにサーバを停止してみたらアカウント登録時に設定したメールアドレスにちゃんとサーバ死んだよメールが届きました
起動すれば復旧メールも届きます

一応これでサーバ自体がダウンした場合と80番でLISTENできなくなった場合はNewRelicから監視することができるようになりました

が、たとえばzabbix-serverのプロセス自体が死んだ場合やZabbixが使っているMySQLが死んだ場合は検知できない状態です
本当はそこまで監視したかったんですが、プラグインを作ったりしないといけなさそうだったのと自分のNewRelic力がなさすぎて今回はギブしました
時間があったらやってみようかな

参考サイト