tag:blogger.com,1999:blog-87716731279182636452024-02-22T21:25:01.235+09:00世界の一部unknownhttp://www.blogger.com/profile/15190790785934095924noreply@blogger.comBlogger29125tag:blogger.com,1999:blog-8771673127918263645.post-57616901842437204492016-04-02T07:30:00.000+09:002016-04-08T12:46:15.569+09:00Android Splash(ローディング)画面<h2 class="sub_title">Androidのローディング画面</h2>
簡単にSplash画面を作ってみます。<br/>
<strong>・AndroidManifestに<code class="path">SplashActivity</code>を追加します。</strong><br/>
<pre class="brush:java">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".SplashActivity"
android:configChanges="keyboardHidden|screenSize"
android:label="@string/app_name" android:launchMode="singleTop"
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:theme="@style/AppTheme.NoActionBar">
</activity>
</application>
</pre>
.MainActivityの方にあった<code class="path">intent-filter</code>は.SplashActivityの方に移す必要があります。<br/><br/>
<strong>・SplashActivity</strong><br/>
<pre class="brush:java">
package com.park.commonasynctask;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.widget.TextView;
/**
* Created by park on 2016/03/31.
*/
public class SplashActivity extends Activity {
private Thread splashThread = new Thread(new SplashThread(SplashActivity.this));
private TextView progressTextTv = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash);
progressTextTv = (TextView)findViewById(R.id.progressText);
progressTextTv.setText(R.string.splash_progress_start);
splashThread.start();
}
class SplashThread implements Runnable {
Context context = null;
SplashThread(Context context) {
this.context = context;
}
private void setProgressMessage(int message) {
Message msg = progressHandler.obtainMessage();
msg.obj = getString(message);
progressHandler.sendMessage(msg);
}
@Override
public void run() {
try {
Thread.sleep(2000);
setProgressMessage(R.string.splash_progress_update);
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
Thread.sleep(2000);
setProgressMessage(R.string.splash_progress_end);
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Intent openMainActivity = new Intent(SplashActivity.this, MainActivity.class);
startActivity(openMainActivity);
finish();
}
}
public Handler progressHandler = new Handler(){
public void handleMessage(Message msg){
progressTextTv.setText(msg.obj.toString());
}
};
}
</pre>
<strong>・Layoutにactivity_splash.xmlを追加します。</strong><br/>
<pre class="brush:java">
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#0099cc">
<LinearLayout
android:id="@+id/progressLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="bottom|center"
android:orientation="vertical">
<ProgressBar
style="?android:attr/progressBarStyle"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_marginBottom="10dp" />
<TextView
android:id="@+id/progressText"
style="@style/nomalText"
android:layout_marginBottom="70dp"
android:gravity="center"
android:textColor="#000000"/>
</LinearLayout>
</LinearLayout>
</pre>
<strong>・追加したStyle</strong><br/>
<pre class="brush:java">
<style name="warp_content">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
</style>
<style name="nomalText" parent="warp_content">
<item name="android:textSize">20sp</item>
<item name="android:textStyle">normal</item>
<item name="android:textColor">#000000</item>
</style>
</pre>
<strong>・追加したString</strong><br/>
<pre class="brush:java">
<string name="splash_progress_start">初期化中です。</string>
<string name="splash_progress_update">アップデート中です。</string>
<string name="splash_progress_end">初期化完了</string>
</pre>
<strong>・動作イメージ</strong><br/>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj83hQMdLkzXiKv1lGtJtbGx6oIxROElFHGfjQQNgVvA07JJOogeOVTLaSpoSJB9U44JxAK_RlkBsfqt1fPeTFoE34aTn4D8UBcDU2KPBjgTojdjniFjlo8Qj1YOk249o8yb0UDRqwfOkU/s1600/Screenshot_2016-03-31-14-57-48.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj83hQMdLkzXiKv1lGtJtbGx6oIxROElFHGfjQQNgVvA07JJOogeOVTLaSpoSJB9U44JxAK_RlkBsfqt1fPeTFoE34aTn4D8UBcDU2KPBjgTojdjniFjlo8Qj1YOk249o8yb0UDRqwfOkU/s1600/Screenshot_2016-03-31-14-57-48.png" /></a></div>
<br/><br/>
<hr/>
詳細のソースコードはGithubをご参照ください。<br/>
<a href="https://github.com/kongbab04/CommonAsyncTask" target="_blank">https://github.com/kongbab04/CommonAsyncTask</a>unknownhttp://www.blogger.com/profile/15190790785934095924noreply@blogger.com0tag:blogger.com,1999:blog-8771673127918263645.post-80709567462504636392016-04-02T07:00:00.000+09:002016-04-02T07:00:06.120+09:00Android AsyncTask 共通化<h2 class="sub_title">
Android AsyncTask Common</h2>
AsyncTaskは時間がかかる作業(HTTP通信、データベースクエリ、BT通信等)をBackgroundで処理する時に
よく使われますが、Activity毎に作成したりするのは面倒くさいので、まとめてみました。<br />
<br />
<strong>・BaseTask作成</strong><br />
バックグラウンド処理中、ProgressDialogを表示する
<br />
<pre class="brush:java">
package com.park.commonasynctask.common;
import android.app.ProgressDialog;
import android.content.Context;
import android.os.AsyncTask;
import java.lang.ref.WeakReference;
/**
* Filename : BaseTask.java
* Function :
* Comment : バックグラウンド処理の間にキャンセルできないプログレスダイアログを表示する
*
* History : 2016/03/31, su min park, develop
*
* @version 1.0
* @author su min park
* @since JDK 1.7
*/
public abstract class BaseTask<Object, Void, T> extends AsyncTask<Object, Void, T> {
private final Context mContext;
private final WeakReference<ProgressDialog> mProgressRef;
public BaseTask(Context context, int rMessage) {
mContext = context;
ProgressDialog dialog = new ProgressDialog(context);
dialog.setMessage(mContext.getString(rMessage));
dialog.setCancelable(false);
mProgressRef = new WeakReference<>(dialog);
}
@Override
protected void onPreExecute() {
super.onPreExecute();
ProgressDialog dialog = mProgressRef.get();
if (dialog != null && !dialog.isShowing()) {
dialog.show();
}
}
@Override
protected void onPostExecute(T result) {
super.onPostExecute(result);
ProgressDialog dialog = mProgressRef.get();
if (dialog != null && dialog.isShowing()) {
dialog.dismiss();
}
}
@Override
protected void onCancelled() {
super.onCancelled();
ProgressDialog dialog = mProgressRef.get();
if (dialog != null && dialog.isShowing()) {
dialog.dismiss();
}
}
}
</pre>
<br />
<strong>・実装クラス作成</strong><br />
今回はデータベースへのクエリを想定して作成しました。<br />
QueryExecutorCallbackを利用して、処理結果を戻すようになっています。<br />
<pre class="brush:java">
package com.park.commonasynctask.database;
import android.content.Context;
import com.park.commonasynctask.R;
import com.park.commonasynctask.common.BaseTask;
import com.park.commonasynctask.constants.Globals;
import com.park.commonasynctask.database.connection.DatabaseHelper;
import com.park.commonasynctask.exception.InitializeException;
import com.park.commonasynctask.util.LogUtil;
/**
* Filename : QueryExecutor.java
* Function :
* Comment : 非同期でQueryを実行する
*
* History : 2016/03/31, su min park, develop
*
* @version 1.0
* @author su min park
* @since JDK 1.7
*/
public class QueryExecutor<T> extends BaseTask<Object, Void, T> {
public enum WhichDatabase {
MASTER
}
private Context mContext;
private Query mQuery;
private QueryExecutorCallback mCallback;
private DatabaseHelper mDatabaseHelper;
private WhichDatabase mWhichService;
private Exception e = null;
public QueryExecutor(Context context, WhichDatabase whichService, QueryExecutorCallback callback) {
this(context, whichService, callback, R.string.common_loading);
}
public QueryExecutor(Context context, WhichDatabase whichService, QueryExecutorCallback callback, int message) {
super(context, message);
mContext = context;
mWhichService = whichService;
mCallback = callback;
}
public QueryExecutor setQuery(Query query) {
this.mQuery = query;
return this;
}
@Override
protected void onPreExecute() {
super.onPreExecute();
LogUtil.d("before ");
try {
switch (mWhichService) {
case MASTER:
mDatabaseHelper = new DatabaseHelper(mContext, Globals.getInstance().DB_MASTER_NAME, Globals.getInstance().DB_MASTER_VERSION);
break;
}
} catch (InitializeException e1) {
LogUtil.e(e1);
}
}
@Override
protected T doInBackground(Object... params) {
try {
if (mQuery.getType() == Query.TYPE.SELECT) {
LogUtil.d("run query--- ");
Thread.sleep(3000);
}
else if (mQuery.getType() == Query.TYPE.DELETE) {
// DELETE EXECUTOR CODE
}
else if (mQuery.getType() == Query.TYPE.INSERT) {
// INSERT EXECUTOR CODE
}
}
catch (Exception e) {
this.e = e;
}
return null;
}
@Override
protected void onPostExecute(T result) {
super.onPostExecute(result);
LogUtil.d("after");
if (e == null) {
if (mCallback != null) {
mCallback.returnResult(result);
}
if (mDatabaseHelper != null) {
mDatabaseHelper.close();
mDatabaseHelper = null;
}
}
else {
// Something went wrong.
// Do something with exception on
e.printStackTrace();
}
}
public static class Query {
public enum TYPE {
SELECT,
DELETE,
INSERT
}
String column;
String orderBy;
String tableFrom;
String where;
String[] bindWhere;
boolean whereIn;
TYPE type;
public Query(TYPE type) {
this.type = type;
}
public Query setSelectColumn(String column) {
this.column = column;
return this;
}
public Query setOrderByColumn(String orderBy) {
this.orderBy = orderBy;
return this;
}
public Query setSelectTable(String tableName) {
this.tableFrom = tableName;
return this;
}
public Query setSelectWhere(String where) {
this.where = where;
return this;
}
public Query setBindWhere(String... args) {
bindWhere = args;
return this;
}
public Query setWhereIn(boolean whereIn) {
this.whereIn = whereIn;
return this;
}
public TYPE getType() {
return type;
}
}
public interface QueryExecutorCallback<T> {
void returnResult(T result);
}
}
</pre>
<br />
<strong>・Activityでの呼び出し</strong><br />
<pre class="brush:java">
QueryExecutor.Query query = new QueryExecutor.Query(QueryExecutor.Query.TYPE.SELECT);
new QueryExecutor(MainActivity.this, QueryExecutor.WhichDatabase.MASTER, new QueryExecutor.QueryExecutorCallback<Map<String, String>>() {
@Override
public void returnResult(Map<String, String> result) {
LogUtil.d("result");
}
}).setQuery(query).execute();
</pre>
<br/><br/>
<hr/>
詳細のソースコードはGithubをご参照ください。<br/>
<a href="https://github.com/kongbab04/CommonAsyncTask" target="_blank">https://github.com/kongbab04/CommonAsyncTask</a>
<br/><hr/><br/>
unknownhttp://www.blogger.com/profile/15190790785934095924noreply@blogger.com0tag:blogger.com,1999:blog-8771673127918263645.post-32447892972475672812016-03-31T20:00:00.000+09:002016-03-31T20:00:10.527+09:00AndroidのLogをファイルで出力<h2 class="sub_title">AndroidのLogをファイルで出力</h2>
AndroidのLog出力をスマートに変更し、そのログをFileにも出力するようにしたソースです。<br/>
出力されたログファイルはSplash(アプリ起動する)時にサーバ側にアップロードすることで、Debugが可能になるかと思います。<br/>
<br/>
Libraryは<code class="path">jodaとGuava</code>を利用しています。<br/>
com.park.constants.Globalsには各種設定情報が格納されています。<br/>
<pre class="brush:java">
package com.park.util;
import android.util.Log;
import com.google.common.base.Charsets;
import com.google.common.io.CharSink;
import com.google.common.io.Files;
import com.park.constants.Globals;
import com.park.exception.PlatformException;
import org.joda.time.format.DateTimeFormat;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
/**
* Filename : LogUtil.java
* Function :
* Comment : ログ出力に関するUtil
* History : 2016/03/30, su min park, develop
*
* @version 1.0
* @author su min park
* @since JDK 1.7
*/
public class LogUtil {
// **********************************************************************
// 定数
// **********************************************************************
private static final String TAG = "After";
private static final int LOG_LEVEL = Log.DEBUG;
// **********************************************************************
// メンバ
// **********************************************************************
private static boolean mIsShowLog = true;
private static boolean mIsRunWriteThread = false;
private static Queue<String> logDataQueue = new ConcurrentLinkedQueue<String>();
// **********************************************************************
// パブリックメソッド
// **********************************************************************
public static void setShowLog(boolean isShowLog) {
mIsShowLog = isShowLog;
}
public static void d() {
outputLog(Log.DEBUG, null, null);
}
public static void d(String message) {
outputLog(Log.DEBUG, message, null);
}
public static void d(String message, Throwable throwable) {
outputLog(Log.DEBUG, message, throwable);
}
public static void i(String message) {
outputLog(Log.INFO, message, null);
}
public static void i(String message, Throwable throwable) {
outputLog(Log.INFO, message, throwable);
}
public static void w(String message) {
outputLog(Log.WARN, message, null);
}
public static void w(String message, Throwable throwable) {
outputLog(Log.WARN, message, throwable);
}
public static void e(String message, Throwable throwable) {
outputLog(Log.ERROR, message, throwable);
}
public static void e(Throwable throwable) {
outputLog(Log.ERROR, null, throwable);
}
// **********************************************************************
// プライベートメソッド
// **********************************************************************
private static void outputLog(int type, String message, Throwable throwable) {
if (!mIsShowLog) {
// ログ出力フラグが立っていない場合は何もしません。
return;
}
// ログのメッセージ部分にスタックトレース情報を付加します。
if (message == null) {
message = getStackTraceInfo();
} else {
message = getStackTraceInfo() + message;
}
// ログを出力!
switch (type) {
case Log.DEBUG:
if (throwable == null) {
Log.d(TAG, message);
} else {
Log.d(TAG, message, throwable);
}
break;
case Log.INFO:
if (throwable == null) {
Log.i(TAG, message);
} else {
Log.i(TAG, message, throwable);
}
break;
case Log.WARN:
if (throwable == null) {
Log.w(TAG, message);
} else {
Log.w(TAG, message, throwable);
}
break;
case Log.ERROR:
if (throwable == null) {
Log.e(TAG, message);
} else {
Log.e(TAG, message, throwable);
}
break;
}
//ファイル出力はしない
if (type >= LOG_LEVEL) {
addQueue(message, throwable);
threadQueue();
}
}
/**
* Queueにログを追加する
* 処理に時間がかかる場合はThreadに修正
* @param message
* @param throwable
*/
private static void addQueue(String message, Throwable throwable) {
String eMessage = "";
if (throwable != null) {
try {
eMessage = getStackTraceString(throwable);
} catch (IOException ioe) { }
}
String logWriteTime = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss.SSS").toString();
logDataQueue.offer(logWriteTime + "\t" + message +"\n"+ eMessage);
}
/**
* Queueに溜まったデータをThreadで処理する
*/
private static synchronized void threadQueue() {
try {
if (!mIsRunWriteThread) {
mIsRunWriteThread = true;
//UI制御はない。
(new Thread(new Runnable() {
@Override
public void run() {
StringBuffer logBuffer = new StringBuffer();
while (!logDataQueue.isEmpty()) {
String log = logDataQueue.poll();
if (log != null) {
logBuffer.append(log);
}
}
//残り write
writeLogFile(logBuffer);
mIsRunWriteThread = false;
}
})).start();
}
} catch (Exception e) {
Log.e(TAG, "Log thread error" , e);
}
}
/**
* 操作ログデータをファイルに書き込む
* @param logBuffer
*/
private static synchronized void writeLogFile(final StringBuffer logBuffer) {
if (logBuffer == null || logBuffer.length() == 0) return ;
try {
try {
String sPath = Globals.getInstance().LOG_PATH;
//String sPath = Environment.getExternalStorageDirectory().getPath() + "/appName/log";
String sLogName = "ll_" + DateTimeFormat.forPattern("yyyyMMdd").toString() + ".txt";
File logFile = new File(sPath + File.separator + sLogName);
Files.createParentDirs(logFile);
CharSink sink = Files.asCharSink(logFile, Charsets.UTF_8);
sink.write(logBuffer.toString());
} catch (IOException e) {
Log.e(TAG, "Log Write failed" , e);
} catch (PlatformException e) {
Log.e(TAG, "Globals not init" , e);
}
} finally {
logBuffer.charAt(0);
}
}
/**
* スタックトレースから呼び出し元の基本情報を取得。
* @return
*/
private static String getStackTraceInfo() {
// 現在のスタックトレースを取得。
// 0:VM 1:スレッド 2:getStackTraceInfo() 3:outputLog() 4:logDebug()等 5:呼び出し元
StackTraceElement element = Thread.currentThread().getStackTrace()[5];
String fullName = element.getClassName();
String className = fullName.substring(fullName.lastIndexOf(".") + 1);
String methodName = element.getMethodName();
int lineNumber = element.getLineNumber();
return "<<" + className + "#" + methodName + ":" + lineNumber + ">> ";
}
/**
* Throwableのスタックトレース情報を返す。
* @param e
* @return
* @throws IOException
*/
private static String getStackTraceString(Throwable e) throws IOException {
// エラーのスタックトレースを表示
StringWriter sw = new StringWriter();
PrintWriter pw = null;
try {
pw = new PrintWriter(sw);
e.printStackTrace(pw);
pw.flush();
} finally {
if (pw != null) {
pw.close();
}
}
return sw.toString();
}
}
</pre>
<h2 class="sub_title">参考URL</h2>
<a href="http://blog.fenrir-inc.com/jp/2013/07/android-output-log-smart.html" target="_blank">http://blog.fenrir-inc.com/jp/2013/07/android-output-log-smart.html</a><br/>unknownhttp://www.blogger.com/profile/15190790785934095924noreply@blogger.com1tag:blogger.com,1999:blog-8771673127918263645.post-42864097648541227002015-05-14T22:00:00.000+09:002015-05-14T22:00:08.261+09:00[javascript] 環境依存文字の文字化け対応<h2 class="sub_title">環境依存文字の文字化け対応</h2>
環境依存文字(①、②などの特殊文字)が文字化けしてしまった場合、
ページをUTF-8に変える等、色々な方法があると思いますが、
今回は、環境依存文字テーブルを利用して、Javascript側でHEX(HTML)に置換し
サーバ側に送る方法について紹介したいと思います。<br/><br/>
<br/>
<h2 class="sub_title">JavaScript</h2>
・ソース説明<br/>
画面上の全input:text, textareaを取得し、該当の入力欄の文字列の中に<code class="path">環境依存文字(特殊文字)テーブル</code>の文字が含まれている場合、HEXに置換しHTMLタグとしてサーバに送信する<br/><br/>
以下のJavaScriptコードをreplace-code.jsなどの名前に保存してください。<br/><br/>
<pre class="brush:java">
/**
* 置換する環境依存文字テーブル
* http://www.asahi-net.or.jp/~ax2s-kmtn/ref/cref_num.html
* 参照
*/
var replaceUnicode = {
"2460":"1", "2461":"1","2462":"1","2463":"1","2464":"1","2465":"1",
"2466":"1", "2467":"1","2468":"1","2469":"1","246A":"1","246B":"1",
"246C":"1", "246D":"1","246E":"1","246F":"1","2470":"1","2471":"1",
"2472":"1", "2473":"1","2160":"1","2161":"1","2162":"1","2163":"1",
"2164":"1", "2165":"1","2166":"1","2167":"1","2168":"1","2169":"1",
"3349":"1", "3314":"1","3322":"1","334D":"1","3318":"1","3327":"1",
"3303":"1", "3336":"1","3351":"1","3357":"1","330D":"1","3326":"1",
"3323":"1", "332B":"1","334A":"1","333B":"1","339C":"1","339D":"1",
"339E":"1", "338E":"1","338F":"1","33C4":"1","33A1":"1","337B":"1",
"301D":"1", "301F":"1","2116":"1","33CD":"1","2121":"1","32A4":"1",
"32A5":"1", "32A6":"1","32A7":"1","32A8":"1","3231":"1","3232":"1",
"3239":"1", "337E":"1","337D":"1","337C":"1","2252":"1","2261":"1",
"222B":"1", "222E":"1","2211":"1","221A":"1","22A5":"1","2220":"1",
"221F":"1", "22BF":"1","2235":"1","2229":"1","222A":"1",
"7E8A":"1", "891C":"1","9348":"1","9288":"1","84DC":"1","4FC9":"1",
"70BB":"1", "6631":"1","68C8":"1","92F9":"1","66FB":"1","5F45":"1",
"4E28":"1", "4EE1":"1","4EFC":"1","4F00":"1","4F03":"1","4F39":"1",
"4F56":"1", "4F92":"1","4F8A":"1","4F9A":"1","4F94":"1","4FCD":"1",
"5040":"1", "5022":"1","4FFF":"1","501E":"1","5046":"1","5070":"1",
"5042":"1", "5094":"1","50F4":"1","50D8":"1","514A":"1","5164":"1",
"519D":"1", "51BE":"1","51EC":"1","5215":"1","529C":"1","52A6":"1",
"52C0":"1", "52DB":"1","5300":"1","5307":"1","5324":"1","5372":"1",
"5393":"1", "53B2":"1","53DD":"1","FA0E":"1","549C":"1","548A":"1",
"54A9":"1", "54FF":"1","5586":"1","5759":"1","5765":"1","57AC":"1",
"57C8":"1", "57C7":"1","FA0F":"1","FA10":"1","589E":"1","58B2":"1",
"590B":"1", "5953":"1","595B":"1","595D":"1","5963":"1","59A4":"1",
"59BA":"1", "5B56":"1","5BC0":"1","752F":"1","5BD8":"1","5BEC":"1",
"5C1E":"1", "5CA6":"1","5CBA":"1","5CF5":"1","5D27":"1","5D53":"1",
"FA11":"1", "5D42":"1","5D6D":"1","5DB8":"1","5DB9":"1","5DD0":"1",
"5F21":"1", "5F34":"1","5F67":"1","5FB7":"1",
"5FDE":"1", "605D":"1","6085":"1","608A":"1","60DE":"1","60D5":"1",
"6120":"1", "60F2":"1","6111":"1","6137":"1","6130":"1","6198":"1",
"6213":"1", "62A6":"1","63F5":"1","6460":"1","649D":"1","64CE":"1",
"654E":"1", "6600":"1","6615":"1","663B":"1","6609":"1","662E":"1",
"661E":"1", "6624":"1","6665":"1","6657":"1","6659":"1","FA12":"1",
"6673":"1", "6699":"1","66A0":"1","66B2":"1","66BF":"1","66FA":"1",
"670E":"1", "F929":"1","6766":"1","67BB":"1","6852":"1","67C0":"1",
"6801":"1", "6844":"1","68CF":"1","FA13":"1","6968":"1","FA14":"1",
"6998":"1", "69E2":"1","6A30":"1","6A6B":"1","6A46":"1","6A73":"1",
"6A7E":"1", "6AE2":"1","6AE4":"1","6BD6":"1","6C3F":"1","6C5C":"1",
"6C86":"1", "6C6F":"1","6CDA":"1","6D04":"1","6D87":"1","6D6F":"1",
"6D96":"1", "6DAC":"1","6DCF":"1","6DF8":"1","6DF2":"1","6DFC":"1",
"6E39":"1", "6E5C":"1","6E27":"1","6E3C":"1","6EBF":"1","6F88":"1",
"6FB5":"1", "6FF5":"1","7005":"1","7007":"1","7028":"1","7085":"1",
"70AB":"1", "710F":"1","7104":"1","715C":"1","7146":"1","7147":"1",
"FA15":"1", "71C1":"1","71FE":"1","72B1":"1",
"72BE":"1", "7324":"1","FA16":"1","7377":"1","73BD":"1","73C9":"1",
"73D6":"1", "73E3":"1","73D2":"1","7407":"1","73F5":"1","7426":"1",
"742A":"1", "7429":"1","742E":"1","7462":"1","7489":"1","749F":"1",
"7501":"1", "756F":"1","7682":"1","769C":"1","769E":"1","769B":"1",
"76A6":"1", "FA17":"1","7746":"1","52AF":"1","7821":"1","784E":"1",
"7864":"1", "787A":"1","7930":"1","FA18":"1","FA19":"1","FA1A":"1",
"7994":"1", "FA1B":"1","799B":"1","7AD1":"1","7AE7":"1","FA1C":"1",
"7AEB":"1", "7B9E":"1","FA1D":"1","7D48":"1","7D5C":"1","7DB7":"1",
"7DA0":"1", "7DD6":"1","7E52":"1","7F47":"1","7FA1":"1","FA1E":"1",
"8301":"1", "8362":"1","837F":"1","83C7":"1","83F6":"1","8448":"1",
"84B4":"1", "8553":"1","8559":"1","856B":"1","FA1F":"1","85B0":"1",
"FA20":"1", "FA21":"1","8807":"1","88F5":"1","8A12":"1","8A37":"1",
"8A79":"1", "8AA7":"1","8ABE":"1","8ADF":"1","FA22":"1","8AF6":"1",
"8B53":"1", "8B7F":"1","8CF0":"1","8CF4":"1","8D12":"1","8D76":"1",
"FA23":"1", "8ECF":"1","FA24":"1","FA25":"1","9067":"1","90DE":"1",
"FA26":"1", "9115":"1","9127":"1","91DA":"1",
"91D7":"1", "91DE":"1","91ED":"1","91EE":"1","91E4":"1","91E5":"1",
"9206":"1", "9210":"1","920A":"1","923A":"1","9240":"1","923C":"1",
"924E":"1", "9259":"1","9251":"1","9239":"1","9267":"1","92A7":"1",
"9277":"1", "9278":"1","92E7":"1","92D7":"1","92D9":"1","92D0":"1",
"FA27":"1", "92D5":"1","92E0":"1","92D3":"1","9325":"1","9321":"1",
"92FB":"1", "FA28":"1","931E":"1","92FF":"1","931D":"1","9302":"1",
"9370":"1", "9357":"1","93A4":"1","93C6":"1","93DE":"1","93F8":"1",
"9431":"1", "9445":"1","9448":"1","9592":"1","F9DC":"1","FA29":"1",
"969D":"1", "96AF":"1","9733":"1","973B":"1","9743":"1","974D":"1",
"974F":"1", "9751":"1","9755":"1","9857":"1","9865":"1","FA2A":"1",
"FA2B":"1", "9927":"1","FA2C":"1","999E":"1","9A4E":"1","9AD9":"1",
"9ADC":"1", "9B75":"1","9B72":"1","9B8F":"1","9BB1":"1","9BBB":"1",
"9C00":"1", "9D70":"1","9D6B":"1","FA2D":"1","9E19":"1","9ED1":"1",
"2170":"1", "2171":"1","2172":"1","2173":"1","2174":"1","2175":"1",
"2176":"1", "2177":"1","2178":"1","2179":"1","FFE2":"1","FFE4":"1",
"FF07":"1", "FF02":"1",
"2170":"1", "2171":"1","2172":"1","2173":"1","2174":"1","2175":"1",
"2176":"1", "2177":"1","2178":"1","2179":"1","2160":"1","2161":"1",
"2162":"1", "2163":"1","2164":"1","2165":"1","2166":"1","2167":"1",
"2168":"1", "2169":"1","FFE2":"1","FFE4":"1","FF07":"1","FF02":"1",
"3231":"1", "2116":"1","2121":"1","2235":"1","7E8A":"1","891C":"1",
"9348":"1", "9288":"1","84DC":"1","4FC9":"1","70BB":"1","6631":"1",
"68C8":"1", "92F9":"1","66FB":"1","5F45":"1","4E28":"1","4EE1":"1",
"4EFC":"1", "4F00":"1","4F03":"1","4F39":"1","4F56":"1","4F92":"1",
"4F8A":"1", "4F9A":"1","4F94":"1","4FCD":"1","5040":"1","5022":"1",
"4FFF":"1", "501E":"1","5046":"1","5070":"1","5042":"1","5094":"1",
"50F4":"1", "50D8":"1","514A":"1","5164":"1","519D":"1","51BE":"1",
"51EC":"1", "5215":"1","529C":"1","52A6":"1","52C0":"1","52DB":"1",
"5300":"1", "5307":"1","5324":"1","5372":"1","5393":"1","53B2":"1",
"53DD":"1", "FA0E":"1","549C":"1","548A":"1","54A9":"1","54FF":"1",
"5586":"1", "5759":"1","5765":"1","57AC":"1","57C8":"1","57C7":"1",
"FA0F":"1", "FA10":"1","589E":"1","58B2":"1",
"590B":"1", "5953":"1","595B":"1","595D":"1","5963":"1","59A4":"1",
"59BA":"1", "5B56":"1","5BC0":"1","752F":"1","5BD8":"1","5BEC":"1",
"5C1E":"1", "5CA6":"1","5CBA":"1","5CF5":"1","5D27":"1","5D53":"1",
"FA11":"1", "5D42":"1","5D6D":"1","5DB8":"1","5DB9":"1","5DD0":"1",
"5F21":"1", "5F34":"1","5F67":"1","5FB7":"1","5FDE":"1","605D":"1",
"6085":"1", "608A":"1","60DE":"1","60D5":"1","6120":"1","60F2":"1",
"6111":"1", "6137":"1","6130":"1","6198":"1","6213":"1","62A6":"1",
"63F5":"1", "6460":"1","649D":"1","64CE":"1","654E":"1","6615":"1",
"663B":"1", "6609":"1","662E":"1","661E":"1","6624":"1","6665":"1",
"6657":"1", "6659":"1","FA12":"1","6673":"1","6699":"1","66A0":"1",
"66B2":"1", "66BF":"1","66FA":"1","670E":"1","F929":"1","6766":"1",
"67BB":"1", "6852":"1","67C0":"1","6801":"1","6844":"1","68CF":"1",
"FA13":"1", "6968":"1","FA14":"1","6998":"1","69E2":"1","6A30":"1",
"6A6B":"1", "6A46":"1","6A73":"1","6A7E":"1","6AE2":"1","6AE4":"1",
"6BD6":"1", "6C3F":"1","6C5C":"1","6C86":"1","6C6F":"1","6CDA":"1",
"6D04":"1", "6D87":"1","6D6F":"1",
"6D96":"1", "6DAC":"1","6DCF":"1","6DF8":"1","6DF2":"1","6DFC":"1",
"6E39":"1", "6E5C":"1","6E27":"1","6E3C":"1","6EBF":"1","6F88":"1",
"6FB5":"1", "6FF5":"1","7005":"1","7007":"1","7028":"1","7085":"1",
"70AB":"1", "710F":"1","7104":"1","715C":"1","7146":"1","7147":"1",
"FA15":"1", "71C1":"1","71FE":"1","72B1":"1","72BE":"1","7324":"1",
"FA16":"1", "7377":"1","73BD":"1","73C9":"1","73D6":"1","73E3":"1",
"73D2":"1", "7407":"1","73F5":"1","7426":"1","742A":"1","7429":"1",
"742E":"1", "7462":"1","7489":"1","749F":"1","7501":"1","756F":"1",
"7682":"1", "769C":"1","769E":"1","769B":"1","76A6":"1","FA17":"1",
"7746":"1", "52AF":"1","7821":"1","784E":"1","7864":"1","787A":"1",
"7930":"1", "FA18":"1","FA19":"1","FA1A":"1","7994":"1","FA1B":"1",
"799B":"1", "7AD1":"1","7AE7":"1","FA1C":"1","7AEB":"1","7B9E":"1",
"FA1D":"1", "7D48":"1","7D5C":"1","7DB7":"1","7DA0":"1","7DD6":"1",
"7E52":"1", "7F47":"1","7FA1":"1","FA1E":"1","8301":"1","8362":"1",
"837F":"1", "83C7":"1","83F6":"1","8448":"1","84B4":"1","8553":"1",
"8559":"1", "856B":"1","FA1F":"1","85B0":"1",
"FA20":"1", "FA21":"1","8807":"1","88F5":"1","8A12":"1","8A37":"1",
"8A79":"1", "8AA7":"1","8ABE":"1","8ADF":"1","FA22":"1","8AF6":"1",
"8B53":"1", "8B7F":"1","8CF0":"1","8CF4":"1","8D12":"1","8D76":"1",
"FA23":"1", "8ECF":"1","FA24":"1","FA25":"1","9067":"1","90DE":"1",
"FA26":"1", "9115":"1","9127":"1","91DA":"1","91D7":"1","91DE":"1",
"91ED":"1", "91EE":"1","91E4":"1","91E5":"1","9206":"1","9210":"1",
"920A":"1", "923A":"1","9240":"1","923C":"1","924E":"1","9259":"1",
"9251":"1", "9239":"1","9267":"1","92A7":"1","9277":"1","9278":"1",
"92E7":"1", "92D7":"1","92D9":"1","92D0":"1","FA27":"1","92D5":"1",
"92E0":"1", "92D3":"1","9325":"1","9321":"1","92FB":"1","FA28":"1",
"931E":"1", "92FF":"1","931D":"1","9302":"1","9370":"1","9357":"1",
"93A4":"1", "93C6":"1","93DE":"1","93F8":"1","9431":"1","9445":"1",
"9448":"1", "9592":"1","F9DC":"1","FA29":"1","969D":"1","96AF":"1",
"9733":"1", "973B":"1","9743":"1","974D":"1","974F":"1","9751":"1",
"9755":"1", "9857":"1","9865":"1","FA2A":"1","FA2B":"1","9927":"1",
"FA2C":"1", "999E":"1","9A4E":"1","9AD9":"1",
"9ADC":"1", "9B75":"1","9B72":"1","9B8F":"1","9BB1":"1","9BBB":"1",
"9C00":"1", "9D70":"1","9D6B":"1","FA2D":"1","9E19":"1","9ED1":"1"};
/**
* 画面上の入力欄の環境依存文字があるか
* 確認し、置換作業を行う
*/
function startReplaceSpecialCharacter() {
//画面上のinput:text, textarea
//リストを取得する
var textInputs;
if (document.querySelectorAll) {
textInputs = document.querySelectorAll('input[type=text],textarea');
} else {
textInputs = [];
var unfiltered = document.getElementsByTagName("input"),
i = unfiltered.length,
input;
while(i--) {
input = unfiltered[i];
if (!input.type || input.type === 'text') {
textInputs.push(input);
}
}
unfiltered = document.getElementsByTagName("textarea"),
i = unfiltered.length,
input;
while(i--) {
input = unfiltered[i];
textInputs.push(input);
}
}
//環境依存文字がある場合は
//Hexに変換
for (var inx = 0; inx < textInputs.length; inx ++) {
var e = textInputs[inx];
var text = e.value;
var rtnText = "";
if (text) {
for (var i = 0; i < text.length; i ++) {
var isCode = replaceUnicode[text.charCodeAt(i).toString(16)];
if (isCode == 1) {
rtnText += "&#x" + text.charCodeAt(i).toString(16)+ ";";
} else {
rtnText += text.charAt(i);
}
}
if (rtnText) {
e.value = rtnText;
}
}
}
}
</pre>
<br/>
<h2 class="sub_title">実際の使い方</h2>
・JavaScript追加<br/>
<pre class="brush:java">
<script type="text/javascript" src="../script/replace-code.js"></script>
</pre>
<br/><br/>
・メッソドの呼び出し<br/>
※submitする時に自動で変わるようにするためには、startReplaceSpecialCharacter()をsubmitされる直前に呼び出してください。<br/>
<pre class="brush:java">
<script type="text/javascript">
function doSubmit(form) {
startReplaceSpecialCharacter();
form.submit();
}
</script>
</pre>
unknownhttp://www.blogger.com/profile/15190790785934095924noreply@blogger.com0tag:blogger.com,1999:blog-8771673127918263645.post-84852952913372040022015-03-03T22:00:00.000+09:002016-05-12T12:01:11.555+09:00JDBC Connection Pool [HikariCP] 設定<h2 class="sub_title">HikariCP</h2>
HikariCPはBoneCPより速い速度を誇るDB Connection Poolです。(HikariCP公式サイト参照)<br/>
BoneCPの場合は、Hibernate 4.xバージョンからは支援が曖昧になった気がしますが、
HikariCPはHibernateとの<a href="http://mvnrepository.com/artifact/org.hibernate/hibernate-hikaricp/4.3.6.Final" target="_blank">統合jar</a>が出るなど、HikariCPを押している気がします。<br/>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNcJ_tQrwQ7RiqDo3-9odF01cL5Cr_chHZNksbR3FpzreSOAKWuPhlhM9UOhjgTRk9Hr-x5siYogeMnJMFzZz1hOgeFrjMHsbWueEWA5JZ3RWydTIOjcqjFpyw-SyDMMpPXrX2LZh5Yco/s1600/Benchmarks.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNcJ_tQrwQ7RiqDo3-9odF01cL5Cr_chHZNksbR3FpzreSOAKWuPhlhM9UOhjgTRk9Hr-x5siYogeMnJMFzZz1hOgeFrjMHsbWueEWA5JZ3RWydTIOjcqjFpyw-SyDMMpPXrX2LZh5Yco/s320/Benchmarks.png" /></a>
<br/><br/>
<h2 class="sub_title">HikariCP設定</h2>
・Maven設定
<pre class="brush:bash">
Java 8 maven artifact:
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>2.2.5</version>
<scope>compile</scope>
</dependency>
Java 6 and Java 7 maven artifact:
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP-java6</artifactId>
<version>2.2.5</version>
<scope>compile</scope>
</dependency>
</pre>
<br/>
・Spring + HikariCP<br/>
@Configurationを利用したJava Config設定<br/>
<pre class="brush:bash">
@Bean(destroyMethod = "shutdown")
public DataSource dataSource() {
HikariConfig config = new HikariConfig();
config.setDataSourceClassName("com.mysql.jdbc.jdbc2.optional.MysqlDataSource");
config.addDataSourceProperty("serverName", "localhost");
config.addDataSourceProperty("port", "3306");
config.addDataSourceProperty("databaseName", "test");
config.addDataSourceProperty("user", "root");
config.addDataSourceProperty("password", "test");
config.addDataSourceProperty("zeroDateTimeBehavior", "convertToNull");
config.addDataSourceProperty("useUnicode", "true");
config.addDataSourceProperty("characterEncoding", "utf8");
config.addDataSourceProperty("autoReconnect", "true");
config.addDataSourceProperty("cachePrepStmts", "true");
config.addDataSourceProperty("prepStmtCacheSize", "250");
config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048");
config.addDataSourceProperty("useServerPrepStmts", "true");
config.setMinimumIdle(20);
config.setMaximumPoolSize(20);
config.setJdbc4ConnectionTest(true);
config.setConnectionInitSql("SELECT 1");
HikariDataSource dataSource = new HikariDataSource(config);
return dataSource;
}
</pre>
・hibernate.cfg.xmlファイル設定
<pre class="brush:bash">
<property name="connection.provider_class">com.zaxxer.hikari.hibernate.HikariConnectionProvider</property>
<property name="hibernate.hikari.dataSourceClassName">com.mysql.jdbc.jdbc2.optional.MysqlDataSource</property>
<property name="hibernate.hikari.dataSource.url">jdbc:mysql://localhost/test</property>
<property name="hibernate.hikari.dataSource.user">root</property>
<property name="hibernate.hikari.dataSource.password">test</property>
<property name="hibernate.hikari.dataSource.cachePrepStmts">true</property>
<property name="hibernate.hikari.dataSource.prepStmtCacheSize">250</property>
<property name="hibernate.hikari.dataSource.prepStmtCacheSqlLimit">2048</property>
<property name="hibernate.hikari.dataSource.useServerPrepStmts">true</property>
</pre>
<br/>
以下はHikariCPのpropertyの説明になります。<br/><br/>
<h4>autoCommit (default : true)</h4>
connectionが終了されたり、poolが返却される時、connectionに属しているtransactionをcommitするかどうかを決めます。<br/>
<br/>
<h4>readOnly (default : false)</h4>
database connectionをreadOnly modeでopenします。<br/>
この設定はdatabaseが支援してくれないとreadOnlyではない状態でopenされるため、支援databaseリストを確認する必要があります。<br/>
<br/>
<h4>transactionIsolation (default : none)</h4>
java.sql.Connectionに指定されたTransaction Isolationを指定します。<br/>
Transaction Isoluationは以下になります。<br/><br/>
<strong>・Connection.TRANSACTION_NONE</strong> : transactionを支援しません。<br/>
<strong>・Connection.TRANSACTION_READ_UNCOMMITTED</strong> : 他のtransactionからデータを読み込んで来る時、更新された(まだcommitされてなくても)値(dirty value)を読み込みます。<br/>
<strong>・Connection.TRANSACTION_READ_COMMITTED</strong> : 他のtransactionからデータを読み込んで来る時、変更されてない(Commitする前)値を読み込みます。<br/>
<strong>・Connection.TRANSACTION_REPEATABLE_READ</strong> : 同じtransactionの中で、同じ値を読み込む時に、変更される前(他のtransactionで、commitされたとしても)の値を読み込みます。TRANSACTION_READ_UNCOMMITTEDと一緒に使用できません。<br/>
<strong>・Connection.TRANSACTION_SERIALIZABLE</strong> : Dirty Read、Non-repeatable Read、Phantom Readが制御されます。<br/>
Default値はそれぞれのDriver vendorのJDBCDriverで支援しているTransaction Isoluationに従います。(noneで設定した時)
<br/>
transactionに関しては<a href="http://www.atmarkit.co.jp/ait/articles/0804/04/news146.html" target="_blank">こちら</a>を参照してください。<br/>
<br/>
<h4>category (default : none)</h4>
connectionで接続されるcategoryを決めます。<br/>
値が設定されてない場合、JDBC Driverで設定された基本categoryが指定されます。<br/>
<br/>
<h4>connectionTimeout(default: 30000 - 30 seconds)</h4>
connectionが接続される時のtimeout out時間を設定します。<br/>
この時間以内にconnectionが接続されなかった場合、SQLExceptionが発生します。<br/>
<br/>
<h4>idleTimeout(default : 600000 - 10 minutes)</h4>
connection Poolによって確保されたconnectionのmaximum idle timeを決めます。<br/>
connection Poolによって確保されたconnectionが使われずに、Poolでこの時間の間、待機している場合、connectionをDBに返却します。<br/>
値を0に設定した場合、確保されたconnectionを絶対返却しません。<br/>
<br/>
<h4>maxLifetime(default : 1800000 - 30 minutes)</h4>
connection Poolによって確保されたconnectionの最大Life Timeを決めます。<br/>
connectionを取得した後、この時間以上になった場合、最近使われたconnectionでも、connectionをcloseします。<br/>
使用中のconnectionはcloseしません。(connectionの使用が終わったらすぐcloseされます。) HikariCPではこの値を30~60 minutesに設定することをお勧めします。<br/>
この値を0にした場合、lifetimeは無制限になります。<br/>
<br/>
<h4>leakDetectionThreshold (default : 0)</h4>
connectionPoolから返却されたconnectionが正しく返却されたかどうかをチェックするthread数を指定します。<br/>
この値を0に指定した場合、leak detectionはdisableされます。<br/>
<br/>
<h4>jdbc4ConnectionTest (default : true)</h4>
connectionされた後、Connection.isValid() methodを呼び出しconnectionが正常かどうかを確認します。<br/>
このpropertyは次のconnectionTestQueryに密接な影響をうけます。<br/>
<br/>
<h4>connectionTestQuery (default : none)</h4>
Connection.isValid() methodが使えない‘legacy’ databaseの為にTEST用の簡単なqueryの指定ができます。<br/>(ex: VALUES 1)<br/>
jdbc4ConnectionTestが使える場合は、jdbc4ConnectionTestを使った方がいいです。<br/>
<br/>
<h4>connectionInitSql (default : none)</h4>
新しいconnectionが生成され、Poolに追加される前に実行されるSQL queryを指定します。<br/>
<br/>
<h4>dataSourceClassName (default : none)</h4>
JDBC driverで支援するdataSourceClassNameを指定します。この値はdriverClassNameが指定された場合は、指定する必要がありません。<br/>
<br/>
<h4>dataSource (default : none)</h4>
使用者が作ったdataSourceをPoolによってwrappedしたい場合は、この値を指定します。<br/>
HikariCPはこの文字列を利用してreflectionを通じてdataSourceを生成します。<br/>
この値が設定された場合、dataSourceClassName, driverClassNameに設定された値は無視されます。<br/>
<br/>
<h4>driverClassName</h4>
HikariCPで使用するDriverClassを指定します。<br/>
この値が指定された場合、jdbcUrlを必ず指定しなければなりません。<br/>
<br/>
<h4>jdbcUrl</h4>
jdbcUrlを指定します。driverClassNameが指定された場合、jdbcUrlを指定する必要があります。<br/>
<br/>
<h4>minimumIdle (default : maximumPoolSize)</h4>
connection Poolで維持する最小限のconnection数を指定します。<br/>
HikariCPでは最高のperformanceの為に、maximumPoolSizeとminimumIdleの値は同じにしてconnection Poolの大きさをfixすることをお勧めしています。<br/>
<br/>
<h4>maximumPoolSize</h4>
connection Poolで使用する最大のconnection数を指定します。<br/>
この部分は運営環境と開発環境での多くのテストが必要です。<br/>
<br/>
<h4>username</h4>
Connectionを取得するための認証ユーザ名を指定します。<br/>
<br/>
<h4>password</h4>
usernameのパスワードを指定します。<br/>
<br/>
<h4>poolName (default : auto-generated)</h4>
loggingとJMX managementで出力されるpoolの名前を指定します。<br/>
<br/>
<h4>registerMbeans (default : false)</h4>
JMX management Beansに登録されるかどうかを決めます。<br/>
<br/>
<br/><br/>
<h2 class="sub_title">参考URL</h2>
<a href="http://stackoverflow.com/questions/20955875/is-tomcat-7-jdbc-connection-pool-good-enough-for-production-and-how-is-it-com" target="_blank">http://stackoverflow.com/questions/20955875/is-tomcat-7-jdbc-connection-pool-good-enough-for-production-and-how-is-it-com</a><br/>
<a href="https://github.com/brettwooldridge/HikariCP" target="_blank">https://github.com/brettwooldridge/HikariCP</a><br/>
<br/>unknownhttp://www.blogger.com/profile/15190790785934095924noreply@blogger.com1tag:blogger.com,1999:blog-8771673127918263645.post-51146537404884616652015-01-16T21:00:00.000+09:002015-01-19T09:38:51.094+09:00[SB Admin 2] BootstrapのAdmin ThemeBootstrapのAdmin ThemeであるSB Admin 2を少し修正してみました。<br/><br/>
修正した部分は以下のようになります。<br/><br/>
<h2 class="sub_title">1. TOPメニュー固定 Fixed Top Navbar</h2>
・TOPのキャプチャーです。<br/>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgqYwHvgj7gQae0ipBmvfpECKVirbvYbHB7hd8y5iq3WP-2ZWT2idJ9EvyZwJnq64UmTaTaf9zvbClGPbPojGkcnyNZDoCPvGOCRL6FcbrpKy5nExDJHbY1OUHroZ8cSQ_odtc4KWwJf6E/s1600/fixed-top-navbar1.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgqYwHvgj7gQae0ipBmvfpECKVirbvYbHB7hd8y5iq3WP-2ZWT2idJ9EvyZwJnq64UmTaTaf9zvbClGPbPojGkcnyNZDoCPvGOCRL6FcbrpKy5nExDJHbY1OUHroZ8cSQ_odtc4KWwJf6E/s1600/fixed-top-navbar1.png" /></a><br/><br/>
・スクロールしてもTOPメニューが固定されています。<br/>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFT8VhUCl5Vwll8TP913F9zTBjEEYUpzcjLh8vUpGcETp0GYLBjXiRNkUTXApf37yEuTEfsOQ69bCEGECswrD4SKQuHoS27LnOIye8yp8VRUKhiO7X6xQXQRB6RMb0NSZO_s2zJSTwSEU/s1600/fixed-top-navbar2.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFT8VhUCl5Vwll8TP913F9zTBjEEYUpzcjLh8vUpGcETp0GYLBjXiRNkUTXApf37yEuTEfsOQ69bCEGECswrD4SKQuHoS27LnOIye8yp8VRUKhiO7X6xQXQRB6RMb0NSZO_s2zJSTwSEU/s1600/fixed-top-navbar2.png" /></a><br/><br/>
<h2 class="sub_title">2. サイドメニューの伸縮(?) Sidebar Toggle</h2>
・TOPのキャプチャーです。<br/>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgqYwHvgj7gQae0ipBmvfpECKVirbvYbHB7hd8y5iq3WP-2ZWT2idJ9EvyZwJnq64UmTaTaf9zvbClGPbPojGkcnyNZDoCPvGOCRL6FcbrpKy5nExDJHbY1OUHroZ8cSQ_odtc4KWwJf6E/s1600/fixed-top-navbar1.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgqYwHvgj7gQae0ipBmvfpECKVirbvYbHB7hd8y5iq3WP-2ZWT2idJ9EvyZwJnq64UmTaTaf9zvbClGPbPojGkcnyNZDoCPvGOCRL6FcbrpKy5nExDJHbY1OUHroZ8cSQ_odtc4KWwJf6E/s1600/fixed-top-navbar1.png" /></a><br/><br/>
・ロゴ(SB Admin v2.0)の横にあるトグル(toggle)ボタンを押すとアイコンのみ表示されます。<br/>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfCMyqcZTIIVaJD8GDFlKCtTw7gNDWM1mzWNyVA0eBu33NMMc7mh8XiSTMBN3pOAeR9XRXa0XdLQw8F0cnrPdCIjzV6w41j7yymHLynD9cvyVBzAyzbofD2c1CQfBs_GL1njExrZDfBtY/s1600/sidebar-toggle1.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfCMyqcZTIIVaJD8GDFlKCtTw7gNDWM1mzWNyVA0eBu33NMMc7mh8XiSTMBN3pOAeR9XRXa0XdLQw8F0cnrPdCIjzV6w41j7yymHLynD9cvyVBzAyzbofD2c1CQfBs_GL1njExrZDfBtY/s1600/sidebar-toggle1.png" /></a><br/><br/>
・それぞれのアイコンにマウスオーバーすると詳細メニューが表示されます。<br/>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhqKUmjNfYvk0zglgGTWdMm3YD6FKI-Yjf_b9q1SJc5hSlfdxgdJzZZER1QI2pt-Ytc9aqM8EPHBUH_iqftAE6ntRhCf2GP5bwlgq6rN0-whaGSybwu9wqk07qj7TjtCf7_AYljMENVD4s/s1600/sidebar-toggle2.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhqKUmjNfYvk0zglgGTWdMm3YD6FKI-Yjf_b9q1SJc5hSlfdxgdJzZZER1QI2pt-Ytc9aqM8EPHBUH_iqftAE6ntRhCf2GP5bwlgq6rN0-whaGSybwu9wqk07qj7TjtCf7_AYljMENVD4s/s1600/sidebar-toggle2.png" /></a><br/><br/>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgqu_xmW-0Qy4nvqCnjBl2l9Knsg8vNfMxZjpCL5BeIrUcI7Gsd5MVGzLkbD719iL2X43ZnkItN_ICdseuil3Fbj1bu97rcDiLXOooQN5BjiE_S6UDk-tOsyM6rIqeEto8xShQMhiaOG3o/s1600/sidebar-toggle3.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgqu_xmW-0Qy4nvqCnjBl2l9Knsg8vNfMxZjpCL5BeIrUcI7Gsd5MVGzLkbD719iL2X43ZnkItN_ICdseuil3Fbj1bu97rcDiLXOooQN5BjiE_S6UDk-tOsyM6rIqeEto8xShQMhiaOG3o/s1600/sidebar-toggle3.png" /></a><br/><br/>
<br/>
<h2 class="sub_title">主な修正個所</h2>
・HTMLファイル(/pages/ディレクトリ):<br/>
<code class="path">bodyの開始タグ</code>から<code class="path"><div id="page-wrapper"></code>まで、TOPメニューとサイドバー部分修正<br/>
下段のJavascript部分にjquery.cookie.jsを追加<br/>
<pre class="brush:java">
<script src="../bower_components/jquery-cookie-master/src/jquery.cookie.js"></script>
</pre>
<br/>
・CSSファイル(/dist/css/):<br/>
sb-admin-2.css<br/>
<br/>
・JavaScriptファイル(/dist/js/):<br/>
sb-admin-2.js<br/>
<br/>
<br/>
<hr/>
詳細のソースコードはGithubをご参照ください。<br/>
<a href="https://github.com/kongbab04/sb-admin2-sidebar-toggle" target="_blank">https://github.com/kongbab04/sb-admin2-sidebar-toggle</a>
<br/><hr/><br/><br/><br/>
・元のソースは以下のページを参照してください。<br/>
<a href="https://github.com/IronSummitMedia/startbootstrap-sb-admin-2" target="_blank">https://github.com/IronSummitMedia/startbootstrap-sb-admin-2</a>
<br/><br/>unknownhttp://www.blogger.com/profile/15190790785934095924noreply@blogger.com1tag:blogger.com,1999:blog-8771673127918263645.post-40935113654124120972015-01-08T21:00:00.000+09:002015-01-08T21:00:02.692+09:00Gradleを利用してSpringのマルチプロジェクト生成
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh6QEEsQuWNFJ92l3bpNACHdDrjUlD7d2-KlUBJYo6nGDUt1gx5KmX3oDhXmTMf_12e_pNh78Hz1qA13lVTsiov-Cb1KWjkofduvAqjJmKrRn4CbCBdiGKSWJkmJApvPvj2ScvuhLASd4s/s1600/sts.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh6QEEsQuWNFJ92l3bpNACHdDrjUlD7d2-KlUBJYo6nGDUt1gx5KmX3oDhXmTMf_12e_pNh78Hz1qA13lVTsiov-Cb1KWjkofduvAqjJmKrRn4CbCBdiGKSWJkmJApvPvj2ScvuhLASd4s/s1600/sts.png" /></a><br/>
今回は、Gradleを利用してSpring-bootのマルチプロジェクトを生成し、<br/>
EclipseにImportしてみます。<br/><br/>
プロジェクトの構成は以下のようになります。<br/>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2YZeUJz0cD0W37BJJDRefJLpAjTp5GKUW0ezXsKszIVlMz-oimoG6NdWuIYf6GfqIHo2vA9mha5azRTjGNTHgMz1pn3Gl2dgm7tA1W_FFrDLr2L6ly_oX6hDVAbkuq-HXpcaQVdnBQFQ/s1600/project_structure.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2YZeUJz0cD0W37BJJDRefJLpAjTp5GKUW0ezXsKszIVlMz-oimoG6NdWuIYf6GfqIHo2vA9mha5azRTjGNTHgMz1pn3Gl2dgm7tA1W_FFrDLr2L6ly_oX6hDVAbkuq-HXpcaQVdnBQFQ/s1600/project_structure.png" /></a><br/>
<br/>
・Master:Multi Projectを生成・管理するための、Gradleの設定ファイルが配置されます。<br/><br/>
・Base:SpringのJavaプロジェクトで、DAO、DTO、各種Utilなどが配置されます。<br/>
・Shop Front:一般ユーザーが利用する画面で、Baseをインポートします。<br/>
・Shop Manager:管理者が利用する画面で、Baseをインポートします。<br/>
・Shop Batch:各種バッチが実行されるプロジェクトです。Baseをインポートします。<br/><br/>
インストール環境とバージョンは以下のようになります。<br/>
<h2 class="sub_title">インストール環境とバージョン</h2>
<table class="table_system_info01">
<tbody>
<tr>
<th>名前</th>
<th>バージョン</th>
<th>ダウンロード元</th>
</tr>
<tr>
<td class="td-subject">Windwos(OS)</td>
<td>7 (64bit)</td>
<td></td>
</tr>
<tr>
<td class="td-subject">Java</td>
<td>Java SE 1.8.0_20</td>
<td><a href="http://www.oracle.com/technetwork/java/javase/downloads/index.html" target="_blank" title="Java SE 1.8.0_20">Oracle</a></td>
</tr>
<tr>
<td class="td-subject">Gradle</td>
<td>2.1</td>
<td><a href="https://www.gradle.org/downloads" target="_blank" title="gradle-2.1">Gradle</a></td>
</tr>
<tr>
<td class="td-subject">IDE</td>
<td>SPRING TOOL SUITE 3.6.1(Eclipse)</td>
<td><a href="http://spring.io/tools/sts" target="_blank" title="sts 3.6.1">Sts</a></td>
</tr>
</tbody>
</table>
※上記は私の環境で、バージョンが少し変わっても問題ないと思います。<br/>
<h2 class="sub_title">インストール</h2>
・JavaはJDKをダウンロード→インストールした後、環境変数を登録してください。<br/>
・Gradleはサイトからダウンロード→圧縮解凍した後、環境変数に登録してください。<br/>
・STS(SPRING TOOL SUITE)はサイトからダウンロード→圧縮解凍してください。<br/>
<br/>
問題なくインストールされたかをWindowsのコマンドプロンプトを利用して確認してみましょう。<br/>
<pre class="brush:bash">
Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation. All rights reserved.
C:\Users\park>java -version
java version "1.8.0_20"
Java(TM) SE Runtime Environment (build 1.8.0_20-b26)
Java HotSpot(TM) 64-Bit Server VM (build 25.20-b23, mixed mode)
C:\Users\park>gradle -version
------------------------------------------------------------
Gradle 2.1
------------------------------------------------------------
Build time: 2014-09-08 10:40:39 UTC
Build number: none
Revision: e6cf70745ac11fa943e19294d19a2c527a669a53
Groovy: 2.3.6
Ant: Apache Ant(TM) version 1.9.3 compiled on December 23 2013
JVM: 1.8.0_20 (Oracle Corporation 25.20-b23)
OS: Windows 7 6.1 amd64
</pre>
<br/>
続いて、<br/>
プロジェクトのワークスペースとプロジェクトのディレクトリを作成します。<br/>
私はShopという名前のプロジェクトをD:\に作成しましたが、<br/>
他の経路でも構いません。<br/>
<pre class="brush:bash">
C:\Users\park>cd /d d:
D:\>md D:\project\shop\workspace\master
D:\>md D:\project\shop\workspace\base
D:\>md D:\project\shop\workspace\shop_front
D:\>md D:\project\shop\workspace\shop_manager
D:\>md D:\project\shop\workspace\shop_batch
D:\>cd D:\project\shop\workspace\master
D:\project\shop\workspace\master>
</pre>
<h2 class="sub_title">Gradleのbuild.gradleファイル設定</h2>
<code class="path">master</code>ディレクトリの中に<code class="path">build.gradle</code>ファイルを配置してください。<br/>
build.gradleファイルの中身は以下のようになります。<br/>
<pre class="brush:bash">
apply plugin: 'eclipse'
/**
* eclipse 更新時
* gradlew.bat clean mkdirs eclipse
*
* Build時
* gradlew.bat clean build
*
* リアルサーバ用のBuild時
* gradlew.bat -Penv=prod clean build
*
* ディレクトリの生成が必要なときには mkdirs タスク
*/
buildscript {
ext {
//Spring Boot
springBootVersion = '1.1.6.RELEASE'
//Spring
springVersion = '4.0.7.RELEASE'
}
repositories {
mavenCentral()
maven {
url 'http://repo.spring.io/libs-release'
url 'http://repo.spring.io/milestone'
}
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
subprojects {
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
//Encoding
def defaultEncoding = 'UTF-8'
[compileJava, compileTestJava]*.options*.encoding = defaultEncoding
//Java Version
sourceCompatibility = 1.8
targetCompatibility = 1.8
//プロジェクトのバージョン
version = '0.1'
repositories {
mavenCentral()
}
//ソースディレクトリ設定
sourceSets {
generated {
java {
srcDirs = ['src/main/generated/']
}
}
main {
resources {
srcDirs = [ 'src/main/resources' ]
}
}
}
//設定ファイルの切り替え(本番用・テストサーバ用)
def environment = project.hasProperty( 'env' ) ? env : 'dev'
if( environment.equals( 'prod' ))
sourceSets.main.resources.srcDirs 'src/main/resources/production'
else
sourceSets.main.resources.srcDirs 'src/main/resources/development'
println "Target environment: $environment"
dependencies {
//Spring boot
compile("org.springframework.boot:spring-boot-starter-web:${springBootVersion}")
compile("org.springframework.boot:spring-boot-starter-test:${springBootVersion}")
// Logging with SLF4J & LogBack
compile("org.slf4j:slf4j-api:1.7.7")
compile("ch.qos.logback:logback-classic:1.1.2")
// util
compile("com.google.guava:guava:18.0")
compile("com.google.code.gson:gson:2.3")
testCompile 'junit:junit:4.11'
}
eclipse {
classpath {
file {
whenMerged { classpath ->
classpath.configure classpath.entries.grep { entry ->
!(entry instanceof org.gradle.plugins.ide.eclipse.model.Library)
}
}
}
}
}
//各種ディレクトリ生成
task mkdirs << {
["src/main/generated", "src/main/java", "src/main/resources", "src/test/java", "src/test/resources"].each {
def path = "${projectDir}/${it}"
ant.mkdir(dir: path)
ant.touch(file: "${path}/.gitkeep")
}
}
}
project(':base') {
dependencies {
}
}
project(':shop_front') {
configurations {
spi
}
dependencies {
compile project(':base')
compile("org.springframework.boot:spring-boot-starter-thymeleaf:${springBootVersion}")
}
task spiJar(type: Jar) {
baseName = 'api-spi'
dependsOn classes
from sourceSets.main.output
include('jp/shop/base/**')
}
artifacts {
spi spiJar
}
}
project(':shop_manager') {
configurations {
spi
}
dependencies {
compile project(':base')
compile("org.springframework.boot:spring-boot-starter-thymeleaf:${springBootVersion}")
}
task spiJar(type: Jar) {
baseName = 'api-spi'
dependsOn classes
from sourceSets.main.output
include('jp/shop/base/**')
}
artifacts {
spi spiJar
}
}
project(':shop_batch') {
apply plugin: 'spring-boot'
configurations {
spi
}
dependencies {
compile project(':base')
}
task spiJar(type: Jar) {
baseName = 'api-spi'
dependsOn classes
from sourceSets.main.output
include('jp/shop/base/**')
}
artifacts {
spi spiJar
}
}
task wrapper(type: Wrapper) {
gradleVersion = '1.12'
}
</pre>
※Windowsのメモ帳ではUTF-8に保存しても「UTF-8 + BOM」になるため、日本語の文字化けにより実行されない可能性があります。<br/>
<h2 class="sub_title">Gradleのsettings.gradleファイル設定</h2>
<code class="path">build.gradle</code>と同様に<code class="path">settings.gradle</code>ファイルを生成します。
<pre class="brush:bash">
includeFlat "base", "shop_front", "shop_manager", "shop_batch"
</pre>
<br/>
<h2 class="sub_title">GradleのWrapper</h2>
他の人(プロジェクトのメンバー)がGradleをインストールせずに使えるようにWrapperを追加してみます。<br/><br/>
追加する方法はコマンドプロンプトで<code class="path">gradle wrapper</code>コマンドを入力するだけです。<br/>
すると自動的に<code class="path">gradlew.bat</code>が生成され、gradleをインストールしなくても使えるようになります。<br/>
<pre class="brush:bash">
C:\Users\park>cd /d d:
D:\>cd d:\project\shop\workspace\master
D:\project\shop\workspace\master>gradle wrapper
Target environment: dev
Target environment: dev
Target environment: dev
Target environment: dev
:wrapper
BUILD SUCCESSFUL
Total time: 3.701 secs
D:\project\shop\workspace\master>
</pre>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtZ-eV7QYs3SY6hkEvuXEt-BIghLyXKM_pYDWCq3aFR0TCsjvMJ1wXSZya1v_kMb7OMLKPod0HyHcjLp-Gh9_k0KU45Kxu88XP7hxlaaNoaEStoptkreLFMFs0mKYSbBVc4zZefAdNNzQ/s1600/directory.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtZ-eV7QYs3SY6hkEvuXEt-BIghLyXKM_pYDWCq3aFR0TCsjvMJ1wXSZya1v_kMb7OMLKPod0HyHcjLp-Gh9_k0KU45Kxu88XP7hxlaaNoaEStoptkreLFMFs0mKYSbBVc4zZefAdNNzQ/s1600/directory.png" /></a><br/>
<h2 class="sub_title">マルチプロジェクト生成</h2>
これで、設定は完了です。<br/>
gradlew.batを利用して、マルチプロジェクトを生成してみましょう。<br/>
<pre class="brush:bash">
C:\Users\park>cd /d d:
D:\>cd d:\project\shop\workspace\master
D:\project\shop\workspace\master>gradlew.bat clean mkdirs eclipse
Target environment: dev
Target environment: dev
Target environment: dev
Target environment: dev
:base:clean UP-TO-DATE
:shop_batch:clean UP-TO-DATE
:shop_front:clean UP-TO-DATE
:shop_manager:clean UP-TO-DATE
:base:mkdirs
:shop_batch:mkdirs
:shop_front:mkdirs
:shop_manager:mkdirs
:eclipseProject
:eclipse
:base:eclipseClasspath
:base:eclipseJdt
:base:eclipseProject
:base:eclipse
:shop_batch:eclipseClasspath
:shop_batch:eclipseJdt
:shop_batch:eclipseProject
:shop_batch:eclipse
:shop_front:eclipseClasspath
:shop_front:eclipseJdt
:shop_front:eclipseProject
:shop_front:eclipse
:shop_manager:eclipseClasspath
:shop_manager:eclipseJdt
:shop_manager:eclipseProject
:shop_manager:eclipse
BUILD SUCCESSFUL
Total time: 1 mins 17.905 secs
D:\project\shop\workspace\master>
</pre>
<h2 class="sub_title">Eclipseにインポート</h2>
STSを実行し、<br/>
File → Import → Gradle → Gradle Project →
Browse → masterプロジェクト指定(D:\project\shop\workspace\master) → Build Model → 全てのプロジェクトをチェック → Finish<br/>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXsiFRvrofTX1bC_OIXJfGYg2hobCWIiQTI6clnZJQxQ7XaBr8zhGlDEobWLKELSobex1-vGi5rNdlDuxJNFNMUr1LcubXpwj66h33AFyiOHBE0k_aFIuUBGsnjTWjHGZQua4vI6B3XrU/s1600/%E7%84%A1%E9%A1%8C.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXsiFRvrofTX1bC_OIXJfGYg2hobCWIiQTI6clnZJQxQ7XaBr8zhGlDEobWLKELSobex1-vGi5rNdlDuxJNFNMUr1LcubXpwj66h33AFyiOHBE0k_aFIuUBGsnjTWjHGZQua4vI6B3XrU/s1600/%E7%84%A1%E9%A1%8C.png" /></a><br/>
<br/>
生成されたディレクトリ構造は以下のようになります。<br/>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDialZdZiXw_Oscg0ynHi8waK-_iqsTCt4CqJTds-v4k7yYeIsVc3gNUW0vZXIlvDKhgqp5nKCJSUUQm3UON_N1Kyxy6OgdL7gND6QtAAMl1sNXBamjlsiFG7EWTNEbLU2Rtp0XOCdRhY/s1600/%E7%84%A1%E9%A1%8C.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDialZdZiXw_Oscg0ynHi8waK-_iqsTCt4CqJTds-v4k7yYeIsVc3gNUW0vZXIlvDKhgqp5nKCJSUUQm3UON_N1Kyxy6OgdL7gND6QtAAMl1sNXBamjlsiFG7EWTNEbLU2Rtp0XOCdRhY/s1600/%E7%84%A1%E9%A1%8C.png" /></a><br/>
<br/>
<hr/>
詳細のソースコードはGithubをご参照ください。<br/>
<a href="https://github.com/kongbab04/gradle-spring-multi-project-skeleton" target="_blank">https://github.com/kongbab04/gradle-spring-multi-project-skeleton</a>
<br/><hr/><br/><br/>unknownhttp://www.blogger.com/profile/15190790785934095924noreply@blogger.com0tag:blogger.com,1999:blog-8771673127918263645.post-74601737964429259142014-11-06T22:39:00.001+09:002014-11-06T23:20:11.424+09:00Zabbix 2.2でTomcat(JMX)を監視する今回は、Zabbixを利用してTomcatのリソースを監視してみたいと思います。<br/>
監視の流れは以下のようになります。<br/>
Zabbix Server(Port:10051、IP:192.168.56.101)<br/>
↓<br/>
ZabbixJavaGateway(Port:10052、IP:192.168.56.101)<br/>
↓<br/>
Tomcat【JMX Interface(Port:10080、IP:192.168.56.102)】<br/><br/>
<h2 class="sub_title">インストール環境とバージョン</h2>
<table class="table_system_info01">
<tbody>
<tr>
<th>名前</th>
<th>バージョン</th>
<th>ダウンロード元</th>
</tr>
<tr>
<td class="td-subject">ubuntu</td>
<td>10.04.4(64bit)</td>
<td><a href="http://releases.ubuntu.com/lucid/" target="_blank" title="ubuntu-10.04.4">http://releases.ubuntu.com/lucid/</a></td>
</tr>
<tr>
<td class="td-subject">ZABBIX</td>
<td>2.2.0</td>
<td><a href="http://www.zabbix.com/" target="_blank" title="zabbix-2.2.0">http://www.zabbix.com/</a></td>
</tr>
<tr>
<td class="td-subject">Tomcat</td>
<td>7.0.50</td>
<td><a href="http://tomcat.apache.org/" target="_blank" title="tomcat">http://tomcat.apache.org/</a></td>
</tr>
</tbody>
</table>
<h2 class="sub_title">Zabbix Serverインストール</h2>
「<a href="/2013/12/zabbix2.2.0-install-server.html" target="_blank" title="zabbix server">Zabbix Serverのインストール手順</a>」を参照してください。
<br />
<h2 class="sub_title">Zabbix Agentインストール</h2>
「<a href="/2014/01/zabbix-agent-install_16.html" target="_blank" title="zabbix agent">Zabbix Agentのインストール手順</a>」を参照してください。
<br />
<h2 class="sub_title">Tomcatインストール</h2>
Tomcatは監視対象(Agent側)のサーバにインストールされている必要があります。<br/>
「<a href="/2014/02/tomcat-install.html" target="_blank" title="tomcat install">Tomcatのインストール手順(7.0.50)</a>」をご参考ください。
<br />
<h2 class="sub_title">Tomcatの設定変更【監視される側(Agent)】</h2>
リモートからJMXでの監視が出来るようにTomcatの起動オプションを変更します。<br/>
Tomcatの起動時の環境変数<code class="path">CATALINA_OPTS</code>に以下のオプションを追加してください。<br/>
<pre class="brush:bash">
-Dcom.sun.management.jmxremote=true
#Openするポート
-Dcom.sun.management.jmxremote.port=10080
#OpenするIP(TomcatサーバのIP)
-Djava.rmi.server.hostname=192.168.56.102
#SSL有無
-Dcom.sun.management.jmxremote.ssl=false
#認証有無
-Dcom.sun.management.jmxremote.authenticate=false
</pre>
<br/>
実際の例は以下のようになります。<br/>
・オプション追加<br/>
<pre class="brush:bash">
# vi /etc/init.d/tomcat
export CATALINA_OPTS="-Xms512m -Xmx512m -XX:NewSize=341m -XX:MaxNewSize=341m
-XX:SurvivorRatio=2 -XX:PermSize=128m -XX:MaxPermSize=128m
-Dcom.sun.management.jmxremote=true
-Dcom.sun.management.jmxremote.port=10080
-Djava.rmi.server.hostname=192.168.56.102
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false"
</pre>
<br/>
・Tomcat再起動後、プロセス確認<br/>
<pre class="brush:bash">
# ps -awef|grep tomcat | grep -v grep
root 1868 1 0 16:22 ? 00:00:00 jsvc.exec -java-home /usr/local/java/current -user tomcat -pidfile /usr/local/tomcat/current/logs/catalina-daemon.pid -wait 10 -outfile /usr/local/tomcat/current/logs/catalina.out -errfile &1 -classpath /usr/local/tomcat/current/bin/bootstrap.jar:/usr/local/tomcat/current/bin/commons-daemon.jar:/usr/local/tomcat/current/bin/tomcat-juli.jar -Djava.util.logging.config.file=/usr/local/tomcat/current/conf/logging.properties -Djava.security.egd=file:/dev/./urandom -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Xms512m -Xmx512m -XX:NewSize=341m -XX:MaxNewSize=341m -XX:SurvivorRatio=2 -XX:PermSize=128m -XX:MaxPermSize=128m -Dcom.sun.management.jmxremote=true -Dcom.sun.management.jmxremote.port=10080 -Djava.rmi.server.hostname=192.168.56.102 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Djava.endorsed.dirs= -Dcatalina.base=/usr/local/tomcat/current -Dcatalina.home=/usr/local/tomcat/current -Djava.io.tmpdir=/usr/local/tomcat/current/temp org.apache.catalina.startup.Bootstrap
tomcat 1869 1868 11 16:22 ? 00:00:03 jsvc.exec -java-home /usr/local/java/current -user tomcat -pidfile /usr/local/tomcat/current/logs/catalina-daemon.pid -wait 10 -outfile /usr/local/tomcat/current/logs/catalina.out -errfile &1 -classpath /usr/local/tomcat/current/bin/bootstrap.jar:/usr/local/tomcat/current/bin/commons-daemon.jar:/usr/local/tomcat/current/bin/tomcat-juli.jar -Djava.util.logging.config.file=/usr/local/tomcat/current/conf/logging.properties -Djava.security.egd=file:/dev/./urandom -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Xms512m -Xmx512m -XX:NewSize=341m -XX:MaxNewSize=341m -XX:SurvivorRatio=2 -XX:PermSize=128m -XX:MaxPermSize=128m -Dcom.sun.management.jmxremote=true -Dcom.sun.management.jmxremote.port=10080 -Djava.rmi.server.hostname=192.168.56.102 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Djava.endorsed.dirs= -Dcatalina.base=/usr/local/tomcat/current -Dcatalina.home=/usr/local/tomcat/current -Djava.io.tmpdir=/usr/local/tomcat/current/temp org.apache.catalina.startup.Bootstrap
</pre>
<br/>
※接続時のID・パスワードの認証をかけたい場合は以下のようにオプションを変更してください。<br/>
<code class="path">authenticate=true</code><br/>
<pre class="brush:bash">
# vi /etc/init.d/tomcat
export CATALINA_OPTS="-Xms512m -Xmx512m -XX:NewSize=341m -XX:MaxNewSize=341m
-XX:SurvivorRatio=2 -XX:PermSize=128m -XX:MaxPermSize=128m
-Dcom.sun.management.jmxremote=true
-Dcom.sun.management.jmxremote.port=10080
-Djava.rmi.server.hostname=192.168.56.102
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=true"
# -Dcom.sun.management.jmxremote.authenticate=false" Comment Out
</pre>
<br/>
接続するID・Passwordの設定<br/>
<code class="path">[jdk_install_dir]/jre/lib/management/jmxremote.password</code><br/>
<pre class="brush:bash">
# cp /usr/local/java/current/jre/lib/management/jmxremote.password.template /usr/local/java/current/jre/lib/management/jmxremote.password
# vi /usr/local/java/current/jre/lib/management/jmxremote.password
</pre>
<br/>
最後のラインのコメントアウト解除(パスワード設定)<br/>
<pre class="brush:bash">
monitorRole QED
# controlRole R&D
</pre>
<br/>
パスワードファイルのパーミッションが<code class="path">600</code>でないと以下のような
エラーが発生しますので、パーミッションを変更します。<br/>
<blockquote>
エラー: パスワードファイルの読み取りアクセスは制限する必要があります。: /usr/local/java/current/jre/lib/management/jmxremote.password
</blockquote>
<br/>
<pre class="brush:bash">
# chmod 600 /usr/local/java/current/jre/lib/management/jmxremote.password
</pre>
<br/>
Tomcat再起動
<h2 class="sub_title">Zabbix Serverの設定を変更【監視する側(Server)】</h2>
<br/>
<strong>・Zabbix Server で Zabbix Java Gateway を認識させる</strong><br/>
<pre class="brush:bash">
# vi /usr/local/etc/zabbix_server.conf
JavaGateway=192.168.56.101 #server ip
JavaGatewayPort=10052
StartJavaPollers=2
</pre>
<br/><br/>
<strong>・ZabbixのJava ゲートウェイをインストールする(し直す)</strong><br/>
(Zabbixのインストールオプションで<code class="path">--enable-java</code>がすでに有効になっている場合はこちらの手順は省略してください。)<br/><br/>
ZabbixでJavaをenableするためにはサーバ側にjdkがインストールされている必要があります。<br/>
インストール手順は
「<a href="/2014/02/java-jdk-install.html" title="jdk1.7" target="_blank">Javaのインストール手順</a>」を参照してください。
<br />
<pre class="brush:bash">
# cd /usr/local/src/zabbix-2.2.0
# ./configure --enable-server --with-mysql=/usr/local/mysql/current/bin/mysql_config --with-net-snmp --with-libcurl --enable-java
# make clean (Zabbixは再インストールなので、clean しています。)
# make
# make install
</pre>
<br /><br />
<strong>・Zabbix Java Gateway の設定を行う</strong><br/>
<pre class="brush:bash">
# vi /usr/local/sbin/zabbix_java/settings.sh
LISTEN_IP="192.168.56.101" # [server ip]
LISTEN_PORT=10052
START_POLLERS=2
</pre>
<br /><br />
<strong>・ログファイルを設定する</strong><br/>
<pre class="brush:bash">
# vi /usr/local/sbin/zabbix_java/lib/logback.xml
<configuration scan="true" scanPeriod="15 seconds">
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>/var/log/zabbix/zabbix_java.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
<fileNamePattern>/var/log/zabbix/zabbix_java.log.%i</fileNamePattern>
<minIndex>1</minIndex>
<maxIndex>3</maxIndex>
</rollingPolicy>
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<maxFileSize>5MB</maxFileSize>
</triggeringPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="FILE" />
</root>
</configuration>
</pre>
<br/><br/>
<strong>・zabbix_javaを起動する</strong><br/>
<pre class="brush:bash">
# /usr/local/sbin/zabbix_java/startup.sh
# ps -awef|grep zabbix-java-gateway | grep -v grep
root 25460 1 3 19:19 pts/0 00:00:00 java -server -classpath lib:lib/logback-classic-0.9.27.jar:lib/logback-core-0.9.27.jar:lib/org-json-2010-12-28.jar:lib/slf4j-api-1.6.1.jar:bin/zabbix-java-gateway-2.0.5.jar -Dzabbix.pidFile=/tmp/zabbix_java.pid -Dzabbix.listenIP=192.168.56.101 -Dzabbix.listenPort=10052 -Dzabbix.startPollers=2 com.zabbix.gateway.JavaGateway
#
</pre>
<br/>
もし、プロセスが無い場合は「logback.xml」で指定した「/var/log/zabbix/zabbix_java.log」を確認して対応してください。<br/>
例)Cannot assign requested address エラーが発生した場合<br/>
<pre class="brush:bash">
2014-10-21 23:31:02.647 [main] ERROR com.zabbix.gateway.JavaGateway - caught fatal exception
java.net.BindException: Cannot assign requested address
at java.net.PlainSocketImpl.socketBind(Native Method) ~[na:1.6.0_17]
at java.net.PlainSocketImpl.bind(PlainSocketImpl.java:365) ~[na:1.6.0_17]
at java.net.ServerSocket.bind(ServerSocket.java:319) ~[na:1.6.0_17]
at java.net.ServerSocket.<init>(ServerSocket.java:185) ~[na:1.6.0_17]
at com.zabbix.gateway.JavaGateway.main(JavaGateway.java:65) ~[zabbix-java-gateway-2.2.0.jar:na]
2014-10-21 23:31:02.648 [Thread-1] INFO com.zabbix.gateway.JavaGateway - Zabbix Java Gateway 2.2.0 (revision 40163) has stopped
</pre>
<br/>
該当のポートが既に使われているか確認<br/>
<pre class="brush:bash">
# lsof -i -n -P | grep 10052
</pre>
サーバのIPアドレスが問題なく設定されているの確認
<pre class="brush:bash">
# vi /usr/local/etc/zabbix_server.conf
# vi /usr/local/sbin/zabbix_java/settings.sh
</pre>
<br/></br/>
<h2 class="sub_title">Zabbix管理画面でHostを登録する</h2>
<strong>・tomcatのテンプレートをインポートする</strong><br/><br/>
まず、以下のリンクから自分のTomcatバージョンのテンプレートxmlファイルをダウンロードします。<br/>
<a href="https://sites.google.com/site/kongbab04/file/zabbix2-tomcat6-jmx-template.xml" title="zabbix2-tomcat6-jmx-template download"><u><i>tomcat6のテンプレート ダウンロード</i></u></a><br/>
<a href="https://sites.google.com/site/kongbab04/file/zabbix2-tomcat7-jmx-template.xml" title="zabbix2-tomcat7-jmx-template download"><u><i>tomcat7のテンプレート ダウンロード</i></u></a><br/><br/>
ダウンロードしたテンプレートをZabbix管理画面の以下のページにてインポートしてください。<br/>
<code class="path">設定</code>⇒<code class="path">テンプレート</code>⇒<code class="path">インポート</code>
<br/><br/>
<strong>・Tomcatのホストを登録する</strong><br/><br/>
<code class="path">設定</code>⇒<code class="path">ホスト</code>⇒<code class="path">ホストの作成</code><br/>
JMX interfacesにはTomcat(Agent)側に設定したIPとポートを入れてください。<br/>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_qGo9vSZm6MYC5GBC1k1B8oNi2f7DB_txuYpqbCp_dMnfBR0dYvn9m57xbf59m_CTUHZUGPXV9-WImU1Qud5Gta0Al2R7Up6rhKS3qs0aRoxQaMkf6x1A4PE4waCWZHV-pLjjdqOhle8/s1600/b2.png" target="_blank" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_qGo9vSZm6MYC5GBC1k1B8oNi2f7DB_txuYpqbCp_dMnfBR0dYvn9m57xbf59m_CTUHZUGPXV9-WImU1Qud5Gta0Al2R7Up6rhKS3qs0aRoxQaMkf6x1A4PE4waCWZHV-pLjjdqOhle8/s1600/b2.png" /></a><br/><br/>
<code class="path">Templatesタブ</code>に移動して、先ほど登録した<code class="path">Template JMX Tomcat7</code>テンプレートを検索して追加します。
<br/><br/>
<code class="path">Macrosタブ</code>に移動して以下のマクロを追加します。<br/>
<table class="table_system_info01">
<tbody>
<tr>
<th>マクロ名</th>
<th>値</th>
</tr>
<tr>
<td class="td-subject">{$AJP_PORT}</td>
<td>8009</td>
</tr>
<tr>
<td class="td-subject">{$CONNECTOR_MODE}</td>
<td>apr</td>
</tr>
<tr>
<td class="td-subject">{$HTTP_PORT}</td>
<td>8080</td>
</tr>
<tr>
<td class="td-subject">{$HTTPS_PORT}</td>
<td>8088</td>
</tr>
<tr>
<td class="td-subject">{$JMX_PASSWORD}</td>
<td>QED</td>
</tr>
<tr>
<td class="td-subject">{$JMX_USERNAME}</td>
<td>monitorRole</td>
</tr>
</tbody>
</table>
<br/>
こちらのマクロのリストはそれぞれのテンプレートXML(一番上)に記載されていますので、
ご参考ください。<br/>
また、こちらの<code class="path">設定値</code>はTomcat(Agent側)の<code class="path">server.xml</code>に記載されている内容を設定して頂く必要があります。<br/><br/>
<h2 class="sub_title">監視状態確認</h2>
ここまで問題なく設定されましたら、グラフ画面にて以下のようなデータが確認出来るかと思います<br/><br/>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhvn7fSoHG6oGQGzIVlaUXpwXKESo72mg4djVdpqoVPXDekoBADugkPivXet0IxNoHh5vRVQAtvqjdFeo_jsADEwdTlDfpOySowYarGkWX7EoBpgPpnx-ixZl0aEjWVSN80GEKKzX_Vg2I/s1600/b1.png" imageanchor="1" target="_blank" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhvn7fSoHG6oGQGzIVlaUXpwXKESo72mg4djVdpqoVPXDekoBADugkPivXet0IxNoHh5vRVQAtvqjdFeo_jsADEwdTlDfpOySowYarGkWX7EoBpgPpnx-ixZl0aEjWVSN80GEKKzX_Vg2I/s1600/b1.png" /></a>
<br/>
<br/>
もし、
上手くデータが取得出来ない場合はログなどを確認し、対応してください。<br/>
<br/>
<strong>・Zabbix ServerとAgent間の通信問題</strong><br/>
以下のコマンドで、適切な値が返ってくるのかをご確認ください。<br/>
<pre class="brush:bash">
# zabbix_get -s 192.168.56.102 -k agent.ping
1
# zabbix_get -s 192.168.56.102 -k agent.version
2.2.0
</pre>
<strong>・テンプレートXMLのキー(もしくはマクロ)の設定値の不一致</strong><br/>
Zabbix管理画面に登録されているマクロの設定値はTomcatのServer.xmlの値である必要がありますので、<br/>
それぞれの値が正確に入っているのか比較してください。<br/><br/>
また、<br/>
テンプレートXMLの<code class="path">Key</code>の値は、AgentサーバのTomcatのServer.xmlに設定されている値、且つ現在のJavaのバージョンのJMX(MBeans)から取得可能な値である必要があります。<br/>
上記の値を確認する方法としては、JConsoleなどのツールから該当のAgent(Tomcat)サーバに接続し、MBeansの値をチェックするのが一番簡単ではないかと思います。<br/><br/>
例)<br/>
テンプレートXMLの
<code class="path">HTTP Connector threads allocated</code>の<code class="path">jmx["Catalina:type=ThreadPool,name=\"http-{$CONNECTOR_MODE}-{$HTTP_PORT}\"",currentThreadCount]</code>が取得可能かどうかを確認してみます。<br/><br/>
JConsoleを立ち上げ、Agentサーバに接続 → MBeansタブへ移動<br/>
JConsole経路:<code class="path">%JAVA_HOME%\bin\jconsole.exe</code>
<br/><br/>
XMLキーで、Treeをで辿って行きます。<br/>
jmx["Catalina:type=ThreadPool,name=\"http-{$CONNECTOR_MODE}-{$HTTP_PORT}\"",currentThreadCount]<br/>
の場合は<br/>
jmx["Catalina(1階層):type=ThreadPool(2階層),name=\"http-{$CONNECTOR_MODE}-{$HTTP_PORT}\""(3階層),currentThreadCount(属性)]<br/>
になります。<br/>
即ち<br/>
Treeの第1階層: Catalina<br/>
Treeの第2階層: ThreadPool<br/>
Treeの第3階層: http-{$CONNECTOR_MODE}-{$HTTP_PORT} (マクロにそれぞれに入れた値)<br/>
の<code class="path">属性</code>に<code class="path">currentThreadCount</code>があればOK。<br/>
ない場合は、取得したい値をMBeansから探して、テンプレートXMLもしくはマクロを修正する必要があります。<br/><br/>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgyF15OgBEcR4EDO1MMVpRtV8CO4i77NYnjIhEedW-_UtLQYnOhgmMPaEsjYMcxG1sFITVfFuXu7V0nLj67ncVacixIUQvpoi4elx8Q_3CpxG5LT9sMPwG9BApBaj4glVxal8BPmnBVngk/s1600/b4.png" imageanchor="1" target="_blank" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgyF15OgBEcR4EDO1MMVpRtV8CO4i77NYnjIhEedW-_UtLQYnOhgmMPaEsjYMcxG1sFITVfFuXu7V0nLj67ncVacixIUQvpoi4elx8Q_3CpxG5LT9sMPwG9BApBaj4glVxal8BPmnBVngk/s1600/b4.png" /></a><br/>
<br/>
<h2 class="sub_title">参考URL</h2>
<a href="https://gist.github.com/hgomez/3209196" target="_blank">https://gist.github.com/hgomez/3209196</a><br/>
<a href="http://www.checksite.jp/zabbix-2-0-jmx-tomcat7-javagateway/" target="_blank">http://www.checksite.jp/zabbix-2-0-jmx-tomcat7-javagateway/</a><br/>
unknownhttp://www.blogger.com/profile/15190790785934095924noreply@blogger.com0tag:blogger.com,1999:blog-8771673127918263645.post-45268040585224216432014-10-07T21:00:00.000+09:002014-10-08T18:34:37.433+09:00AndroidのTableLayoutのスクロール&HeaderとBodyの分離&Cellの横幅自動整列<a id="_top"></a>
Androidで、TableLayoutをスクロールさせるためにはTableLayout全体をスクロールさせる方法しかないようで、<br/>
Headerを固定にし、Bodyのみスクロールさせるためには、Header部分とBody部分のTableLayoutを分離する必要があるようです。<br />
例) <br/>
<pre class="brush:java">
<!-- Table Head -->
<TableLayout android:layout_height="wrap_content"
android:layout_width="match_parent" android:id="@+id/headerTable">
<TableRow style="@style/tableHeaderRow">
<TextView style="@style/tableHeaderText" android:text="@string/header_text1" />
<TextView style="@style/tableHeaderText" android:text="@string/header_text1" />
<TextView style="@style/tableHeaderText" android:text="@string/header_text2" />
<TextView style="@style/tableHeaderText" android:text="@string/header_text3" />
</TableRow>
</TableLayout>
<!-- Table Body -->
<ScrollView android:layout_width="match_parent"
android:layout_height="wrap_content">
<TableLayout android:layout_height="wrap_content"
android:layout_width="match_parent" android:id="@+id/bodyTable">
</TableLayout>
</ScrollView>
</pre>
<br/>
HeaderとBodyを分離した場合、Bodyの部分の内容が固定(もしくはCellのWidthが固定)の場合は問題ありませんが、<br/>
Bodyの内容が前の処理などによって動的に変わる且つ、CellのWidthも変わる場合はHeaderとBodyのCellが合わなくなります。<br/><br/>
それを対処するためには、色々と方法があるかと思いますが、今回は以下の2つの方法について整理してみました。<br/>
1.LinearLayoutのonLayout時にTableLayoutのCellのWidthを調整する<br/>
2.RelativeLayoutに同じ内容のTableLayoutを二つ生成し、marginTopで位置をずらす。<br/>
<h2 class="sub_title">
1.LinearLayoutのonLayout時にTableLayoutのCellのWidthを調整する
</h2>
詳細ソース:<a href="https://github.com/kongbab04/ListViewTable" target="_blank">https://github.com/kongbab04/ListViewTable</a><br/>
layoutのmain.xml<br/>
<pre class="brush:java">
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent"
android:background="#FFFFFF"
android:layout_height="fill_parent">
<com.android.listview.table.ListViewTable
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<TableLayout android:layout_height="wrap_content"
android:layout_width="match_parent" android:id="@+id/headerTable">
<TableRow style="@style/tableHeaderRow">
<TextView style="@style/tableHeaderText" android:text="@string/header_text1" />
<TextView style="@style/tableHeaderText" android:text="@string/header_text1" />
<TextView style="@style/tableHeaderText" android:text="@string/header_text2" />
<TextView style="@style/tableHeaderText" android:text="@string/header_text3" />
</TableRow>
<TableRow style="@style/tableBodyRow">
<TextView android:text="@string/dummy" style="@style/tableBodyText" android:height="0dp" />
<TextView android:text="@string/dummy" style="@style/tableBodyText"
android:height="0dp" />
<TextView android:text="@string/dummy" style="@style/tableBodyText" android:height="0dp" />
<TextView android:text="@string/dummy" style="@style/tableBodyText" android:height="0dp" />
</TableRow>
</TableLayout>
<!-- Table Body -->
<ScrollView android:layout_width="match_parent"
android:layout_height="wrap_content">
<TableLayout android:layout_height="wrap_content"
android:layout_width="match_parent" android:id="@+id/bodyTable">
</TableLayout>
</ScrollView>
</com.android.listview.table.ListViewTable>
</LinearLayout>
</pre>
<br/>
ListViewTable.java<br/>
<pre class="brush:java">
package com.android.listview.table;
import java.util.LinkedList;
import java.util.List;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TableLayout;
import android.widget.TableRow;
public class ListViewTable extends LinearLayout {
public ListViewTable( Context context ) {
super( context );
}
public ListViewTable(Context context, AttributeSet attrs) {
super( context, attrs );
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout( changed, l, t, r, b );
List<Integer> colWidths = new LinkedList<Integer>();
TableLayout header = (TableLayout) findViewById( R.id.headerTable );
TableLayout body = (TableLayout) findViewById( R.id.bodyTable );
if (body.getChildCount() > 0) {
for ( int rownum = 0; rownum < 1; rownum++ ) {
TableRow row = (TableRow) body.getChildAt( rownum );
for ( int cellnum = 0; cellnum < row.getChildCount(); cellnum++ ) {
View cell = row.getChildAt( cellnum );
TableRow.LayoutParams params = (TableRow.LayoutParams)cell.getLayoutParams();
Integer cellWidth = params.span == 1 ? cell.getWidth() : 0;
if ( colWidths.size() <= cellnum ) {
colWidths.add( cellWidth );
} else {
Integer current = colWidths.get( cellnum );
if( cellWidth > current ) {
colWidths.remove( cellnum );
colWidths.add( cellnum, cellWidth );
}
}
}
}
for ( int rownum = 0; rownum < header.getChildCount(); rownum++ ) {
TableRow row = (TableRow) header.getChildAt( rownum );
for ( int cellnum = 0; cellnum < row.getChildCount(); cellnum++ ) {
View cell = row.getChildAt( cellnum );
TableRow.LayoutParams params = (TableRow.LayoutParams)cell.getLayoutParams();
params.width = 0;
for( int span = 0; span < params.span; span++ ) {
params.width += colWidths.get( cellnum + span );
}
}
}
}
}
}
</pre>
<br/>
結果のキャプチャー<br/>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgLSWs__Ww5XfYeIQ7TZXaAq_TB03xqmE_LVvirHLRFyJdvRKeLs1e5Zputes9820dGENUXd8w-auZkHMlqt4YCgwg9QSMds0BJjqtwmZYWJBjxo9w656oPEzjV_vuBG-lx3wEN_4gRRmI/s1600/1.result_1.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgLSWs__Ww5XfYeIQ7TZXaAq_TB03xqmE_LVvirHLRFyJdvRKeLs1e5Zputes9820dGENUXd8w-auZkHMlqt4YCgwg9QSMds0BJjqtwmZYWJBjxo9w656oPEzjV_vuBG-lx3wEN_4gRRmI/s400/1.result_1.png" /></a><br/>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjpyNrh2T9HTlXRIl8TjbaSLmHWd-cBsrBqGzK9I75fcXcQlmKieVhTeqJsZ7Em6qo5Qhhckdbv9Zrjm-jqSHzsFrOaejiFHJ1Cgp_ykvcEPJy614lSPtuYAQHBAk2BEnvh80nOFOH1tJk/s1600/1.result_2.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjpyNrh2T9HTlXRIl8TjbaSLmHWd-cBsrBqGzK9I75fcXcQlmKieVhTeqJsZ7Em6qo5Qhhckdbv9Zrjm-jqSHzsFrOaejiFHJ1Cgp_ykvcEPJy614lSPtuYAQHBAk2BEnvh80nOFOH1tJk/s400/1.result_2.png" /></a><br/>
詳細のソースコードはGithubをご参照ください。<br/>
<a href="https://github.com/kongbab04/ListViewTable" target="_blank">https://github.com/kongbab04/ListViewTable</a>
<br/><br/><br/>
<h2 class="sub_title">
2.RelativeLayoutに同じ内容のTableLayoutを二つ生成し、marginTopで位置をずらす。
</h2>
詳細ソース:<a href="https://github.com/kongbab04/ListViewTable2" target="_blank">https://github.com/kongbab04/ListViewTable2</a><br/>
layoutのmain.xml<br/>
<pre class="brush:java">
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FFFFFF"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<!--
TableLayout[1]
画面にはHeader部分のみ見せる。
Body部分にはTableLayout[2]と同じ内容を入れる事で、
HeaderのWidthが自動的に調節される。
-->
<TableLayout android:layout_height="wrap_content"
android:layout_width="match_parent" android:id="@+id/headerTable">
<TableRow style="@style/tableHeaderRow">
<TextView style="@style/tableHeaderText" android:text="Header1" />
<TextView style="@style/tableHeaderText" android:text="Header2" />
<TextView style="@style/tableHeaderText" android:text="Header3" />
<TextView style="@style/tableHeaderText" android:text="Header4" />
</TableRow>
<TableRow style="@style/tableBodyRow">
<TextView style="@style/tableHeaderText" android:text="Body1-1" />
<TextView style="@style/tableHeaderText" android:text="Body1-2" />
<TextView style="@style/tableHeaderText" android:text="Body1-3" />
<TextView style="@style/tableHeaderText" android:text="Body1-4" />
</TableRow>
<TableRow style="@style/tableBodyRow">
<TextView style="@style/tableHeaderText" android:text="Body2-1" />
<TextView style="@style/tableHeaderText" android:text="Body2-2" />
<TextView style="@style/tableHeaderText" android:text="Body2-3" />
<TextView style="@style/tableHeaderText" android:text="Body2-4" />
</TableRow>
<TableRow style="@style/tableBodyRow">
<TextView style="@style/tableHeaderText" android:text="Body3-1" />
<TextView style="@style/tableHeaderText" android:text="Body3-2" />
<TextView style="@style/tableHeaderText" android:text="Body3-3---------------------------" />
<TextView style="@style/tableHeaderText" android:text="Body3-4" />
</TableRow>
<TableRow style="@style/tableBodyRow">
<TextView style="@style/tableHeaderText" android:text="Body4-1" />
<TextView style="@style/tableHeaderText" android:text="Body4-2" />
<TextView style="@style/tableHeaderText" android:text="Body4-3" />
<TextView style="@style/tableHeaderText" android:text="Body4-4" />
</TableRow>
<TableRow style="@style/tableBodyRow">
<TextView style="@style/tableHeaderText" android:text="Body5-1" />
<TextView style="@style/tableHeaderText" android:text="Body5-2" />
<TextView style="@style/tableHeaderText" android:text="Body5-3" />
<TextView style="@style/tableHeaderText" android:text="Body5-4" />
</TableRow>
<TableRow style="@style/tableBodyRow">
<TextView style="@style/tableHeaderText" android:text="Body6-1" />
<TextView style="@style/tableHeaderText" android:text="Body6-2" />
<TextView style="@style/tableHeaderText" android:text="Body6-3" />
<TextView style="@style/tableHeaderText" android:text="Body6-4" />
</TableRow>
<TableRow style="@style/tableBodyRow">
<TextView style="@style/tableHeaderText" android:text="Body7-1" />
<TextView style="@style/tableHeaderText" android:text="Body7-2" />
<TextView style="@style/tableHeaderText" android:text="Body7-3" />
<TextView style="@style/tableHeaderText" android:text="Body7-4" />
</TableRow>
<TableRow style="@style/tableBodyRow">
<TextView style="@style/tableHeaderText" android:text="Body8-1" />
<TextView style="@style/tableHeaderText" android:text="Body8-2" />
<TextView style="@style/tableHeaderText" android:text="Body8-3" />
<TextView style="@style/tableHeaderText" android:text="Body8-4" />
</TableRow>
<TableRow style="@style/tableBodyRow">
<TextView style="@style/tableHeaderText" android:text="Body9-1" />
<TextView style="@style/tableHeaderText" android:text="Body9-2" />
<TextView style="@style/tableHeaderText" android:text="Body9-3" />
<TextView style="@style/tableHeaderText" android:text="Body9-4" />
</TableRow>
<TableRow style="@style/tableBodyRow">
<TextView style="@style/tableHeaderText" android:text="Body10-1" />
<TextView style="@style/tableHeaderText" android:text="Body10-2" />
<TextView style="@style/tableHeaderText" android:text="Body10-3" />
<TextView style="@style/tableHeaderText" android:text="Body10-4" />
</TableRow>
<TableRow style="@style/tableBodyRow">
<TextView style="@style/tableHeaderText" android:text="Body11-1" />
<TextView style="@style/tableHeaderText" android:text="Body11-2" />
<TextView style="@style/tableHeaderText" android:text="Body11-3" />
<TextView style="@style/tableHeaderText" android:text="Body11-4" />
</TableRow>
<TableRow style="@style/tableBodyRow">
<TextView style="@style/tableHeaderText" android:text="Body12-1" />
<TextView style="@style/tableHeaderText" android:text="Body12-2" />
<TextView style="@style/tableHeaderText" android:text="Body12-3" />
<TextView style="@style/tableHeaderText" android:text="Body12-4" />
</TableRow>
<TableRow style="@style/tableBodyRow">
<TextView style="@style/tableHeaderText" android:text="Body13-1" />
<TextView style="@style/tableHeaderText" android:text="Body13-2" />
<TextView style="@style/tableHeaderText" android:text="Body13-3" />
<TextView style="@style/tableHeaderText" android:text="Body13-4" />
</TableRow>
<TableRow style="@style/tableBodyRow">
<TextView style="@style/tableHeaderText" android:text="Body14-1" />
<TextView style="@style/tableHeaderText" android:text="Body14-2" />
<TextView style="@style/tableHeaderText" android:text="Body14-3" />
<TextView style="@style/tableHeaderText" android:text="Body14-4" />
</TableRow>
</TableLayout>
<!--
TableLayout[2]
画面にはBody部分のみ見せる。
ScrollViewにandroid:layout_marginTop="50dp"を入れることで、
TableLayout[1]のHeaderを見せ、TableLayout[2]はBodyのみ見せれる。
TableLayout[2]にはHeader部分がない。
-->
<ScrollView android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="50dp"
android:layout_alignParentTop="true"
android:layout_centerInParent="true"
>
<TableLayout android:layout_height="wrap_content"
android:layout_width="match_parent" android:id="@+id/headerTable">
<!--
2番目のTableLayoutにはHeaderが不要( 1番目のHeaderを使う為 )
代わりにmarginTop
<TableRow style="@style/tableHeaderRow">
<TextView style="@style/tableHeaderText" android:text="Header1" />
<TextView style="@style/tableHeaderText" android:text="Header2" />
<TextView style="@style/tableHeaderText" android:text="Header3" />
<TextView style="@style/tableHeaderText" android:text="Header4" />
</TableRow>
-->
<TableRow style="@style/tableBodyRow">
<TextView style="@style/tableHeaderText" android:text="Body1-1" />
<TextView style="@style/tableHeaderText" android:text="Body1-2" />
<TextView style="@style/tableHeaderText" android:text="Body1-3" />
<TextView style="@style/tableHeaderText" android:text="Body1-4" />
</TableRow>
<TableRow style="@style/tableBodyRow">
<TextView style="@style/tableHeaderText" android:text="Body2-1" />
<TextView style="@style/tableHeaderText" android:text="Body2-2" />
<TextView style="@style/tableHeaderText" android:text="Body2-3" />
<TextView style="@style/tableHeaderText" android:text="Body2-4" />
</TableRow>
<TableRow style="@style/tableBodyRow">
<TextView style="@style/tableHeaderText" android:text="Body3-1" />
<TextView style="@style/tableHeaderText" android:text="Body3-2" />
<TextView style="@style/tableHeaderText" android:text="Body3-3---------------------------" />
<TextView style="@style/tableHeaderText" android:text="Body3-4" />
</TableRow>
<TableRow style="@style/tableBodyRow">
<TextView style="@style/tableHeaderText" android:text="Body4-1" />
<TextView style="@style/tableHeaderText" android:text="Body4-2" />
<TextView style="@style/tableHeaderText" android:text="Body4-3" />
<TextView style="@style/tableHeaderText" android:text="Body4-4" />
</TableRow>
<TableRow style="@style/tableBodyRow">
<TextView style="@style/tableHeaderText" android:text="Body5-1" />
<TextView style="@style/tableHeaderText" android:text="Body5-2" />
<TextView style="@style/tableHeaderText" android:text="Body5-3" />
<TextView style="@style/tableHeaderText" android:text="Body5-4" />
</TableRow>
<TableRow style="@style/tableBodyRow">
<TextView style="@style/tableHeaderText" android:text="Body6-1" />
<TextView style="@style/tableHeaderText" android:text="Body6-2" />
<TextView style="@style/tableHeaderText" android:text="Body6-3" />
<TextView style="@style/tableHeaderText" android:text="Body6-4" />
</TableRow>
<TableRow style="@style/tableBodyRow">
<TextView style="@style/tableHeaderText" android:text="Body7-1" />
<TextView style="@style/tableHeaderText" android:text="Body7-2" />
<TextView style="@style/tableHeaderText" android:text="Body7-3" />
<TextView style="@style/tableHeaderText" android:text="Body7-4" />
</TableRow>
<TableRow style="@style/tableBodyRow">
<TextView style="@style/tableHeaderText" android:text="Body8-1" />
<TextView style="@style/tableHeaderText" android:text="Body8-2" />
<TextView style="@style/tableHeaderText" android:text="Body8-3" />
<TextView style="@style/tableHeaderText" android:text="Body8-4" />
</TableRow>
<TableRow style="@style/tableBodyRow">
<TextView style="@style/tableHeaderText" android:text="Body9-1" />
<TextView style="@style/tableHeaderText" android:text="Body9-2" />
<TextView style="@style/tableHeaderText" android:text="Body9-3" />
<TextView style="@style/tableHeaderText" android:text="Body9-4" />
</TableRow>
<TableRow style="@style/tableBodyRow">
<TextView style="@style/tableHeaderText" android:text="Body10-1" />
<TextView style="@style/tableHeaderText" android:text="Body10-2" />
<TextView style="@style/tableHeaderText" android:text="Body10-3" />
<TextView style="@style/tableHeaderText" android:text="Body10-4" />
</TableRow>
<TableRow style="@style/tableBodyRow">
<TextView style="@style/tableHeaderText" android:text="Body11-1" />
<TextView style="@style/tableHeaderText" android:text="Body11-2" />
<TextView style="@style/tableHeaderText" android:text="Body11-3" />
<TextView style="@style/tableHeaderText" android:text="Body11-4" />
</TableRow>
<TableRow style="@style/tableBodyRow">
<TextView style="@style/tableHeaderText" android:text="Body12-1" />
<TextView style="@style/tableHeaderText" android:text="Body12-2" />
<TextView style="@style/tableHeaderText" android:text="Body12-3" />
<TextView style="@style/tableHeaderText" android:text="Body12-4" />
</TableRow>
<TableRow style="@style/tableBodyRow">
<TextView style="@style/tableHeaderText" android:text="Body13-1" />
<TextView style="@style/tableHeaderText" android:text="Body13-2" />
<TextView style="@style/tableHeaderText" android:text="Body13-3" />
<TextView style="@style/tableHeaderText" android:text="Body13-4" />
</TableRow>
<TableRow style="@style/tableBodyRow">
<TextView style="@style/tableHeaderText" android:text="Body14-1" />
<TextView style="@style/tableHeaderText" android:text="Body14-2" />
<TextView style="@style/tableHeaderText" android:text="Body14-3" />
<TextView style="@style/tableHeaderText" android:text="Body14-4" />
</TableRow>
</TableLayout>
</ScrollView>
</RelativeLayout>
</pre>
<br/>
style.xml
<pre class="brush:java">
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<style name="tableHeaderRow">
<item name="android:background">#7FAF7F</item>
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
</style>
<style name="tableHeaderText">
<item name="android:textColor">#0F7F0F</item>
<item name="android:shadowColor">#AFFFFFFF</item>
<item name="android:shadowDx">1</item>
<item name="android:shadowDy">1</item>
<item name="android:shadowRadius">1.0</item>
<item name="android:padding">5dp</item>
<item name="android:gravity">center</item>
<item name="android:textSize">25sp</item>
<item name="android:textStyle">bold</item>
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
</style>
<style name="tableBodyRow">
<item name="android:background">#FFFFFF</item>
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
</style>
<style name="tableBodyText">
<item name="android:textColor">#7F7F7F</item>
<item name="android:shadowColor">#AFFFFFFF</item>
<item name="android:shadowDx">1</item>
<item name="android:shadowDy">1</item>
<item name="android:shadowRadius">1.0</item>
<item name="android:padding">5dp</item>
<item name="android:gravity">center</item>
<item name="android:textSize">22sp</item>
<item name="android:textStyle">bold</item>
<item name="android:layout_weight">1</item>
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
</style>
</resources>
</pre>
<br/>
結果のキャプチャー<br/>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhv1A1RmDhf8qieNc1otWkuUBT1msAB5oDxvZZ19yuXnSR2claJi7MMi7FJAE_8LPIFcTm4yBCWwyVz3bKv4nSMWxpx2rAX3jYWb7cOvwcaCXxnS5Vqo0GllwH9m2JCgnnmSOWLm8WQn9M/s1600/2.result_1.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhv1A1RmDhf8qieNc1otWkuUBT1msAB5oDxvZZ19yuXnSR2claJi7MMi7FJAE_8LPIFcTm4yBCWwyVz3bKv4nSMWxpx2rAX3jYWb7cOvwcaCXxnS5Vqo0GllwH9m2JCgnnmSOWLm8WQn9M/s400/2.result_1.png" /></a><br/>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNihMuDyqgdPcl3kP6YVbFQYu0t3c4MVOdirWnBqHZnaI1hKTs5HbwJJRZjZEQxZY_JsotulrBYmYdkwt069_6_6_qh4cNFXK59nE6s6QodHeCBDoX_aX3o5mX-ug9L8rZO8-Ddu6yZxo/s1600/2.result_2.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNihMuDyqgdPcl3kP6YVbFQYu0t3c4MVOdirWnBqHZnaI1hKTs5HbwJJRZjZEQxZY_JsotulrBYmYdkwt069_6_6_qh4cNFXK59nE6s6QodHeCBDoX_aX3o5mX-ug9L8rZO8-Ddu6yZxo/s400/2.result_2.png" /></a><br/><br/>
詳細のソースコードはGithubをご参照ください。<br/>
<a href="https://github.com/kongbab04/ListViewTable2" target="_blank">https://github.com/kongbab04/ListViewTable2</a>
<br/><br/><br/>unknownhttp://www.blogger.com/profile/15190790785934095924noreply@blogger.com1tag:blogger.com,1999:blog-8771673127918263645.post-43234529631396969142014-05-18T15:24:00.000+09:002014-06-03T18:52:21.331+09:00MYSQL Got error 12 from storage engine
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4ZEFvjoAnwwVdqqjow74SV6UsmR8qUPzpydPXcQbp7shlL_IZtfayPdY1oA7MGLS53KCgpG1Rd7jAItYSylgrPlyXP4nYP9AI1gVCOFpOy8UqD8kUYQ5HX8iLNCs9KlBXxN-xED-6-hM/s1600/%E7%84%A1%E9%A1%8C2.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4ZEFvjoAnwwVdqqjow74SV6UsmR8qUPzpydPXcQbp7shlL_IZtfayPdY1oA7MGLS53KCgpG1Rd7jAItYSylgrPlyXP4nYP9AI1gVCOFpOy8UqD8kUYQ5HX8iLNCs9KlBXxN-xED-6-hM/s1600/%E7%84%A1%E9%A1%8C2.png" /></a>
<br/>
mysqlサーバから特定のQueryを実行したところ、<code class="path">error 12</code>が返ってきた場合の対処方法をメモしておきます。<br/><br/>
Tomcatなどの場合は以下のようなエラーが発生します。<br/>
<pre class="brush:bash">
com.mysql.jdbc.exceptions.MySQLNonTransientConnectionException: Server connection failure during transaction. Due to underlying exception: 'java.sql.SQLException: Got error 12 from storage engine'.
** BEGIN NESTED EXCEPTION **
java.sql.SQLException
MESSAGE: Got error 12 from storage engine
STACKTRACE:
java.sql.SQLException: Got error 12 from storage engine
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:946)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:2985)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1631)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:1723)
at com.mysql.jdbc.Connection.execSQL(Connection.java:3277)
at com.mysql.jdbc.Connection.execSQL(Connection.java:3206)
at com.mysql.jdbc.Statement.executeQuery(Statement.java:1232)
at com.mysql.jdbc.Connection.loadServerVariables(Connection.java:4478)
at com.mysql.jdbc.Connection.initializePropsFromServer(Connection.java:4062)
at com.mysql.jdbc.Connection.createNewIO(Connection.java:2940)
at com.mysql.jdbc.Connection.<init>(Connection.java:1555)
at com.mysql.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:285)
at org.apache.tomcat.dbcp.dbcp.DriverConnectionFactory.createConnection(DriverConnectionFactory.java:38)
at org.apache.tomcat.dbcp.dbcp.PoolableConnectionFactory.makeObject(PoolableConnectionFactory.java:294)
at org.apache.tomcat.dbcp.pool.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:1148)
at org.apache.tomcat.dbcp.dbcp.PoolingDataSource.getConnection(PoolingDataSource.java:96)
at org.apache.tomcat.dbcp.dbcp.BasicDataSource.getConnection(BasicDataSource.java:880)
</pre>
<br/>
<h2 class="sub_title">error 12の原因</h2>
調べたところ、メモリに関するエラーのようで、<br/>
<blockquote>Error 12 = Cannot allocate memory </blockquote>
私の場合はQueryを実施した直後、エラーが発生していましたので、<br/>
Queryもしくはその結果データをメモリ上に上げる時に<br/>
エラーが発生していると判断しました。<br/><br/>
<h2 class="sub_title">解決</h2>
エラーが発生した原因によって解決方法は変わると思いますが、<br/>
今回は<code class="path">mysqlサーバの使用可能メモリを増やす</code>と<code class="path">Queryの最適化</code>という方法で、
解決しました。<br/><br/>
<h3>・MySQLのメモリを増やす</h3>
以下のページを参照して、必要なパラメタを増やしましょう。<br/>
<a href="/2013/10/mysqlmycnf.html" title="MySQLのmy.cnf">MySQLのmy.cnfファイル</a><br/><br/>
MyISAMの<code class="path">key_buffer_size</code>を動的に増やす例)
<pre class="brush:bash">
SET global key_buffer_size=1024*1024*1024;
</pre>
<br/><br/>
<h3>・Queryを最適化する</h3>
SELECTクエリ自体が重い場合は<code class="path">EXPLAIN</code>を利用してクエリを最適化したり、<br/>
クエリ自体を複数に分けるのも一つの方法だと思います。<br/>
重くなりがちな<code class="path">JOIN</code>、<code class="path">GROUP BY</code>、<code class="path">UNION</code>、<code class="path">SUB QUERY</code>などを中心にチューニングしましょう。
<br/><br/>unknownhttp://www.blogger.com/profile/15190790785934095924noreply@blogger.com0tag:blogger.com,1999:blog-8771673127918263645.post-42819623541898388812014-02-19T23:16:00.000+09:002014-02-19T23:25:43.728+09:00Tomcatのインストール手順(7.0.50)
<h2 class="sub_title">インストール環境とバージョン</h2>
今回、インストールするサーバとTomcatのバージョンは以下のようになります。<br />
<table class="table_system_info01">
<tbody>
<tr>
<th>名前</th>
<th>バージョン</th>
<th>ダウンロード元</th>
</tr>
<tr>
<td class="td-subject">ubuntu</td>
<td>10.04.4(64bit)</td>
<td><a href="http://releases.ubuntu.com/lucid/" target="_blank" title="ubuntu-10.04.4">http://releases.ubuntu.com/lucid/</a></td>
</tr>
<tr>
<td class="td-subject">java(jdk)</td>
<td>1.7.0_51</td>
<td><a href="http://www.oracle.com/us/technologies/java/overview/index.html" target="_blank" title="java">http://www.oracle.com/us/technologies/java/overview/index.html</a></td>
</tr>
<tr>
<td class="td-subject">Tomcat</td>
<td>7.0.50</td>
<td><a href="http://tomcat.apache.org/" target="_blank" title="tomcat">http://tomcat.apache.org/</a></td>
</tr>
</tbody>
</table>
<h2 class="sub_title">
インストールする前の準備作業</h2>
開発パッケージが設置されてない場合は、<code class="path">apt-get</code>でインストールする必要があります。<br />
<pre class="brush:bash"># apt-get install build-essential curl libcurl3 libpcre3-dev libssl-dev libxml2-dev libbz2-dev libgd2-xpm-dev libmcrypt-dev
</pre>
<br/>
<h2 class="sub_title">JAVA(JDK)のインストール</h2>
「<a href="/2014/02/java-jdk-install.html" title="jdk1.7">Javaのインストール手順</a>」を参照してください。
<br />
<h2 class="sub_title">Tomcatのインストール</h2>
まず、Linuxのユーザを作成します。<br/>
※tomcatはセキュリティの為、一般ユーザで実行するようにしましょう。<br/>
<pre class="brush:bash">
# groupadd tomcat
# useradd -g tomcat -s /bin/false tomcat
</pre>
<br/>
Tomcatを設置します。<br/>
<pre class="brush:bash">
# mkdir /usr/local/tomcat
# cd /usr/local/src/
# wget http://ftp.kddilabs.jp/infosystems/apache/tomcat/tomcat-7/v7.0.50/bin/apache-tomcat-7.0.50.tar.gz
# tar xvf apache-tomcat-7.0.50.tar.gz -C /usr/local/tomcat/
# cd /usr/local/tomcat/
# ln -s apache-tomcat-7.0.50 current
# chown -R tomcat:tomcat /usr/local/tomcat/
</pre>
<br/>
環境ファイルを設定します。<br/>
<pre class="brush:bash">
# vi /etc/profile
#################
#java
#################
JAVA_HOME=/usr/local/java/current
#################
#tomcat
#################
CATALINA_HOME=/usr/local/tomcat/current
TOMCAT_USER=tomcat
export JAVA_HOME CATALINA_HOME TOMCAT_USER
PATH=$PATH:$HOME/bin:$JAVA_HOME/bin
export PATH
# source /etc/profile
# echo $CATALINA_HOME
/usr/local/tomcat/current
</pre>
<br/>
Tomcatをデーモン化します。<br/>
<pre class="brush:bash">
# cp /usr/local/tomcat/current/bin/commons-daemon-native.tar.gz /tmp/
# cd /tmp/
# tar xvzf commons-daemon-native.tar.gz
# cd commons-daemon-1.0.15-native-src/unix/
# ./configure
# make
# chown tomcat:tomcat jsvc
# mv jsvc /usr/local/tomcat/current/bin/
# rm -rf /tmp/commons-daemon-1.0.15-native-src /tmp/commons-daemon-native.tar.gz
</pre>
<br/>
Tomcat起動スクリプト<code class="path">/etc/init.d/tomcat</code>を作成します。
<pre class="brush:bash">
# vi /etc/init.d/tomcat
#!/bin/bash
#
# chkconfig: - 80 20
# description: catalina-daemon
# Source function library.
. /lib/lsb/init-functions
export CATALINA_OPTS="-Xms1024m -Xmx1024m -XX:NewSize=341m -XX:MaxNewSize=341m -XX:SurvivorRatio=2 -XX:PermSize=128m -XX:MaxPermSize=128m"
export CATALINA_PID=$CATALINA_HOME/logs/catalina-daemon.pid
export CATALINA_OUT="$CATALINA_HOME/logs/catalina.out"
export CATALINA_TMP="$CATALINA_HOME/temp"
tomcat=$CATALINA_HOME/bin/daemon.sh
prog=tomcat
lockfile=${LOCKFILE-/var/lock/tomcat}
RETVAL=0
start() {
echo -n $"Starting $prog: "
$tomcat start
RETVAL=$?
echo -n "[ $RETVAL ]"
if [ $RETVAL = 0 ]; then
echo "success"
touch ${lockfile}
else
echo "failure"
fi
echo
return $RETVAL
}
stop() {
echo -n $"Stopping $prog: "
$tomcat stop
RETVAL=$?
if [ $RETVAL = 0 ]; then
echo "success"
rm -f ${lockfile} ${CATALINA_PID}
else
echo "failure"
fi
echo
return $RETVAL
}
version() {
$tomcat version
RETVAL=$?
return $RETVAL
}
case "$1" in
start)
start
;;
stop)
stop
;;
restart)
stop
start
;;
condrestart)
if [ -f ${CATALINA_PID} ] ; then
stop
start
fi
;;
status)
if [ -f ${CATALINA_PID} ] ; then
cat /proc/`cat ${CATALINA_PID}`/status
else
echo "Tomcat is not running"
fi
;;
version)
version
;;
*)
echo $"Usage: $prog {start|stop|restart|condrestart|status|version}"
exit 1
esac
exit $RETVAL
</pre>
<br/>
Tomcatを起動します。<br/>
<pre class="brush:bash">
# chmod +x /etc/init.d/tomcat
# /etc/init.d/tomcat start
Starting tomcat: [ 0 ]success
# ps -ef | grep tomcat
root 6188 1 0 17:14 ? 00:00:00 jsvc.exec -java-home /usr/local/java/current -user tomcat -pidfile /usr/local/tomcat/current/logs/catalina-daemon.pid -wait 10 -outfile /usr/local/tomcat/current/logs/catalina.out -errfile &1 -classpath /usr/local/tomcat/current/bin/bootstrap.jar:/usr/local/tomcat/current/bin/commons-daemon.jar:/usr/local/tomcat/current/bin/tomca -juli.jar -Djava.util.logging.config.file=/usr/local/tomcat/current/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Xms512m -Xmx512m -XX:NewSize=341m -XX:MaxNewSize=341m -XX:SurvivorRatio=2 -XX:PermSize=128m -XX:MaxPermSize=128m -Djava.endorsed.dirs= -Dcatalina.base=/usr/local/tomcat/current -Dcatalina.home=/usr/local/tomcat/current -Djava.io.tmpdir=/usr/local/tomcat/current/temp org.apache.catalina.startup.Bootstrap
tomcat 6189 6188 1 17:14 ? 00:00:02 jsvc.exec -java-home /usr/local/java/current -user tomcat -pidfile /usr/local/tomcat/current/logs/catalina-daemon.pid -wait 10 -outfile /usr/local/tomcat/current/logs/catalina.out -errfile &1 -classpath /usr/local/tomcat/current/bin/bootstrap.jar:/usr/local/tomcat/current/bin/commons-daemon.jar:/usr/local/tomcat/current/bin/tomca -juli.jar -Djava.util.logging.config.file=/usr/local/tomcat/current/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Xms512m -Xmx512m -XX:NewSize=341m -XX:MaxNewSize=341m -XX:SurvivorRatio=2 -XX:PermSize=128m -XX:MaxPermSize=128m -Djava.endorsed.dirs= -Dcatalina.base=/usr/local/tomcat/current -Dcatalina.home=/usr/local/tomcat/current -Djava.io.tmpdir=/usr/local/tomcat/current/temp org.apache.catalina.startup.Bootstrap
root 6206 1118 0 17:16 pts/0 00:00:00 grep --color=auto tomcat
</pre>
tomcatのプロセスは親・子で、2つ上がるのが正常だそうです。<br/>
※起動時に時間がかかってfailureになる場合は<code class="path">Tomcat7の起動が遅い時</code>部分を参照してください。
<br/><br/>
<code class="path">catalina.out</code>ログを簡単に確認できるように<code class="path">alias</code>を登録します。<br/>
<pre class="brush:bash">
# vi /etc/profile
alias tclog="tail -f -n100 /usr/local/tomcat/current/logs/catalina.out"
# source /etc/profile
# tclog
....
Feb 18, 2014 6:32:38 PM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["http-bio-8080"]
Feb 18, 2014 6:32:38 PM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["ajp-bio-8009"]
Feb 18, 2014 6:32:38 PM org.apache.catalina.startup.Catalina start
INFO: Server startup in 2010 ms
</pre>
<br/>
正常に起動されましたら、ブラウザから接続してみましょう。<br/>
基本的にtomcatのポートは8080になっています。<br/>
※ポート番号は<code class="path">/usr/local/tomcat/current/conf/server.xml</code>の<code class="path">Connector</code>のプロトコル<code class="path">protocol="HTTP/1.1"</code>になっているコネクタのポート番号になります。<br/>
<br/>
http://192.168.56.102:8080/<br/>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjB8ry0TZuCvsTNsJWtSi9qBD71o_eEcJnV2ksvP8gsxXgcCORGJ2djIPBPMQpuajQnmV7Wp_5L67NMdrxB_4bJE4TR5T_MasFjePEjQe0Rwh63ualcXzOX2zbKG_CapqOB-XEB1x90E6Y/s1600/tomcat.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjB8ry0TZuCvsTNsJWtSi9qBD71o_eEcJnV2ksvP8gsxXgcCORGJ2djIPBPMQpuajQnmV7Wp_5L67NMdrxB_4bJE4TR5T_MasFjePEjQe0Rwh63ualcXzOX2zbKG_CapqOB-XEB1x90E6Y/s1600/tomcat.png" /></a><br/>
<h2 class="sub_title">Tomcat7の起動が遅い時</h2>
Tomcat7をstartupした時に時間がかかり、<code class="path">failure</code>(実際には成功したにも関わらず)になる場合があります。<br/>
<code class="path">catalina.out</code>ログを確認してみたら、ランダムセッションIDを発行する<code class="path">org.apache.catalina.util.SessionIdGenerator createSecureRandom</code>部分で時間がかかっていました。<br/>
その時はJREの設定を<code class="path">/dev/random</code> ⇒ <code class="path">/dev/./urandom</code>(non-blocking)に変更してください。<br/><br/>
<strong>・起動が遅かったときのcatalinaログ</strong><br/>
<pre class="brush:bash">
INFO: Initializing ProtocolHandler ["ajp-bio-8009"]
Feb 18, 2014 5:25:32 PM org.apache.catalina.startup.Catalina load
INFO: Initialization processed in 901 ms
Feb 18, 2014 5:25:32 PM org.apache.catalina.core.StandardService startInternal
INFO: Starting service Catalina
Feb 18, 2014 5:25:32 PM org.apache.catalina.core.StandardEngine startInternal
INFO: Starting Servlet Engine: Apache Tomcat/7.0.50
Feb 18, 2014 5:25:32 PM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory /usr/local/tomcat/apache-tomcat-7.0.50/webapps/host-manager
Feb 18, 2014 5:28:42 PM org.apache.catalina.util.SessionIdGenerator createSecureRandom
INFO: Creation of SecureRandom instance for session ID generation using [SHA1PRNG] took [188,975] milliseconds.
Feb 18, 2014 5:28:42 PM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory /usr/local/tomcat/apache-tomcat-7.0.50/webapps/examples
Feb 18, 2014 5:28:43 PM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory /usr/local/tomcat/apache-tomcat-7.0.50/webapps/manager
Feb 18, 2014 5:28:43 PM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory /usr/local/tomcat/apache-tomcat-7.0.50/webapps/ROOT
Feb 18, 2014 5:28:43 PM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory /usr/local/tomcat/apache-tomcat-7.0.50/webapps/docs
Feb 18, 2014 5:28:43 PM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["http-bio-8080"]
Feb 18, 2014 5:28:43 PM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["ajp-bio-8009"]
Feb 18, 2014 5:28:43 PM org.apache.catalina.startup.Catalina start
INFO: Server startup in 191154 ms
</pre>
SecureRandom部分で[188,975] millisecondsがかかっていますね。<br/><br/>
<strong>・対策(Tomcat起動時のJREの設定変更)</strong>
<br/>
<pre class="brush:bash">
# vi /etc/profile
#################
#java
#################
JAVA_HOME=/usr/local/java/current
JAVA_OPTS="-Djava.security.egd=file:/dev/./urandom"
#################
#tomcat
#################
CATALINA_HOME=/usr/local/tomcat/current
TOMCAT_USER=tomcat
export JAVA_HOME CATALINA_HOME TOMCAT_USER JAVA_OPTS
</pre>
既存の<code class="path">/etc/profile</code>に<code class="path">JAVA_OPTS</code>部分を追加しました。<br/><br/>
適応した後、確認<br/>
<pre class="brush:bash">
# source /etc/profile
# echo $JAVA_OPTS
-Djava.security.egd=file:/dev/./urandom
</pre>
<br/><br/>
問題なく出力されたら、<code class="path">daemon.sh</code>を修正して、環境ファイルのJAVA_OPTS設定を使うようにしましょう。<br/>
<pre class="brush:bash">
# vi /usr/local/tomcat/current/bin/daemon.sh
# Ensure that any user defined CLASSPATH variables are not used on startup,
# but allow them to be specified in setenv.sh, in rare case when it is needed.
CLASSPATH=
JAVA_OPTS="$JAVA_OPTS"
</pre>
122Lineの<code class="path">JAVA_OPTS=</code>を<code class="path">JAVA_OPTS="$JAVA_OPTS"</code>に修正しました。<br/><br/>
Tomcatの起動速度を確認すると以下のようになりました。<br/>
<pre class="brush:bash">
# /etc/init.d/tomcat stop
# /etc/init.d/tomcat start
Feb 19, 2014 10:12:59 AM org.apache.coyote.AbstractProtocol init
INFO: Initializing ProtocolHandler ["http-bio-8080"]
Feb 19, 2014 10:12:59 AM org.apache.coyote.AbstractProtocol init
INFO: Initializing ProtocolHandler ["ajp-bio-8009"]
Feb 19, 2014 10:12:59 AM org.apache.catalina.startup.Catalina load
INFO: Initialization processed in 910 ms
Feb 19, 2014 10:12:59 AM org.apache.catalina.core.StandardService startInternal
INFO: Starting service Catalina
Feb 19, 2014 10:12:59 AM org.apache.catalina.core.StandardEngine startInternal
INFO: Starting Servlet Engine: Apache Tomcat/7.0.50
Feb 19, 2014 10:12:59 AM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory /usr/local/tomcat/apache-tomcat-7.0.50/webapps/host-manager
Feb 19, 2014 10:13:00 AM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory /usr/local/tomcat/apache-tomcat-7.0.50/webapps/examples
Feb 19, 2014 10:13:00 AM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory /usr/local/tomcat/apache-tomcat-7.0.50/webapps/manager
Feb 19, 2014 10:13:01 AM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory /usr/local/tomcat/apache-tomcat-7.0.50/webapps/ROOT
Feb 19, 2014 10:13:01 AM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory /usr/local/tomcat/apache-tomcat-7.0.50/webapps/docs
Feb 19, 2014 10:13:01 AM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["http-bio-8080"]
Feb 19, 2014 10:13:01 AM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["ajp-bio-8009"]
Feb 19, 2014 10:13:01 AM org.apache.catalina.startup.Catalina start
INFO: Server startup in 2016 ms
</pre>
【参照したサイト】<br/>
<ul>
<li><a target="_blank" href="http://wiki.apache.org/tomcat/HowTo/FasterStartUp">How do I make Tomcat startup faster?</a></li>
</ul>
unknownhttp://www.blogger.com/profile/15190790785934095924noreply@blogger.com0tag:blogger.com,1999:blog-8771673127918263645.post-58001359453196518422014-02-18T21:24:00.000+09:002014-02-18T21:24:17.979+09:00Javaのインストール手順(jdk1.7.0_51)
<h2 class="sub_title">インストール環境とバージョン</h2>
今回、インストールするサーバとJavaのバージョンは以下のようになります。<br />
<table class="table_system_info01">
<tbody>
<tr>
<th>名前</th>
<th>バージョン</th>
<th>ダウンロード元</th>
</tr>
<tr>
<td class="td-subject">ubuntu</td>
<td>10.04.4(64bit)</td>
<td><a href="http://releases.ubuntu.com/lucid/" target="_blank" title="ubuntu-10.04.4">http://releases.ubuntu.com/lucid/</a></td>
</tr>
<tr>
<td class="td-subject">java(jdk)</td>
<td>1.7.0_51</td>
<td><a href="http://www.oracle.com/us/technologies/java/overview/index.html" target="_blank" title="java">http://www.oracle.com/us/technologies/java/overview/index.html</a></td>
</tr>
</tbody>
</table>
<h2 class="sub_title">
インストールする前の準備作業</h2>
開発パッケージが設置されてない場合は、<code class="path">apt-get</code>でインストールする必要があります。<br />
<pre class="brush:bash"># apt-get install build-essential curl libcurl3 libpcre3-dev libssl-dev libxml2-dev libbz2-dev libgd2-xpm-dev libmcrypt-dev
</pre>
<br/>
<h2 class="sub_title">JDKをインストールします</h2>
<pre class="brush:bash">
# mkdir -p /usr/local/java/
# cd /usr/local/src/
# wget http://download.oracle.com/otn-pub/java/jdk/7u51-b13/jdk-7u51-linux-x64.tar.gz --no-check-certificate --no-cookies --header "Cookie: gpw_e24=http%3A%2F%2Fwww.oracle.com"
# tar xvf jdk-7u51-linux-x64.tar.gz -C /usr/local/java/
# cd /usr/local/java/
# ln -s jdk1.7.0_51 current
</pre>
<br/>
JDKの環境ファイルを設定します。<br/>
<pre class="brush:bash">
# vi /etc/profile
JAVA_HOME=/usr/local/java/current
export JAVA_HOME
PATH=$PATH:$HOME/bin:$JAVA_HOME/bin
export PATH
# source /etc/profile
</pre>
<br/>
問題なく設置されたのか確認してみましょう。<br/>
<pre class="brush:bash">
# java -version
java version "1.7.0_51"
Java(TM) SE Runtime Environment (build 1.7.0_51-b13)
Java HotSpot(TM) 64-Bit Server VM (build 24.51-b03, mixed mode)
</pre>
<br/>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjWeJntgJoqOxIKiMuOUqA_t8l8dLbBKQW3tzDp4yRNnIMSRf4Bci4rtWqEjlkCnQnVhyphenhyphen23x901RXXLYqb5XFgTUIxRrD7vF19sAfJxPGF3LL4l-i3EaXOJn4fQCAQPQ8opH_O-QeZuniY/s1600/jdk.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjWeJntgJoqOxIKiMuOUqA_t8l8dLbBKQW3tzDp4yRNnIMSRf4Bci4rtWqEjlkCnQnVhyphenhyphen23x901RXXLYqb5XFgTUIxRrD7vF19sAfJxPGF3LL4l-i3EaXOJn4fQCAQPQ8opH_O-QeZuniY/s1600/jdk.png" /></a>unknownhttp://www.blogger.com/profile/15190790785934095924noreply@blogger.com0tag:blogger.com,1999:blog-8771673127918263645.post-55496269160297093792014-02-06T22:51:00.000+09:002014-02-25T15:28:49.170+09:00ZabbixでMysqlを監視する今回は、Mysqlサーバをリソース監視システム(Zabbix)でリソース・死活監視する方法について整理して見ました。<br/>
運用中のMysqlのリソースを監視し、パフォーマンスのチューニングポイントを見つけてみましょう。<br/>
<h2 class="sub_title">インストール環境とバージョン</h2>
今回、インストールするサーバとzabbixのバージョンは以下のようになります。<br />
<table class="table_system_info01">
<tbody>
<tr>
<th>名前</th>
<th>バージョン</th>
<th>ダウンロード元</th>
</tr>
<tr>
<td class="td-subject">ubuntu</td>
<td>10.04.4(64bit)</td>
<td><a href="http://releases.ubuntu.com/lucid/" target="_blank" title="ubuntu-10.04.4">http://releases.ubuntu.com/lucid/</a></td>
</tr>
<tr>
<td class="td-subject">ZABBIX</td>
<td>2.2.0</td>
<td><a href="http://www.zabbix.com/" target="_blank" title="zabbix-2.2.0">http://www.zabbix.com/</a></td>
</tr>
</tbody>
</table>
<h2 class="sub_title">Zabbix Serverインストール</h2>
「<a href="/2013/12/zabbix2.2.0-install-server.html" target="_blank" title="zabbix server">Zabbix Serverのインストール手順</a>」を参照してください。
<br />
<h2 class="sub_title">Zabbix Agentインストール</h2>
「<a href="/2014/01/zabbix-agent-install_16.html" target="_blank" title="zabbix agent">Zabbix Agentのインストール手順</a>」を参照してください。
<br />
※AgentサーバにはMysqlが設置されている状態です。<br />
<h2 class="sub_title">Mysqlインストール</h2>
「<a href="/2013/10/mysql-5614.html" target="_blank" title="mysql install">MySQL 5.6.16のインストール手順</a>」を参照してください。
<br />
<h2 class="sub_title">Zabbix Agent側での設定</h2>
<strong>1.mysqlにzabbix agentユーザ登録</strong><br/>
※パスワードは変更してください。<br/>
<pre class="brush:bash">
# mysql -uroot -p
mysql> grant process on *.* to 'zabbix_agent'@'localhost' identified by 'changeit';
Query OK, 0 rows affected (0.00 sec)
mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)
mysql> select host,user from mysql.user where user='zabbix_agent';
+-----------+--------------+
| host | user |
+-----------+--------------+
| localhost | zabbix_agent |
+-----------+--------------+
1 row in set (0.00 sec)
</pre>
<br/>
<strong>2.mysqlに接続するID/PWファイル生成</strong><br/>
<code class="path">zabbix_my.cnf</code>というファイルを生成し、ファイルの権限を変更します。<br/>
<pre class="brush:bash">
# vi /usr/local/etc/zabbix_my.cnf
[client]
user = zabbix_agent
password = changeit
# chmod 640 /usr/local/etc/zabbix_my.cnf
# chown zabbix:zabbix /usr/local/etc/zabbix_my.cnf
</pre>
<br/>
<strong>3.mysqlからstatus情報を取得するShell作成</strong><br/>
Mysqlの<code class="path">show global status</code>,<code class="path">show engine innodb status</code>から情報を取得するためにShellを作成します。<br/>
※他のstatus情報も必要な場合は<code class="path">$1=="Bytes_sent" { print "Bytes_sent", $2 }</code>部分を追加してください。<br/>
<pre class="brush:bash">
# vi /usr/local/etc/mysql_stat_zabbix.sh
#!/bin/sh
mycnf_path=/usr/local/etc/zabbix_my.cnf
echo_sql() {
cat <<'EOF'
show global status;
show engine innodb status\G
EOF
}
echo_sql | mysql --defaults-extra-file=$mycnf_path | sed -e "s/------- TRX HAS BEEN WAITING/Trx_waiting/g" | awk '
BEGIN{w_time_sum=0} {if($1=="Trx_waiting") w_time_sum += $2 } END{print "Trx_waiting", w_time_sum}
$1=="Bytes_received" { print "Bytes_received", $2 }
$1=="Bytes_sent" { print "Bytes_sent", $2 }
$1=="Com_insert" { print "Com_insert", $2 }
$1=="Com_select" { print "Com_select", $2 }
$1=="Com_update" { print "Com_update", $2 }
$1=="Com_delete" { print "Com_delete", $2 }
$1=="Threads_connected" { print "Threads_connected", $2 }
$1=="Threads_running" { print "Threads_running", $2 }
/^Buffer pool hit rate [0-9]+ \/ [0-9]+/ {
print "Buffer_pool_hit_rate", $5 / $7
}
/^[0-9.]+ inserts\/s, [0-9.]+ updates\/s, [0-9.]+ deletes\/s, [0-9.]+ reads\/s/ {
print "insertsPerSec", $1
print "updatesPerSec", $3
print "deletesPerSec", $5
print "readsPerSec", $7
}
'
# chown zabbix:zabbix /usr/local/etc/mysql_stat_zabbix.sh
# chmod 700 /usr/local/etc/mysql_stat_zabbix.sh
</pre>
<br/>
<strong>4.zabbix agentのUserParameterの設定する。</strong><br/>
zabbix agentの設定ファイルを修正します。<br/>
<pre class="brush:bash">
# vi /usr/local/etc/zabbix_agentd.conf
コメントアウト解除
Include=/usr/local/etc/zabbix_agentd.conf.d/
</pre>
<br/>
Mysqlから情報を取得するUserParameterを追加します。<br/>
<pre class="brush:bash">
# vi /usr/local/etc/zabbix_agentd.conf.d/custom_mysql.conf
UserParameter=mysql.max_connections[*],/usr/local/bin/mysqladmin --defaults-extra-file=/usr/local/etc/zabbix_my.cnf variables|grep max_connections| awk '{print $$4}'
UserParameter=mysql.threads_connected[*],/usr/local/bin/mysqladmin --defaults-extra-file=/usr/local/etc/zabbix_my.cnf extended-status|grep Threads_connected| awk '{print $$4}'
UserParameter=mysql.threads_created[*],/usr/local/bin/mysqladmin --defaults-extra-file=/usr/local/etc/zabbix_my.cnf extended-status|grep Threads_created| awk '{print $$4}'
UserParameter=mysql.threads_running[*],/usr/local/bin/mysqladmin --defaults-extra-file=/usr/local/etc/zabbix_my.cnf extended-status|grep Threads_running| awk '{print $$4}'
UserParameter=mysql.thread_cache_size[*],/usr/local/bin/mysqladmin --defaults-extra-file=/usr/local/etc/zabbix_my.cnf variables|grep thread_cache_size| awk '{print $$4}'
UserParameter=mysql.connections[*],/usr/local/bin/mysqladmin --defaults-extra-file=/usr/local/etc/zabbix_my.cnf extended-status|grep Connections| awk '{print $$4}'
UserParameter=mysql.query_per_sec_avg[*],/usr/local/bin/mysqladmin --defaults-extra-file=/usr/local/etc/zabbix_my.cnf status|awk '{print $$22}'
UserParameter=mysql.status[*],/usr/local/bin/mysqladmin --defaults-extra-file=/usr/local/etc/zabbix_my.cnf extended-status |grep -w $1 | awk '{print $$4}'
UserParameter=mysql.innodb.status[*],/usr/local/etc/mysql_stat_zabbix.sh | grep -w $1 | awk '{print $$2}'
#max_connections:これまでに記録された同時接続数の最大値
#Threads_connected:現在開いている接続の数
#thread_cache_size:接続を処理するために生成されたスレッド数。起動してから生成されたスレッドの数。この値が大きい場合はthread_cache_sizeの値を大きくした方が良いかも。
#Threads_running:スリープ状態になっていないスレッド数
#thread_cache_size:スレッドキャッシュでキャッシュされているスレッドの数。
#Queries per second avg:問い合わせ平均応答秒数
</pre>
<br/>
zabbix agentを再起動します。<br/>
<pre class="brush:bash">
# /etc/init.d/zabbix-agent restart
</pre>
<h2 class="sub_title">Zabbix Serverでの確認</h2>
zabbix-agentで設定した内容が問題なく取得できているのか確認してみましょう。<br/>
<pre class="brush:bash">
# zabbix_get -s 192.168.56.102 -k mysql.innodb.status[Trx_waiting]
0
# zabbix_get -s 192.168.56.102 -k mysql.max_connections
300
</pre>
<br/>
結果が問題なく返ってくると正常です。<br/>
<code class="path">zabbix_get</code>を設置する方法については以下のページの【zabbix-getのInstall】部分をご参照ください。<br/>
<a href="/2013/12/zabbix2.2.0-install-server.html" target="_blank" title="zabbix server 2.2" target="_blank">Zabbix Server2.2.0のインストール手順</a>
<br/><br/>
<h2 class="sub_title">ZabbixのWEB管理ページでの設定</h2>
<strong>1.テンプレートをダウンロードする</strong><br/>
テンプレートは以下のページでダウンロードしてください。<br/>
・<a href="https://sites.google.com/site/kongbab04/file/Template_JP_App_MySQL.xml?attredirects=0&d=1" title="Template_JP_App_mysql">Template_JP_App_mysql</a><br/>
※こちらのファイルはhttp://www.zabbix.jp/のテンプレートを基に修正したファイルになります。<br/>
<br/>
<strong>2.テンプレートを管理画面にインポートする</strong><br/>
<code class="path">設定</code>⇒<code class="path">テンプレート</code>⇒<code class="path">インポート</code>ページにてダウンロードした【Template_JP_App_mysql】ファイルをインポートしてください。<br/><br/>
<br/>
<strong>3.ホストにテンプレート追加</strong><br/>
<code class="path">設定</code>⇒<code class="path">ホスト</code>⇒<code class="path">監視対象の設定ページ(名前の部分を押下)</code>⇒<code class="path">テンプレートタブ</code><br/>
上記のページにて【Template_JP_App_MySQL】を追加してください。<br/>
<br/>
<strong>4.グラフの確認</strong><br/>
ここまで、問題なく設定ができたら、グラフページにて7つのグラフがご確認いただけると思います。<br/>
<code class="path">監視データ</code>⇒<code class="path">グラフ</code><br/>
<blockquote>
MySQL Command Counters<br/>
MySQL Connections<br/>
MySQL Handlers<br/>
MySQL InnoDB Current Lock Waits<br/>
MySQL Select Types<br/>
MySQL Threads<br/>
MySQL Transaction Handler<br/>
</blockquote><br/>
※グラフの色などは自由に変更してください。<br/>
<br/><br/>
<h2 class="sub_title">MySQLのチューニングポイント</h2>
<strong>・SQL の種類を確認する MySQL Command Counters</strong><br/>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjn-urwrKStLt6ji06FrRR7zrKpvIDwAVJRwk2dAFEZYvZ0pbRpkWrH5_T7MvmSuFX8ERcm6Gdufpdcbt6oumfcVXbT7hRgkOhFIIjDqbQtAUEatL9zGGFGqZwZ0uAbl64nhrDJm1E12ps/s1600/commandCounters.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjn-urwrKStLt6ji06FrRR7zrKpvIDwAVJRwk2dAFEZYvZ0pbRpkWrH5_T7MvmSuFX8ERcm6Gdufpdcbt6oumfcVXbT7hRgkOhFIIjDqbQtAUEatL9zGGFGqZwZ0uAbl64nhrDJm1E12ps/s1600/commandCounters.png" /></a><br/>
Com は Command の略で Com Select / Delete / Insert / Update / Replace はその名前のとおりの SQL の実行回数です。 Com xxx Multi と付いているのは複数テーブルを一括して Update するMySQL 独特の構文です。<br/>
QuestionsはQuestionsはMySQL Serverが発行したクエリの総数で、SET等の補助的なコマンドとエラーの応答もカウントされます。<br/>
Questionsだけが増加して来たら、サーバ側で何かのエラーを起こしている可能性が高いそうです。
<code class="path">SET @key := '1'</code>
<br/><br/>
<strong>・ロック待ち時間が確認できる InnoDB Current Lock Waits</strong><br/>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEifRvvw57Dg0F8Y2rAX24f2QJ9f1h10eZiRZ4Il3Sr-GKUeoNc9aHZ23u-PeoLp40FF1y-OvmwP55NKbK1OrBmZHPAGQ9UUMaRwZq5HY-dX44fS5r_RRQa5XzEEXHD1NhwN7t6MYEj8gEk/s1600/lockWaits.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEifRvvw57Dg0F8Y2rAX24f2QJ9f1h10eZiRZ4Il3Sr-GKUeoNc9aHZ23u-PeoLp40FF1y-OvmwP55NKbK1OrBmZHPAGQ9UUMaRwZq5HY-dX44fS5r_RRQa5XzEEXHD1NhwN7t6MYEj8gEk/s1600/lockWaits.png" /></a><br/>
SHOW ENGINE INNODB STATUSで表示される<code class="path">TRANSACTIONS</code>情報のうち、ロックの時間が記録されております<code class="path">TRX HAS BEEN WAITING 【秒】 SEC FOR THIS LOCK TO BE GRANTED</code>の秒数の合計値で、InnoDBのテーブルもしくは行のロックがかかった時に表示されます。<br/>
該当の数値が増えた場合は<code class="path">SHOW FULL PROCESSLIST;</code>もしくは<code class="path">slow queryログ</code>等で、どの部分でロックがかかっているのか確認し、対応する必要があります。<br/><br/>
<strong>・トランザクション状況が分かる MySQL Transaction Handler</strong><br/>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEggmWd2IwRCHpk76N6y3kzMV80LGoPWi3nC9Ihnlh8eyXwrHQW9ByOnfNlBDsV9axyBi9riMmO5fyLyxfVerIkYR0gH50uHnir-mKMX-ZlsjdSR2L3lTdtLxJe_9OaBbhhxxLhnSSkGTu8/s1600/transactionHandler.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEggmWd2IwRCHpk76N6y3kzMV80LGoPWi3nC9Ihnlh8eyXwrHQW9ByOnfNlBDsV9axyBi9riMmO5fyLyxfVerIkYR0gH50uHnir-mKMX-ZlsjdSR2L3lTdtLxJe_9OaBbhhxxLhnSSkGTu8/s1600/transactionHandler.png" /></a>
<br/>
このグラフはトランザクションの完了、ロールバック数を表します。<br/>
ロールバックの現状を通じてクエリのエラーとDeadlockも予測できます。<br/>
<br/>
<strong>・SELECTの実行計画が確認できる MySQL Select Types</strong><br/>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEho0R99iG3M_GGOA_ljc6BC4PLBkVCEuZyx_UkX9G_HQREiREUS-OdG6cicDoIbKC7LA-9eb5tR_jbxhICN6Pzp6XqKMTZxqyt_oVoSHrB3eZs17qRDsBlWnoGsem8F9z131aRnFZTa3XI/s1600/1.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEho0R99iG3M_GGOA_ljc6BC4PLBkVCEuZyx_UkX9G_HQREiREUS-OdG6cicDoIbKC7LA-9eb5tR_jbxhICN6Pzp6XqKMTZxqyt_oVoSHrB3eZs17qRDsBlWnoGsem8F9z131aRnFZTa3XI/s1600/1.png" /></a><br/>
このグラフは個別クエリに対してEXPLAINすることで、どの実行計画を使っているのかの確認が出来ます。<br/>
Select_full_join:2つ以上のテーブルにおいて全件同士で(Indexを使わずに)JOINした回数。最も致命的。<br/>
Select_full_range_join:片方のテーブルで全件、もう片方のテーブルで範囲検索を行ってJOINした回数。<br/>
Select_scan:テーブルのデータを全件検索した回数。<br/>
Select Range:範囲が限定された探索(WHERE,HAVINGなど)を行った回数。<br/>
<br/>
<strong>・クエリの I/O 動作を知ることが出来るグラフ MySQL Handlers</strong><br/>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSHG8xRfWXqcXY3nIRaE9dksaKhVbzpA-30EHyMw2MabLXz6zHI_CIfbbW94olKElaaxInTl1jQzSq12VrPx-Gae2vDocXAqWZZJZGnKgLISDahdnEsfHohrc9Qukyr-waf6s9h7iDnA0/s1600/Handlers.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSHG8xRfWXqcXY3nIRaE9dksaKhVbzpA-30EHyMw2MabLXz6zHI_CIfbbW94olKElaaxInTl1jQzSq12VrPx-Gae2vDocXAqWZZJZGnKgLISDahdnEsfHohrc9Qukyr-waf6s9h7iDnA0/s1600/Handlers.png" /></a><br/>
MySQLクエリ実行後ストレジエンジンAPIを通じて発生しているFileやDisk I/Oの確認が出来ます。<br/><br/>
<ul>
<li>Handler Read First : インデックスから最初のエントリーが読み込まれた回数。【Full Index Scanした回数】この値が大きい場合は、サーバがインデックスのフルスキャンを多く行っているという -> チューニング必要</li>
<li>Handler Read Key : キーに基づくレコード読み取り要求の回数。この値が大きい場合、クエリおよびテーブルが適切にインデックス化されていると考えられる。</li>
<li>Handler Read Next : キー値に基づいて行を特定した後、後続の行を読んだ回数</li>
<li>Handler Read Prev : キー順序での前のレコードの読み取り要求の回数。これは主に、ORDER BY ... DESC を最適化するのに使用される。</li>
<li>Handler Read Rnd : 固定位置に基づくレコード読み取り要求の回数。 結果のソートを必要とするクエリを多く実行すると、この値が大きくなる。</li>
<li>Handler Read Rnd Next : データファイルでの次のレコードの読み取り要求の回数。 テーブルスキャンが多く実行されると、この値が大きくなる。この場合、一般的に、テーブルが適切にインデックス化されていないか、クエリがインデックスを有効に利用していないかを意味する。 -> チューニング必要</li>
</ul>
<br/><br/>
【参照したサイト】<br/>
<ul>
<li><a target="_blank" href="http://www.percona.com/software/percona-monitoring-plugins/">percona-monitoring-plugins</a></li>
<li><a target="_blank" href="http://k-1-ne-jp.blogspot.jp/2012/12/mysql.html">MySQLの監視テンプレートを適用する</a></li>
<li><a target="_blank" href="http://www.infiniteloop.co.jp/blog/2012/03/mysql-tuning-cacti-query/">これだけ見れば大丈夫!ーMySQLパフォーマンス監視のツボ(クエリ編)</a></li>
<li><a target="_blank" href="http://qiita.com/hnakamur/items/f1f3393a4d8eb75fb185">Zabbixでmysqlをモニタリングするスクリプト</a></li>
</ul>
<br/>unknownhttp://www.blogger.com/profile/15190790785934095924noreply@blogger.com0tag:blogger.com,1999:blog-8771673127918263645.post-43506465512258463082014-01-27T23:35:00.000+09:002014-01-28T14:12:08.445+09:00Zabbixで物理メモリサイズ(%)取得今回は、リソース監視システム(Zabbix)を利用してAgentサーバの現在利用中の物理メモリのサイズを取得する方法について整理してみました。
<h2 class="sub_title">インストール環境とバージョン</h2>
今回、インストールするサーバとzabbixのバージョンは以下のようになります。<br />
<table class="table_system_info01">
<tbody>
<tr>
<th>名前</th>
<th>バージョン</th>
<th>ダウンロード元</th>
</tr>
<tr>
<td class="td-subject">ubuntu</td>
<td>10.04.4(64bit)</td>
<td><a href="http://releases.ubuntu.com/lucid/" target="_blank" title="ubuntu-10.04.4">http://releases.ubuntu.com/lucid/</a></td>
</tr>
<tr>
<td class="td-subject">ZABBIX</td>
<td>2.2.0</td>
<td><a href="http://www.zabbix.com/" target="_blank" title="zabbix-2.2.0">http://www.zabbix.com/</a></td>
</tr>
</tbody>
</table>
<h2 class="sub_title">Zabbix Serverインストール</h2>
「<a href="/2013/12/zabbix2.2.0-install-server.html" title="zabbix server">Zabbix Serverのインストール手順</a>」を参照してください。
<br />
<h2 class="sub_title">Zabbix Agentインストール</h2>
「<a href="/2014/01/zabbix-agent-install_16.html" title="zabbix agent">Zabbix Agentのインストール手順</a>」を参照してください。
<br />
<h2 class="sub_title">ZabbixのWEB管理ページでの設定</h2>
<strong>1.物理メモリを取得するためにテンプレート(Template OS Linux)にアイテムを登録します。</strong><br/>
<code class="path">設定</code>⇒<code class="path">テンプレート</code>⇒<code class="path">テンプレート(Template OS Linux)のアイテム</code>⇒<code class="path">アイテムの作成</code><br/>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgCMg4MKK_L0-aWj4mP6JueH_43t7AHfP2azW6J67R25hGzgovIG8mm3iPgrmmNmTpV2pwhG3qsUYXm0bVOx01sUeSNJYto8AaoJW9dNFPijSBa3bx5GIH8e2wFuACoQCHdtD-zu6peLLg/s1600/1.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgCMg4MKK_L0-aWj4mP6JueH_43t7AHfP2azW6J67R25hGzgovIG8mm3iPgrmmNmTpV2pwhG3qsUYXm0bVOx01sUeSNJYto8AaoJW9dNFPijSBa3bx5GIH8e2wFuACoQCHdtD-zu6peLLg/s1600/1.png" /></a>
<br/><br/>
2つアイテムの作成します。</br>
<pre class="brush:java">
名前:physical memory free size
タイプ:Zabbixエージェント
キー:vm.memory.size[free]
データ型:数値 (整数)
データの形式:10進数
名前:physical memory pused
タイプ:計算
キー:vm.memory.size[pused]
式:100*(last("vm.memory.size[total]")-last("vm.memory.size[free]"))/last("vm.memory.size[total]")
データ型:数値 (浮動小数)
単位:%
</pre>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjnROUOSESPBVOa0ay_Xn9v9uWcZfulrMTVMJS7hdBDcd97vGvNxde-phFVHUHvBEYjtFxK2PJkNAfMmnIwJ0wzk47BNmoU4l3F3QMHXlBysqQOkbVUcdACUhbHDxKF7pLqlZkHt4R8Muw/s1600/2.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjnROUOSESPBVOa0ay_Xn9v9uWcZfulrMTVMJS7hdBDcd97vGvNxde-phFVHUHvBEYjtFxK2PJkNAfMmnIwJ0wzk47BNmoU4l3F3QMHXlBysqQOkbVUcdACUhbHDxKF7pLqlZkHt4R8Muw/s1600/2.png" /></a><br/>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgw0sM0FqN1YoI5k9u6GJAEg6_Bf1PjuDTXBynij0IH3W823NQ38tdsC6eDX4NTWplnTjmq3jjB90s-w3BhUOIie-5rcIHR7gNVY0x8jxKL_hEJbfxTgdjH8YAdn_AhvDRgdHASAFPZLBI/s1600/3.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgw0sM0FqN1YoI5k9u6GJAEg6_Bf1PjuDTXBynij0IH3W823NQ38tdsC6eDX4NTWplnTjmq3jjB90s-w3BhUOIie-5rcIHR7gNVY0x8jxKL_hEJbfxTgdjH8YAdn_AhvDRgdHASAFPZLBI/s1600/3.png" /></a><br/>
<br/>
<strong>2.テンプレートのグラフを作成します。</strong></br>
<code class="path">設定</code>⇒<code class="path">テンプレート</code>⇒<code class="path">テンプレート(Template OS Linux)のグラフ</code>⇒<code class="path">グラフの作成</code><br/>
先ほど登録したアイテムを表示するグラフを作成します。<br/>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgP4sA9FxkedbyK5N9smpIhnpndRjkvj2Pl93OP9lQcmgcDuSf8VRxlMnjejLKnTlzgifHiWKP9knwxjpmd4rhXxCjtcYzTGCV0pjO2EBWC8LyVkdNzKxR9NNJensABN-a83Tgjm-DV4vs/s1600/4.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgP4sA9FxkedbyK5N9smpIhnpndRjkvj2Pl93OP9lQcmgcDuSf8VRxlMnjejLKnTlzgifHiWKP9knwxjpmd4rhXxCjtcYzTGCV0pjO2EBWC8LyVkdNzKxR9NNJensABN-a83Tgjm-DV4vs/s1600/4.png" /></a><br/>
<br/>
<strong>3.アイテム&グラフを確認してみましょう。</strong></br>
・アイテムを確認する。
<code class="path">監視データ</code>⇒<code class="path">最新データ</code>⇒<code class="path">メモリ</code><br/>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjH_1SkZzA1k1eZkLuwMjZe0FavC7j3aE7IQzTcbwO91ezSButV0iorwFjK2Symo3iOt7ASaobwLpaNplD7e-BIg1ajbRaVWV6pOcUQbGX9IYf5qEFd5QQ4My8TykESO4EqokQV2YaAuko/s1600/22.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjH_1SkZzA1k1eZkLuwMjZe0FavC7j3aE7IQzTcbwO91ezSButV0iorwFjK2Symo3iOt7ASaobwLpaNplD7e-BIg1ajbRaVWV6pOcUQbGX9IYf5qEFd5QQ4My8TykESO4EqokQV2YaAuko/s1600/22.png" /></a><br/><br/>
・グラフを確認する。
<code class="path">監視データ</code>⇒<code class="path">グラフ</code><br/>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgEg5QjObXnv0N9YRmhLd8sotkEfY69hphIo0gkb9mNuybyE4yN0_mqrnc_yOzYLSdXt5UvsTJ9z8SzGlGG4ToVZGBB_DfjAsIgcSNrgJPq8hvr_FQH3v2-URSPcbIVXazOA30UWZh9bRM/s1600/11.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgEg5QjObXnv0N9YRmhLd8sotkEfY69hphIo0gkb9mNuybyE4yN0_mqrnc_yOzYLSdXt5UvsTJ9z8SzGlGG4ToVZGBB_DfjAsIgcSNrgJPq8hvr_FQH3v2-URSPcbIVXazOA30UWZh9bRM/s1600/11.png" /></a><br/><br/>
※今回設定したアイテムとグラフは【Template OS Linux】テンプレートに登録しましたので<br/>
監視対象(HOST)に【Template OS Linux】テンプレートを追加する必要があります。<br/>
追加する方法は以下のようになります。<br/>
<code class="path">設定</code>⇒<code class="path">ホスト</code>⇒<code class="path">監視対象の設定ページ(名前の部分を押下)</code>⇒<code class="path">テンプレートタブ</code><br/>
上記のページにて【Template OS Linux】を追加してください。<br/>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcbwDiqYQuvr9e-ujK7bYcVXe9NzCbCOezAzTv-oXg8QUdXrqnbatxBMnpG1PA9YRnRdswhbtmowaZgHr2id-SrFTCqUXEz3sU7fc61c_e_Z32Wwt3Q4q9co7O98407jbZ18PbT7t7HFw/s1600/33.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcbwDiqYQuvr9e-ujK7bYcVXe9NzCbCOezAzTv-oXg8QUdXrqnbatxBMnpG1PA9YRnRdswhbtmowaZgHr2id-SrFTCqUXEz3sU7fc61c_e_Z32Wwt3Q4q9co7O98407jbZ18PbT7t7HFw/s1600/33.png" /></a><br/>
unknownhttp://www.blogger.com/profile/15190790785934095924noreply@blogger.com0tag:blogger.com,1999:blog-8771673127918263645.post-88329943479251911412014-01-21T21:30:00.000+09:002015-03-11T14:22:44.593+09:00ZabbixでLinuxのHard Disk I/O監視
<h2 class="sub_title">インストール環境とバージョン</h2>
今回、インストールするサーバとzabbixのバージョンは以下のようになります。<br />
<table class="table_system_info01">
<tbody>
<tr>
<th>名前</th>
<th>バージョン</th>
<th>ダウンロード元</th>
</tr>
<tr>
<td class="td-subject">ubuntu</td>
<td>10.04.4(64bit)</td>
<td><a href="http://releases.ubuntu.com/lucid/" target="_blank" title="ubuntu-10.04.4">http://releases.ubuntu.com/lucid/</a></td>
</tr>
<tr>
<td class="td-subject">ZABBIX</td>
<td>2.2.0</td>
<td><a href="http://www.zabbix.com/" target="_blank" title="zabbix-2.2.0">http://www.zabbix.com/</a></td>
</tr>
</tbody>
</table>
<h2 class="sub_title">Zabbix Serverインストール</h2>
「<a href="/2013/12/zabbix2.2.0-install-server.html" title="zabbix server">Zabbix Serverのインストール手順</a>」を参照してください。
<br />
<h2 class="sub_title">Zabbix Agentインストール</h2>
「<a href="/2014/01/zabbix-agent-install_16.html" title="zabbix agent">Zabbix Agentのインストール手順</a>」を参照してください。
<br />
<h2 class="sub_title">Zabbix Agent側での設定</h2>
UserParameterを設定するconfファイルを作成します。
<pre class="brush:bash">
# vi /usr/local/etc/zabbix_agentd.conf
コメントアウト解除
Include=/usr/local/etc/zabbix_agentd.conf.d/
confファイル作成
# vi /usr/local/etc/zabbix_agentd.conf.d/custom_hdd.conf
### DISK I/O###
UserParameter=custom.vfs.dev.read.ops[*],cat /proc/diskstats | egrep $1 | head -1 | awk '{print $$4}'
UserParameter=custom.vfs.dev.read.ms[*],cat /proc/diskstats | egrep $1 | head -1 | awk '{print $$7}'
UserParameter=custom.vfs.dev.write.ops[*],cat /proc/diskstats | egrep $1 | head -1 | awk '{print $$8}'
UserParameter=custom.vfs.dev.write.ms[*],cat /proc/diskstats | egrep $1 | head -1 | awk '{print $$11}'
UserParameter=custom.vfs.dev.io.active[*],cat /proc/diskstats | egrep $1 | head -1 | awk '{print $$12}'
UserParameter=custom.vfs.dev.io.ms[*],cat /proc/diskstats | egrep $1 | head -1 | awk '{print $$13}'
UserParameter=custom.vfs.dev.read.sectors[*],cat /proc/diskstats | egrep $1 | head -1 | awk '{print $$6}'
UserParameter=custom.vfs.dev.write.sectors[*],cat /proc/diskstats | egrep $1 | head -1 | awk '{print $$10}'
### DISK I/O###
</pre>
<br/>
Zabbix Agentを再起動します。<br/>
<pre class="brush:bash">
# /etc/init.d/zabbix-agent restart
</pre>
<br/>
監視するディスクの名前を確認しておきましょう。<br/>
<pre class="brush:bash">
# fdisk -l
Disk /dev/sda: 8589 MB, 8589934592 bytes # <- /dev/sdaがディスク名です。
255 heads, 63 sectors/track, 1044 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00000b36
Device Boot Start End Blocks Id System
/dev/sda1 * 1 32 248832 83 Linux
Partition 1 does not end on cylinder boundary.
/dev/sda2 32 1045 8136705 5 Extended
/dev/sda5 32 1045 8136704 8e Linux LVM
</pre>
<br/>
<h2 class="sub_title">Zabbix Server側での確認</h2>
まず、Zabbix Agentが問題なく設定できているのか確認します。
<pre class="brush:bash">
コマンドは以下のような形式になります。
zabbix_get -s HostName -p 10050 -k custom.vfs.dev.write.ops[Disk Name]
# zabbix_get -s 192.168.56.102 -p 10050 -k custom.vfs.dev.write.ops[sda]
947
</pre>
コマンドを実行すると「947」などの数字が出ると正常です。<br/>
以下のようなエラーが発生した場合は、<code class="path">zabbix_get</code>を設置してください。<br/>
<pre class="brush:bash">
# zabbix_get -s 192.168.56.102 -p 10050 -k custom.vfs.dev.write.ops[sda]
The program 'zabbix_get' can be found in the following packages:
* zabbix-server-mysql
* zabbix-server-pgsql
Try: apt-get install <selected package>
</pre>
zabbix-getをInstallする方法につきましては以下のURLの<code class="path">zabbix-getのInstall</code>部分をご参照ください。<br/>
<a href="/2013/12/zabbix2.2.0-install-server.html" title="zabbix server 2.2" target="_blank">Zabbix Server2.2.0のインストール手順</a><br/>
<h2 class="sub_title">ZabbixのWEB管理ページでの設定</h2>
Agent側に登録した<code class="path">UserParameter</code>を使用するためには管理画面にアイテムなどを登録する必要があります。<br/>
<br/>
<strong>・テンプレートXMLを利用してアイテム登録</strong><br/>
以下のテンプレートファイルをダウンロードし、管理画面にインポートします。<br/>
テンプレートXML:<a href="https://sites.google.com/site/kongbab04/file/zbx_export_templates.xml" title="hdd io template">zbx_export_templates</a><br/><br/>
インポートする個所は下記のようになります。<br/>
管理画面の<code class="path">管理</code>⇒<code class="path">テンプレート</code>⇒<code class="path">インポート</code><br/><br/>
テンプレートをインポートした後、<br/>
<code class="path">管理</code>⇒<code class="path">ホスト</code>⇒<code class="path">登録したホストの設定ページ</code>⇒<code class="path">テンプレートTAB</code>で、インポートしたテンプレート<code class="path">Service Check IOstat</code>を追加してください。<br/>
追加すると
<code class="path">管理</code>⇒<code class="path">ホスト</code>⇒<code class="path">登録したホストのアイテム</code>ページにて確認が出来ます。
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiAkT4JFvfcZ_Q_AXXQr-2xEk5Z6zTj6epSpEAGZNebOsh9efW3rIuGF59vecLt2p704r67hkBJmjl1BWOFLtMQvc0gbHj9FXsVB5B3hgtc-ii7BZTvCg7f8QWtzPAu4hWBmakqdv7EA0E/s1600/1.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiAkT4JFvfcZ_Q_AXXQr-2xEk5Z6zTj6epSpEAGZNebOsh9efW3rIuGF59vecLt2p704r67hkBJmjl1BWOFLtMQvc0gbHj9FXsVB5B3hgtc-ii7BZTvCg7f8QWtzPAu4hWBmakqdv7EA0E/s1600/1.png" /></a><br/><br/>
※テンプレートXMLをインポートせずに、<code class="path">登録したホストのアイテム</code>ページにて直接アイテムを登録することも可能です。<br/>
<code class="path">管理</code>⇒<code class="path">ホスト</code>⇒<code class="path">登録したホストのアイテム</code>⇒<code class="path">アイテムの作成</code><br/>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7ivm4cUlYurg_y0UPMTO2SjOpc7Bv_1Ra1HQXGjsWVv32eJ6HCgQKsZvKGFfHQZKZV1ug9dgfQL1L3sY_rmh8jIiBtJKqOiyd3I9XXaCqxUSQuu21aEl4pcj5X3CUhnZqOIXyxCJU8Xc/s1600/3.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7ivm4cUlYurg_y0UPMTO2SjOpc7Bv_1Ra1HQXGjsWVv32eJ6HCgQKsZvKGFfHQZKZV1ug9dgfQL1L3sY_rmh8jIiBtJKqOiyd3I9XXaCqxUSQuu21aEl4pcj5X3CUhnZqOIXyxCJU8Xc/s1600/3.png" /></a><br/>
<h2 class="sub_title">管理画面のグラフで確認</h2>
管理画面の
<code class="path">監視データ</code>⇒<code class="path">グラフもしくは最新データ</code>ページにて追加したテンプレート<code class="path">IO Stat</code>項目の確認が出来ます。<br/>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjOKI4trycauTd7MAdm8CF3ptLWM1IbyQGkUFh0HIa75u5xG977G2ggvoqR6Dvpz5PhF97prum_LxSaAjZrunrPjCOKyo1QRj1Hf2pdyOZSpV04K67HIqt1iY1wiwe0WgF1GaX7MlljKnw/s1600/2.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjOKI4trycauTd7MAdm8CF3ptLWM1IbyQGkUFh0HIa75u5xG977G2ggvoqR6Dvpz5PhF97prum_LxSaAjZrunrPjCOKyo1QRj1Hf2pdyOZSpV04K67HIqt1iY1wiwe0WgF1GaX7MlljKnw/s1600/2.png" /></a><br/>
<br/><br/>
以下のサイトを参照しました。<br/>
・<a href="http://rals-madlab.blogspot.jp/2013/07/in-spirit-of-zabbix-and-good-monitoring.html" target="_blank">http://rals-madlab.blogspot.jp/2013/07/in-spirit-of-zabbix-and-good-monitoring.html</a><br/>unknownhttp://www.blogger.com/profile/15190790785934095924noreply@blogger.com0tag:blogger.com,1999:blog-8771673127918263645.post-69255895019637231542014-01-16T23:50:00.000+09:002014-01-22T09:56:41.430+09:00Zabbix Agentのインストール手順
<h2 class="sub_title">インストール環境とバージョン</h2>
今回、インストールするサーバとzabbix-agentのバージョンは以下のようになります。<br />
<table class="table_system_info01">
<tbody>
<tr>
<th>名前</th>
<th>バージョン</th>
<th>ダウンロード元</th>
</tr>
<tr>
<td class="td-subject">ubuntu</td>
<td>10.04.4(64bit)</td>
<td><a href="http://releases.ubuntu.com/lucid/" target="_blank" title="ubuntu-10.04.4">http://releases.ubuntu.com/lucid/</a></td>
</tr>
<tr>
<td class="td-subject">ZABBIX</td>
<td>2.2.0</td>
<td><a href="http://www.zabbix.com/" target="_blank" title="zabbix-2.2.0">http://www.zabbix.com/</a></td>
</tr>
</tbody>
</table>
<h2 class="sub_title">
インストールする前の準備作業</h2>
開発パッケージが設置されてない場合は、<code class="path">apt-get</code>でインストールする必要があります。<br />
<pre class="brush:bash"># apt-get install build-essential curl libcurl3 libpcre3-dev libssl-dev libxml2-dev libbz2-dev libgd2-xpm-dev libmcrypt-dev
</pre>
<h2 class="sub_title">Zabbix-agentをインストールします</h2>
<pre class="brush:bash">
# groupadd zabbix
# useradd -g zabbix -s /bin/false -M zabbix
# cd /usr/local/src
# wget -O 'zabbix-2.2.0.tar.gz' http://downloads.sourceforge.net/project/zabbix/ZABBIX%20Latest%20Stable/2.2.0/zabbix-2.2.0.tar.gz?r=http%3A%2F%2Fwww.zabbix.com%2Fjp%2Fdownload.php&ts=1387170751&use_mirror=jaist
# tar xvf zabbix-2.2.0.tar.gz
# cd zabbix-2.2.0
# ./configure --enable-agent
# make
# make install
</pre>
<br/>
その他、設定ファイルを配置します。<br/>
<pre class="brush:bash">
# mkdir /var/log/zabbix
# chown zabbix:zabbix /var/log/zabbix
# cp misc/init.d/debian/zabbix-agent /etc/init.d
# cp conf/zabbix_agentd.conf /usr/local/etc/zabbix_agentd.conf
</pre>
<br/>
zabbix_agentd.confの設定ファイルを編集します。<br/>
<pre class="brush:bash">
# vi /usr/local/etc/zabbix_agentd.conf
~省略~
LogFile=/var/log/zabbix/zabbix_agentd.log
LogFileSize=100
# Server=Zabbix Serverがインストールされたサーバの「IPアドレスもしくはサーバのホスト名」
Server=192.168.56.101
# ServerActive=Zabbix Serverがインストールされたサーバの「IPアドレス:Port番号もしくはサーバのホスト名:Port番号」
ServerActive=192.168.56.101:10051
# Hostname=Zabbixの管理サイトの「設定⇒ホスト」メニューのホストの設定ページにて、登録されている「ホスト名」
Hostname=test_host_102
#ListenIP=Zabbix Agentが接続を待ち受けるIPアドレス
#コメントアウトするとすべてのインターフェースからListenするようになります。
~省略~
</pre>
<br/>
zabbix agentdを起動します。<br/>
<pre class="brush:bash">
# /etc/init.d/zabbix-agent start
</pre>
<br/>
<h2 class="sub_title">サーバ側の設定</h2>
ZabbixのWebページの「設定→ホスト→ホストの作成」ページに移動します。<br/>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRhCS_L3kfUxl1X031V-6nMKIpB5_kBM2yPra8drxxK1-hZniIc-rArg8Hg4jNLfpm3rjNUOt5TkbH3UT9oaYRp0yPJ4RRzKsOJVjljKyaK7BTaJMtxJz7HYbRfVsm8LpUVVmGknEh-iY/s1600/1.jpg" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRhCS_L3kfUxl1X031V-6nMKIpB5_kBM2yPra8drxxK1-hZniIc-rArg8Hg4jNLfpm3rjNUOt5TkbH3UT9oaYRp0yPJ4RRzKsOJVjljKyaK7BTaJMtxJz7HYbRfVsm8LpUVVmGknEh-iY/s1600/1.jpg" /></a>
<br/>
・注意すべきの項目は以下のようになります。<br/>
ホスト名:Agent側に設定したHostname(test_host_102)を設定<br/>
エージェントのインターフェースのIPアドレス:AgentのIPアドレスを入力<br/><br/>
該当のホストが属するグループとテンプレートを設定すると「監視データ→グラフ」にて確認ができます。
<br/>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhvkvyWmWc2vyQJqjBqehFPM2OY8OB96aC7PRjsnIvF3YOylX_VYPI3NTVZBGkb_SvfFGWnQRhrNwCWN_BPNtBilO7P-p_4WfS1OJAr1ys9SUHdIDv2UzfrgFUFFBE_vHNtv4uLx425JQY/s1600/2.jpg" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhvkvyWmWc2vyQJqjBqehFPM2OY8OB96aC7PRjsnIvF3YOylX_VYPI3NTVZBGkb_SvfFGWnQRhrNwCWN_BPNtBilO7P-p_4WfS1OJAr1ys9SUHdIDv2UzfrgFUFFBE_vHNtv4uLx425JQY/s1600/2.jpg" /></a><br/>
<br/>
・Zabbix Server2.2の設置手順につきましては、以下のURLを参照してください。<br/>
<a href="/2013/12/zabbix2.2.0-install-server.html" title="zabbix server 2.2" target="_blank">Zabbix Server2.2.0のインストール手順</a><br/>
<br />unknownhttp://www.blogger.com/profile/15190790785934095924noreply@blogger.com0tag:blogger.com,1999:blog-8771673127918263645.post-34613064193453744892013-12-26T19:05:00.000+09:002014-01-22T10:00:26.187+09:00Javaプロセスの中,一番負荷がかかっているスレッドは?<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1ZN8153VXCCvij_OYRiEGZT4QhxfK5p99SrMLQhr8RPDOVwxfKsnOnxViacCovQgvZcIc7jyYksDQHo_pXdPFJyFP6Qghd2QPCk6l03Yv4indGVhyYyGajjFtIms-FCl22mYrxVx5wgs/s1600/1.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1ZN8153VXCCvij_OYRiEGZT4QhxfK5p99SrMLQhr8RPDOVwxfKsnOnxViacCovQgvZcIc7jyYksDQHo_pXdPFJyFP6Qghd2QPCk6l03Yv4indGVhyYyGajjFtIms-FCl22mYrxVx5wgs/s1600/1.png" /></a><br/><br/>
現在実行中のJavaプロセスの「スレッドの状態」、「メモリの状況」、「一番負荷がかかっているスレッド」の確認をする方法について整理してみました。<br/><br/>
<h2 class="sub_title">Javaプロセスのダンプを取ろう!</h2>
現在実行中のJavaのThreadの状態やJavaプロセスのメモリの状況はJavaのダンプ(Dump)を取ることで、確認が出来ます。<br/><br/>
<strong>1.killコマンドを利用してダンプを取る</strong><br/>
まず、<code class="path">ps</code>コマンドを利用して実行中のjavaのPIDを確認します。<br/>
<pre class="brush:bash">
$ ps -ef | grep java
test 17546 1 1 Dec20 01:38:24 /usr/local/jdk/bin/java -Djava.util.logging.config.file=/home/test/tomcat/conf/logging.properties -Xms2048m -Xmx2048m -XX:MaxPermSize=256m -Dfile.encoding=utf-8 -Dverbose:jni -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.endorsed.dirs=/home/test/tomcat/endorsed -classpath /home/test/tomcat/bin/bootstrap.jar -Dcatalina.base=/home/test/tomcat -Dcatalina.home=/home/test/tomcat -Djava.io.tmpdir=/home/test/tomcat/temp org.apache.catalina.startup.Bootstrap start
test 29257 21592 0 14:59 pts/2 00:00:00 grep java
</pre>
<br/>
<code class="path">kill</code>コマンドを利用して先ほどのPIDのダンプを取ります。<br/>
<pre class="brush:bash">
kill -3 [JavaプロセスのPID]
$ kill -3 17546
取ったダンプはTomcatのLOG(catalina.out)に出力されます。
$ vi /home/test/tomcat/logs/catalina.out
2013-12-26 11:55:57
Full thread dump Java HotSpot(TM) Server VM (xx.x-xxx mixed mode):
"Attach Listener" daemon prio=10 tid=0x08b40c00 nid=0x5839 waiting on condition [0x00000000]
java.lang.Thread.State: RUNNABLE
"TP-Processor8" daemon prio=10 tid=0x08c15400 nid=0x42de runnable [0x4775b000]
java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:129)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:218)
at java.io.BufferedInputStream.read1(BufferedInputStream.java:258)
at java.io.BufferedInputStream.read(BufferedInputStream.java:317)
- locked <0x6cf496b0> (a java.io.BufferedInputStream)
at org.apache.jk.common.ChannelSocket.read(ChannelSocket.java:621)
at org.apache.jk.common.ChannelSocket.receive(ChannelSocket.java:559)
at org.apache.jk.common.ChannelSocket.processConnection(ChannelSocket.java:686)
at org.apache.jk.common.ChannelSocket$SocketConnection.runIt(ChannelSocket.java:891)
at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:690)
at java.lang.Thread.run(Thread.java:619)
…中略…
</pre>
<br/><br/>
<strong>2.JDKのjstackコマンドを利用してダンプを取る</strong><br/>
JDKのディレクトリの<code class="path">jps</code>コマンドを利用してJavaのプロセスを確認します。<br/>
<pre class="brush:bash">
JDKのディレクトリに移動します。
$ cd /usr/local/jdk/bin/
$ ./jps -lv
29840 sun.tools.jps.Jps -Dapplication.home=/usr/local/jdk -Xms8m
17546 org.apache.catalina.startup.Bootstrap -Djava.util.logging.config.file=/home/test/tomcat/conf/logging.properties -Xms2048m -Xmx2048m -XX:MaxPermSize=256m -Dfile.encoding=utf-8 -Dverbose:jni -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.endorsed.dirs=/home/test/tomcat/endorsed -Dcatalina.base=/home/test/tomcat -Dcatalina.home=/home/test/tomcat -Djava.io.tmpdir=/home/test/tomcat/temp
</pre>
<br/>
JDKの<code class="path">jstack</code>コマンドを利用して、該当のプロセスのダンプを出力します。<br/>
<pre class="brush:bash">
$ ./jstack 17546 > /home/test/java_dump.log
$ vi /home/test/java_dump.log
</pre>
<br/>
<h2 class="sub_title">負荷がかかっているスレッドを確認する</h2>
Linuxの<code class="path">top</code>コマンドに「H」オプションつけることでThreadごとのリソース使用率の確認が出来ます。<br/>
<pre class="brush:bash">
$ top -H
top - 15:25:55 up 6 days, 21:35, 1 user, load average: 0.29, 0.24, 0.29
Tasks: 407 total, 1 running, 406 sleeping, 0 stopped, 0 zombie
Cpu(s): 9.4%us, 0.6%sy, 0.0%ni, 89.3%id, 0.4%wa, 0.0%hi, 0.4%si, 0.0%st
Mem: 3145728k total, 557468k used, 2588260k free, 0k buffers
Swap: 11719376k total, 712k used, 11718664k free, 1800000k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
16361 test 16 0 1652m 998m 24m S 59 24.7 1:35.09 java
15431 test 16 0 1652m 998m 24m S 8 24.7 12:19.77 java
15432 test 15 0 1652m 998m 24m S 1 24.7 12:14.28 java
</pre>
<br/>
【Shift + p】CPU使用率でソート<br/>
【Shift + m】メモリ使用量でソート<br/>
もしくは【<,>】キーを利用してソート順を変更しながら、CPUの利用率が高いスレッドのIDを確認します。<br/>
そのスレッドIDを16進数(HEX)に変更して、先ほど取ったjavaダンプにて検索するとどのスレッドなのか確認が出来ます。<br/><br/>unknownhttp://www.blogger.com/profile/15190790785934095924noreply@blogger.com0tag:blogger.com,1999:blog-8771673127918263645.post-75029889622579696482013-12-20T19:05:00.000+09:002014-01-22T10:01:55.397+09:00Keytool を利用してSSLのルート証明書を追加する方法<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJvHwUy_9g8Jap7MclpPet-LFMuTOlevMHJwEZlPa93tabKwECMEiKWf5o0UykX4GSXIrSXXNJvexH8HgwqAVM9gwjIwIRuIxFFO8hyphenhyphen9hjK4nFKhWP-5l_nvRgH-f3dyNMwuuW4yseUOY/s1600/30520302_ssl.jpg" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJvHwUy_9g8Jap7MclpPet-LFMuTOlevMHJwEZlPa93tabKwECMEiKWf5o0UykX4GSXIrSXXNJvexH8HgwqAVM9gwjIwIRuIxFFO8hyphenhyphen9hjK4nFKhWP-5l_nvRgH-f3dyNMwuuW4yseUOY/s1600/30520302_ssl.jpg" /></a>
<br/>サーバ間のSSL通信を行う際に、相手サーバのSSLを対応しているルート証明書が必要とされます。<br/>
相手のサーバのSSLが1024bitから2048bit版に変更された際にも、2048bitに対応したルート証明書が必要です。<br/>
今回は、Keytoolを利用してサーバにルート証明書を追加する方法について整理してみました。<br/><br/>
<h2 class="sub_title">該当のSSLに対応しているか確認する</h2>
確認する方法:該当のSSLが入っているURLにサーバから接続して、問題なく該当のページが取得できるかどうかを見る<br/><br/>
該当のSSLが入っているURLは以下の方法で取得できます。<br/>
1.相手サーバのURL(既に相手のサーバの証明書が更新された場合)<br/>
2.WEBサイトにてゲット<br/>
例)verisignの場合は<a href="https://www.verisign.co.jp/developer/step03.html" target="_blank">https://www.verisign.co.jp/developer/step03.html</a>でテストが出来ます。<br/><br/>
サーバから相手のサーバにURLで接続するサンプルを作って見ました。(JSP)<br/>
以下のサンプルはverisignサイトの「VeriSign Class 3 Public Primary Certification Authority - G5」SSLが設置されているURLに接続するロジックです。
<pre class="brush:java">
<%-- page content type & import --%>
<%@ page contentType="text/xml; charset=UTF-8" %>
<%@ page import="java.io.*, java.util.*, java.sql.*, java.net.*, java.text.*" %>
<%-- common Header & Initialzation --%>
<%!
public String readURL(String urlPage, String method, String param, boolean isNewLine) throws Exception {
//SEND
URL url = null;
HttpURLConnection urlConn = null;
String suffix = isNewLine ? "\n" : "";
url = new URL(urlPage);
urlConn = (HttpURLConnection)url.openConnection();
byte[] sendByte = new String(param).getBytes();
urlConn.setDefaultUseCaches(false);
urlConn.setDoInput(true);
urlConn.setDoOutput(true);
urlConn.setRequestMethod(method);
urlConn.setRequestProperty("content-type", "application/x-www-form-urlencoded");
DataOutputStream out = null;
out = new DataOutputStream(urlConn.getOutputStream());
out.write(sendByte);
out.flush();
//RECIEVE
BufferedReader reader=null;
String line = null;
String result = "";
try {
reader = new BufferedReader(new InputStreamReader(urlConn.getInputStream()));
while ((line = reader.readLine()) != null) {result += line + suffix;}
} finally {if (reader != null) {reader.close();}}
return result;
}
%>
<%
/*********************************************
* MAIN LOGIC
*********************************************/
out.clear();
try {
/*
以下のページにてURL取得
https://www.verisign.co.jp/developer/step03.html
*/
out.println(readURL("https://ssltest6.verisign.co.jp/", "POST", "", true));
} catch(Exception ex) {
System.out.println(new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new java.util.Date()) + " [ERROR] " + ex.getMessage());
ex.printStackTrace();
}
%>
</pre>
<br/>
Tomcatに以下のようなエラーが発生した場合は、該当のルート証明書を追加する必要があります。<br/>
<pre class="brush:java">
sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
</pre>
<h2 class="sub_title">Keytoolを利用してルート証明書を追加する</h2>
ルート証明書を提供しているサイトにてルート証明書をダウンロードします。<br/>
例)<a href="https://www.symantec.com/page.jsp?id=roots" target="_blank">https://www.symantec.com/page.jsp?id=roots</a><br/>
<pre class="brush:bash">
$ wget http://www.verisign.com/repository/roots/root-certificates/PCA-3G5.pem
</pre>
<br/>
設置されているJavaの経路を確認し、keytoolコマンドで証明書を追加します。<br/>
<pre class="brush:bash">
Javaの経路確認
# whereis java
Javaが複数設置されている場合は、必ず現在利用中のJavaに追加する必要があります。
# java -version
keytoolを利用してダウンロードした証明書を追加
形式:keytool -import -alias ”別名(小文字)” -keystore ”Keyストアのパス指定” -file ”ダウンロードしたルート証明書の経路を指定”
# keytool -import -alias verisign_class3_g5_2048 -keystore /usr/local/jdk/jre/lib/security/cacerts -file /home/test/PCA-3G5.pem
Enter keystore password:
Owner: CN=VeriSign Class 3 Public Primary Certification Authority - G5, OU="(c) 2006 VeriSign, Inc. - For authorized use only", OU=VeriSign Trust Network, O="VeriSign, Inc.", C=US
…省略…
#4: ObjectId: 1.3.6.1.5.5.7.1.12 Criticality=false
Trust this certificate? [no]: yes
Certificate was added to keystore
</pre>
<code class="path">Certificate was added to keystore</code>メッセージが出力されたらOK<br/>
※Keyストアのパスは基本的にJavaのホームディレクトリの<code class="path">jre/lib/security/cacerts</code>になります。<br/>
※keytoolのDefaultパスワードは<code class="path">changeit</code>です。<br/><br/>
追加したルート証明書を確認してみます。
<pre class="brush:bash">
# keytool -list -v -keystore /usr/local/jdk/jre/lib/security/cacerts -alias verisign_class3_g5_2048 -storepass changeit
</pre>
※<code class="path">alias</code>オプションを削除すると、該当のキーストアに登録されているすべてのリストが確認できます。<br/><br/>
ルート証明書の追加が完了されたら、Tomcatを再起動してください。<br/>
※Tomcatを再起動しないと追加した証明書が反映されないので、必ずTomcatの再起動を行ってください。<br/><br/>
unknownhttp://www.blogger.com/profile/15190790785934095924noreply@blogger.com0tag:blogger.com,1999:blog-8771673127918263645.post-5025464541964461872013-12-16T21:56:00.000+09:002014-02-04T18:38:21.431+09:00Zabbix2.2.0のインストール手順(server)
<h2 class="sub_title">インストール環境とバージョン</h2>
今回、インストールするサーバとzabbix-serverのバージョンは以下のようになります。<br />
<table class="table_system_info01">
<tbody>
<tr>
<th>名前</th>
<th>バージョン</th>
<th>ダウンロード元</th>
</tr>
<tr>
<td class="td-subject">ubuntu</td>
<td>10.04.4(64bit)</td>
<td><a href="http://releases.ubuntu.com/lucid/" target="_blank" title="ubuntu-10.04.4">http://releases.ubuntu.com/lucid/</a></td>
</tr>
<tr>
<td class="td-subject">Apache Httpd Server</td>
<td>2.4.6</td>
<td><a href="http://httpd.apache.org/" target="_blank" title="Apache">http://httpd.apache.org/</a></td>
</tr>
<tr>
<td class="td-subject">PHP</td>
<td>5.5.5</td>
<td><a href="http://www.php.net/" target="_blank" title="PHP5.5.5">http://www.php.net/</a></td>
</tr>
<tr>
<td class="td-subject">MySQL</td>
<td>5.6.14</td>
<td><a href="http://dev.mysql.com/" target="_blank" title="MySQL-5.6.14">http://dev.mysql.com/</a></td>
</tr>
<tr>
<td class="td-subject">Net-SNMP</td>
<td>5.7.2</td>
<td><a href="http://net-snmp.sourceforge.net/" target="_blank" title="Net-SNMP-5.7.2">http://net-snmp.sourceforge.net/</a></td>
</tr>
<tr>
<td class="td-subject">cURL</td>
<td>7.33.0</td>
<td><a href="http://curl.haxx.se/" target="_blank" title="cURL-7.33.0">http://curl.haxx.se/</a></td>
</tr>
<tr>
<td class="td-subject">ZABBIX</td>
<td>2.2.0</td>
<td><a href="http://www.zabbix.com/" target="_blank" title="zabbix-2.2.0">http://www.zabbix.com/</a></td>
</tr>
</tbody>
</table>
<h2 class="sub_title">
インストールする前の準備作業</h2>
開発パッケージが設置されてない場合は、<code class="path">apt-get</code>でインストールする必要があります。<br />
<pre class="brush:bash"># apt-get install build-essential curl libcurl3 libpcre3-dev libssl-dev libxml2-dev libbz2-dev libgd2-xpm-dev libmcrypt-dev
</pre>
<br/>
ロケール、フォントを追加します。<br />
<pre class="brush:bash">
# sudo locale-gen ja_JP.UTF-8
# apt-get install gettext
</pre>
<h2 class="sub_title">Apacheインストール</h2>
「<a href="/2013/11/apache-246.html" title="apache install">Apache2.4.6のインストール手順</a>」を参照してください。
<br />
<h2 class="sub_title">Mysqlインストール</h2>
「<a href="/2013/10/mysql-5614.html" title="mysql install">MySQL 5.6.16のインストール手順</a>」を参照してください。
<br />
<h2 class="sub_title">PHPインストール</h2>
「<a href="/2013/11/php-fpm-with-apache.html" title="apache install">PHP5.5.5,PHP-FPMのインストール手順</a>」を参照してください。
<br />
<h2 class="sub_title">Net-SNMPをインストールする</h2>
※以下のコマンドを実行してインストールしてください。<br/>
尚、configureでは値の入力を求められますが、入力する値は全てデフォルト値で問題ありません。<br/>
make途中【/usr/bin/ld: cannot find -lperl】エラーの場合<code class="path">apt-get install libperl-dev</code>を実行してください。<br/>
<pre class="brush:bash">
# cd /usr/local/src/
# wget -O 'net-snmp-5.7.2.tar.gz' http://downloads.sourceforge.net/project/net-snmp/net-snmp/5.7.2/net-snmp-5.7.2.tar.gz?r=http%3A%2F%2Fsourceforge.net%2Fprojects%2Fnet-snmp%2Ffiles%2Fnet-snmp%2F5.7.2%2F&ts=1380706908&use_mirror=jaist
# tar xvf net-snmp-5.7.2.tar.gz
# cd net-snmp-5.7.2
# ./configure
# make
# make install
</pre>
<br />
<h2 class="sub_title">cURLをインストールする</h2>
<pre class="brush:bash">
# curl -version
# apt-get remove curl
# cd /usr/local/src/
# wget http://curl.haxx.se/download/curl-7.33.0.tar.gz
# tar xvf curl-7.33.0.tar.gz
# cd curl-7.33.0
# ./configure
# make && make install
</pre>
<br />
cURLのコマンドを<code class="path">/etc/profile</code>に登録します。<br />
尚、既に登録されている場合は省略してください。
<pre class="brush:bash">
# curl -V
# vi /etc/profile
/usr/local/bin/をPATH=の所に追加します。
export PHP_HOME=/usr/local/php/current
PATH=${PHP_HOME}/bin:${PATH}:/usr/local/bin/
# source /etc/profile
# curl -V
</pre>
<br />
<h2 class="sub_title">Zabbixをインストールする</h2>
※configureオプションは自由に変更してください。<br/>
オプション:with-mysql(MYSQL監視)、with-net-snmp(SNMPサポートのため)、with-libcurl(WEB監視)<br/>
<pre class="brush:bash">
# groupadd zabbix
# useradd -g zabbix -s /bin/false -M zabbix
# cd /usr/local/src/
# wget -O 'zabbix-2.2.0.tar.gz' http://downloads.sourceforge.net/project/zabbix/ZABBIX%20Latest%20Stable/2.2.0/zabbix-2.2.0.tar.gz?r=http%3A%2F%2Fwww.zabbix.com%2Fjp%2Fdownload.php&ts=1387170751&use_mirror=jaist
# tar xvf zabbix-2.2.0.tar.gz
# cd zabbix-2.2.0
# ./configure --enable-server --with-mysql=/usr/local/mysql/current/bin/mysql_config --with-net-snmp --with-libcurl
# make
# make install
</pre>
<br/>
その他、設定ファイルを登録します。
<pre class="brush:bash">
# mkdir /var/log/zabbix
# chown zabbix:zabbix /var/log/zabbix
# cp misc/init.d/debian/zabbix-server /etc/init.d
# cp conf/zabbix_server.conf /usr/local/etc/zabbix_server.conf
# cp misc/init.d/ubuntu/zabbix-server.conf /etc/init/
# sudo start zabbix-server
</pre>
<br />
<code class="path">zabbix_server.conf</code>の設定を書き換えます。<br />
<pre class="brush:bash">
# vi /usr/local/etc/zabbix_server.conf
DBName=データベース名
DBUser=データベースに接続するユーザ名
DBPassword=データベースに接続するユーザのパスワード
DBSocket=/usr/local/mysql/current/tmp/mysql.sock
LogFile=/var/log/zabbix/zabbix_server.log
</pre>
<br />
<code class="path">php.ini</code>の設定を書き換えます。<br/>
<pre class="brush:bash">
# vi /usr/local/php/current/conf/php.ini
max_execution_time = 600
max_input_time = 600
memory_limit = 256M
post_max_size = 32M
upload_max_filesize = 16M
date.timezone = "Asia/Tokyo"
</pre>
<br/>
<code class="path">/etc/ld.so.conf.d/net-snmp.conf</code>を作成します。<br />
<pre class="brush:bash">
# vi /etc/ld.so.conf.d/net-snmp.conf
/usr/local/lib
</pre>
<br/>
<code class="path">/etc/ld.so.conf.d/mysql.conf</code>を作成します。<br />
※既に設定されている場合は上書きしてください。<br/>
<pre class="brush:bash">
# vi /etc/ld.so.conf.d/mysql.conf
/usr/local/mysql/current/lib
</pre>
<br/>
以下のコマンドでライブラリのパスを通します。<br/>
<pre class="brush:bash">
# ldconfig
</pre>
<br/>
mysqlサーバにデータベースを作成します。<br/>
<pre class="brush:bash">
mysql -u root -p
> create database zabbix charset=utf8;
> grant all on zabbix.* to zabbix@localhost identified by "任意のパスワード";
> flush privileges;
> exit
# cd /usr/local/src/zabbix-2.2.0
# mysql -u zabbix -D zabbix -p < database/mysql/schema.sql
# mysql -u zabbix -D zabbix -p < database/mysql/images.sql
# mysql -u zabbix -D zabbix -p < database/mysql/data.sql
</pre>
<br/>
以下の手順でphpプログラムを配置します。<br/>
<pre class="brush:bash">
# mkdir /usr/local/httpd/current/htdocs/zabbix
# cd /usr/local/src/zabbix-2.2.0/frontends/php/
# cp -a . /usr/local/httpd/current/htdocs/zabbix/
# chown -R apache:apache /usr/local/httpd/current/htdocs/zabbix
# chmod 777 /usr/local/httpd/current/htdocs/zabbix/conf
</pre>
<br/>
zabbix-serverを起動します。<br/>
<pre class="brush:bash">
# /etc/init.d/zabbix-server start
# ps -ef | grep zabbix
zabbix 9447 1 0 16:46 ? 00:00:00 /usr/local/sbin/zabbix_server
zabbix 9449 9447 0 16:46 ? 00:00:00 /usr/local/sbin/zabbix_server: configuration syncer [waiting 60 sec for processes]
zabbix 9450 9447 0 16:46 ? 00:00:00 /usr/local/sbin/zabbix_server: db watchdog [synced alerts config in 0.004222 sec, idle 60 sec]
zabbix 9451 9447 0 16:46 ? 00:00:00 /usr/local/sbin/zabbix_server: poller #1 [got 0 values in 0.000004 sec, idle 5 sec]
zabbix 9452 9447 0 16:46 ? 00:00:00 /usr/local/sbin/zabbix_server: poller #2 [got 0 values in 0.000002 sec, idle 5 sec]
zabbix 9453 9447 0 16:46 ? 00:00:00 /usr/local/sbin/zabbix_server: poller #3 [got 0 values in 0.000003 sec, idle 5 sec]
zabbix 9454 9447 0 16:46 ? 00:00:00 /usr/local/sbin/zabbix_server: poller #4 [got 0 values in 0.000002 sec, idle 5 sec]
zabbix 9455 9447 0 16:46 ? 00:00:00 /usr/local/sbin/zabbix_server: poller #5 [got 0 values in 0.000003 sec, idle 5 sec]
起動されない場合は以下のログファイルを確認してください。
# tail -f /var/log/zabbix/zabbix_server.log
</pre>
<br/>
Webページに接続して実際のページを確認します。<br/>
http://192.168.56.101/zabbix/setup.php<br/>
ID/PW: admin / zabbix<br/>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvOJPxv5wLaUm0PpvFsusvGBTiaTbhnFSeuBk3OTaoVRPqoItzlEFtDb8UxePxC_tO84pWu1u3E8SelTO2FEJqpwsgO8KXgiefcgmF_MkJd40PZZopoFnXcMZltPangvkEto2oCPzmOoM/s1600/1.jpg" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvOJPxv5wLaUm0PpvFsusvGBTiaTbhnFSeuBk3OTaoVRPqoItzlEFtDb8UxePxC_tO84pWu1u3E8SelTO2FEJqpwsgO8KXgiefcgmF_MkJd40PZZopoFnXcMZltPangvkEto2oCPzmOoM/s1600/1.jpg" /></a><br/>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhnzgeMetjKgQP0DATwzyFSFbme6hwVDibb3xL3Hwn3Yay6ZRwNbupeB1utkIrDScnXZ8Ul3n_-jIgW-cj7ZibeDYjgW6ShefiAh-c9i6DXdZ8_zH7RkAaa9NJMstkIHhfs9yrlOox7cnU/s1600/2.jpg" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhnzgeMetjKgQP0DATwzyFSFbme6hwVDibb3xL3Hwn3Yay6ZRwNbupeB1utkIrDScnXZ8Ul3n_-jIgW-cj7ZibeDYjgW6ShefiAh-c9i6DXdZ8_zH7RkAaa9NJMstkIHhfs9yrlOox7cnU/s1600/2.jpg" /></a>
<br/><br/>
<h2 class="sub_title">Zabbixの日本語文字設定</h2>
日本語のロケール、フォントを追加します。
<pre class="brush:bash">
# cd /usr/local/httpd/current/htdocs/zabbix/locale
# sudo locale-gen ja_JP.UTF-8
# ./make_mo.sh
./make_mo.sh: line 4: msgfmt: command not found
というエラーが発生した場合は「gettext」をインストールしてください。
# apt-get install gettext
</pre>
日本語のフォントを設置します。<br/>
<pre class="brush:bash">
# aptitude install otf-ipafont
# cd /usr/local/httpd/current/htdocs/zabbix/fonts
# ln -s /usr/share/fonts/opentype/ipafont/ipag.ttf ipag.ttf
# vi /usr/local/httpd/current/htdocs/zabbix/include/defines.inc.php
内容変更
//define('ZBX_GRAPH_FONT_NAME', 'DejaVuSans'); // font file name
define('ZBX_GRAPH_FONT_NAME', 'ipag');
//define('ZBX_FONT_NAME', 'DejaVuSans');
define('ZBX_FONT_NAME', 'ipag');
</pre>
Webページにadminにてログインした後、上段の「Profile⇒User⇒Language項目」を英語から「Japanese (ja_JP)」に変更して
保存するとページの言語が変わります。<br/>
<br/><br/>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjTpyE5VdQGLxEReYdkV7-V1Kb0ntCTKtW2RN8p74L5AMz6OYNlUNK7RQvq-XXKry-EJz_lVWizx4i6lAfHPsc1NkVmsPL4JnjSh5wwB7d1iRgXhRuuKxlHCAJMJ66PgfW1wfCx-gx6oI0/s1600/3.jpg" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjTpyE5VdQGLxEReYdkV7-V1Kb0ntCTKtW2RN8p74L5AMz6OYNlUNK7RQvq-XXKry-EJz_lVWizx4i6lAfHPsc1NkVmsPL4JnjSh5wwB7d1iRgXhRuuKxlHCAJMJ66PgfW1wfCx-gx6oI0/s1600/3.jpg" /></a>
<br/><br/>
文字フォントを変更しても以下のキャプチャのようにグラフの文字列が文字化けする場合があります。<br/>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdbHEjOjUrVDUvWgm9ZZZjeYPqLedApTHJ7X7CKNK7i0W4xRWIIh98JjJl8x802dOxN6GwQJ_6LRdRByYraagzxJVz3G1z_N8d86SGTroqjYQQiqbOHLMz5ITE91DRG-KAzuiRv1LaGzk/s1600/1.jpg" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdbHEjOjUrVDUvWgm9ZZZjeYPqLedApTHJ7X7CKNK7i0W4xRWIIh98JjJl8x802dOxN6GwQJ_6LRdRByYraagzxJVz3G1z_N8d86SGTroqjYQQiqbOHLMz5ITE91DRG-KAzuiRv1LaGzk/s1600/1.jpg" /></a><br/><br/>
PHPをコンパイルする際に<code class="path">enable-gd-jis-conv</code>オプションをつけてインストールすると、imagettftext()関数の最後の因数<code class="path">string $text</code>がUTF-8の文字列ではなく、SJISになってしまうのが原因ですので、解決をするためには<code class="path">enable-gd-jis-conv</code>を消して再コンパイルするか、Zabbixの<code class="path">graphs.inc.php</code>ファイルのimagettftext()関数を使う部分にUTF8エンコードするロジックを追加する必要があります。<br/>
修正する方法は以下の部分をご参照ください。<br/><br/>
<pre class="brush:bash">
# vi /usr/local/httpd/current/htdocs/zabbix/include/graphs.inc.php
if ($gdinfo['FreeType Support'] && function_exists('imagettftext')) {
//678Lineに以下のifを追加することで、文字化けがなくなります。
//--------ここから--------
if ($gdinfo['JIS-mapped Japanese Font Support']) {
$string = mb_convert_encoding($string, "SJIS", "UTF-8");
}
//--------ここまで--------
if ((preg_match(ZBX_PREG_DEF_FONT_STRING, $string) && $angle != 0) || ZBX_FONT_NAME == ZBX_GRAPH_FONT_NAME) {
$ttf = ZBX_FONTPATH.'/'.ZBX_FONT_NAME.'.ttf';
imagettftext($image, $fontsize, $angle, $x, $y, $color, $ttf, $string);
}
elseif ($angle == 0) {
$ttf = ZBX_FONTPATH.'/'.ZBX_GRAPH_FONT_NAME.'.ttf';
imagettftext($image, $fontsize, $angle, $x, $y, $color, $ttf, $string);
}
else {
$ttf = ZBX_FONTPATH.'/'.ZBX_GRAPH_FONT_NAME.'.ttf';
$size = imageTextSize($fontsize, 0, $string);
$imgg = imagecreatetruecolor($size['width'] + 1, $size['height']);
$transparentColor = imagecolorallocatealpha($imgg, 200, 200, 200, 127);
imagefill($imgg, 0, 0, $transparentColor);
imagettftext($imgg, $fontsize, 0, 0, $size['height'], $color, $ttf, $string);
$imgg = imagerotate($imgg, $angle, $transparentColor);
ImageAlphaBlending($imgg, false);
imageSaveAlpha($imgg, true);
imagecopy($image, $imgg, $x - $size['height'], $y - $size['width'], 0, 0, $size['height'], $size['width'] + 1);
imagedestroy($imgg);
}
}
</pre>
修正した後、実際の画面で確認してみると問題なくグラフに日本語が表示されます。<br/>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjobxQ3iBJAFf3y3Rl3mf19AAXYU8fe01RK_p1PfMxl_RZD3c57e5IXLTs9tixotDCfbway_Y2cwguikGyNGLt8CrdYXsr3jszibr-sPsVJGPnGYPyrlleSXyO7lvzOEy0elVSd7u3oLu4/s1600/2.jpg" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjobxQ3iBJAFf3y3Rl3mf19AAXYU8fe01RK_p1PfMxl_RZD3c57e5IXLTs9tixotDCfbway_Y2cwguikGyNGLt8CrdYXsr3jszibr-sPsVJGPnGYPyrlleSXyO7lvzOEy0elVSd7u3oLu4/s1600/2.jpg" /></a><br/><br/>
<h2 class="sub_title">zabbix-getのInstall</h2>
zabbix-getなどのコマンドはZabbixの<code class="path">src</code>ディレクトリの中にありますので、makeを利用して追加インストールする必要があります。
<pre class="brush:bash">
# cd /usr/local/src/zabbix-2.2.0/src/zabbix_get
# make
# make install
… …
test -z "/usr/local/bin" || /bin/mkdir -p "/usr/local/bin"
/usr/bin/install -c zabbix_get '/usr/local/bin'
make[1]: Nothing to be done for `install-data-am'.
make[1]: Leaving directory `/usr/local/src/zabbix-2.2.0/src/zabbix_get'
# zabbix_get
usage: zabbix_get [-hV] -s <host name or IP> [-p <port>] [-I <IP address>] -k <key>
</pre>
<br/><br/>
・Zabbix Agent2.2の設置手順につきましては、以下のURLを参照してください。<br/>
<a href="/2013/12/zabbix-agent-install.html" title="zabbix Agent 2.2" target="_blank">Zabbix Agent2.2.0のインストール手順</a><br/>
<br />unknownhttp://www.blogger.com/profile/15190790785934095924noreply@blogger.com1tag:blogger.com,1999:blog-8771673127918263645.post-87467035793826612392013-12-10T20:30:00.000+09:002014-01-22T10:08:14.856+09:00Chromeでfont-sizeを10px以下に設定する方法Chromeブラウザでは、CSSでfont-sizeを10px以下に設定しても、<br/>
ブラウザの設定で最小フォントサイズが決まっているため、10px(Default)以下にはならないようになっています。<br/><br/>
今回は、Chromeでfont-sizeを10px以下に設定する2つの方法について整理しました。<br/>
<h2 class="sub_title">ブラウザの設定を変更する</h2>
Chromeの設定 ⇒ 詳細設定 ⇒ フォントをカスタマイズの<br/>
「最小フォントサイズ」を変更すると設定したブラウザには問題なくフォントサイズが変更されます。<br/>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgIVf0NfxB0YckUwAcMFqJLX_JyWXucKxoUMEnblMuuxfo0AGFu3uD7DEKFBO5e-Kd8zjpYT10cdHcjq-3GklrIXk_yfKfnSwH8PIKmpgP8lNeS1syPWrHl3PQ4tNXRa8SCFq2mYGb29OU/s1600/1.jpg" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgIVf0NfxB0YckUwAcMFqJLX_JyWXucKxoUMEnblMuuxfo0AGFu3uD7DEKFBO5e-Kd8zjpYT10cdHcjq-3GklrIXk_yfKfnSwH8PIKmpgP8lNeS1syPWrHl3PQ4tNXRa8SCFq2mYGb29OU/s400/1.jpg" /></a><br/>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjUKSv7f4ur0b4TmZfSjC8Ee6vEa5hFGYzCnkQbZHIjKvR-6TDoGKG66awzFPb5S4jCDjqoILlq0zbxpQtsiUOeOsorZMQYkujy2pS8V-v3Y35iTKchhjFFgntEO55o7Dvo2TUn2ZBVQ-A/s1600/2.jpg" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjUKSv7f4ur0b4TmZfSjC8Ee6vEa5hFGYzCnkQbZHIjKvR-6TDoGKG66awzFPb5S4jCDjqoILlq0zbxpQtsiUOeOsorZMQYkujy2pS8V-v3Y35iTKchhjFFgntEO55o7Dvo2TUn2ZBVQ-A/s400/2.jpg" /></a><br/>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_vG9_2DQALf3zhzmSfgn5QutERj71fPXlO6nPDGwQoYGK_KPZzJjuZCKEYMIdn5BJ43U9wohvWSOx9NnEhBCpeR-3vxrBrF_0txDo-1x4ZRaqHAiJ_ZmxEWCidTwC4OHWzLNEfHLaJko/s1600/3.jpg" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_vG9_2DQALf3zhzmSfgn5QutERj71fPXlO6nPDGwQoYGK_KPZzJjuZCKEYMIdn5BJ43U9wohvWSOx9NnEhBCpeR-3vxrBrF_0txDo-1x4ZRaqHAiJ_ZmxEWCidTwC4OHWzLNEfHLaJko/s400/3.jpg" /></a><br/>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtZ0zd3073fD1Ze-AGoFAZRdlGmvatL3ogcYq7zO0M0zvDlCj3qCAOylyBZwqopw9h3XxSwvlGmU2uHIbPpW1mY_OJO-IeLj8ZwxNjMlGgJwp1oyp1X8u1-DJv7GH6QEsU2J1gwAuTf5s/s1600/4.jpg" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtZ0zd3073fD1Ze-AGoFAZRdlGmvatL3ogcYq7zO0M0zvDlCj3qCAOylyBZwqopw9h3XxSwvlGmU2uHIbPpW1mY_OJO-IeLj8ZwxNjMlGgJwp1oyp1X8u1-DJv7GH6QEsU2J1gwAuTf5s/s400/4.jpg" /></a>
<br/>
<h2 class="sub_title">CSSにて変更する方法</h2>
webkit-transformの<code class="path">scale3d</code>や<code class="path">scale</code>を利用して、既存の文字フォントサイズを0.x倍縮小することで、フォントをもっと小さく表示できます。<br/><br/>
・scale3dを利用した例:<br/>
12pxで設定すると6pxになります。<br/>
<pre class="brush:css">
p{
width: 200%;
line-height: 200%;
font-size: 12px;
-webkit-transform: scale3d(0.5, 0.5, 1);
-webkit-transform-origin: 0px 0px;
}
</pre><br/>
・scaleを利用した例:<br/>
<pre class="brush:css">
p{
font-size:9px;
-webkit-transform:scale(0.75);
display:inline-block;
}
</pre>
<h2 class="sub_title">参照したページ</h2>
<a href="http://mjj.logdown.com/posts/39967-set-css-font-size-less-than-12px-in" target="_blank"><u><i>http://mjj.logdown.com/posts/39967-set-css-font-size-less-than-12px-in</i></u></a><br/>
<a href="http://hai3.net/blog/2013/06/11/chrome-mini-font/" target="_blank"><u><i>http://hai3.net/blog/2013/06/11/chrome-mini-font/</i></u></a><br/>
<a href="http://www.dotblogs.com.tw/shunnien/archive/2013/06/07/105380.aspx" target="_blank"><u><i>http://www.dotblogs.com.tw/shunnien/archive/2013/06/07/105380.aspx</i></u></a><br/><br/>
unknownhttp://www.blogger.com/profile/15190790785934095924noreply@blogger.com0tag:blogger.com,1999:blog-8771673127918263645.post-81506258073091692842013-12-04T22:54:00.000+09:002014-01-22T10:08:45.419+09:00Redmineの詳細設定とテーマ変更(GitHub)<h2 class="sub_title">Redmineの詳細設定</h2>
1.認証を必須にする<br/>
「管理」→「設定」画面の「認証」タブを開き、「認証が必要」チェックボックスをONにしてください。<br/>
※ログインしていない状態ではRedmine上の情報に一切アクセスできなくなります。<br/><br/>
2.既存プロジェクトを非公開にする<br/>
プロジェクトの「設定」画面を開き、「情報」タブの「公開」チェックボックスをOFFにしてください。<br/>
※プロジェクトを非公開にすると、プロジェクトのメンバーになっているユーザーしか情報を参照できなくなります。<br/><br/>
3.新規プロジェクトのデフォルトを非公開にする<br/>
「管理」→「設定」画面の「認証」タブを開き、「デフォルトで新しいプロジェクトは公開にする」チェックボックスをOFFにしてください。<br/>
<br/>
<h2 class="sub_title">Redmineのテーマ変更</h2>
テーマをダウンロードし、<code class="path">themes</code>ディレクトリに入れてください。<br/>
<pre class="brush:bash">
# cd /usr/local/src/
# wget https://github.com/makotokw/redmine-theme-gitmike/archive/r6.tar.gz
# tar xvf r6.tar.gz
# cp -R redmine-theme-gitmike-r6 /usr/local/redmine/current/public/themes
</pre>
<br/>
その後、Redmineページの「管理⇒設定⇒表示」のテーマ項目を「Redmine-theme-gitmike-r6」に変更して「保存」するとデザインが変更されます。<br/>
<h2 class="sub_title">実際の画面</h2>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh36DgLcP2ifytFGbE43RDWjU8kkbq0hUh16R6gQnfDQjwHCCTk6YxMLR5etLtVoBD9fbed8BXDPwCdiWMkbuDs28OLZW-Pd-HK9D_hWMQNtdLTuU4DX9tf7rVRUqQf5tSH0yn49Sm_sh4/s1600/test.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh36DgLcP2ifytFGbE43RDWjU8kkbq0hUh16R6gQnfDQjwHCCTk6YxMLR5etLtVoBD9fbed8BXDPwCdiWMkbuDs28OLZW-Pd-HK9D_hWMQNtdLTuU4DX9tf7rVRUqQf5tSH0yn49Sm_sh4/s1600/test.png" /></a>
<br/>
<h2 class="sub_title">参照ページ</h2>
<a href="https://github.com/makotokw/redmine-theme-gitmike/tags" target="_blank"><u><i>https://github.com/makotokw/redmine-theme-gitmike/tags</i></u></a>
<br/><br/><br/>
・Redmineのインストール手順につきましては以下のURLを参照してください。<br/>
<a href="/2013/12/redmine-install.html" title="Redmine Install" target="_blank"><u><i>Redmineインストール手順</i></u></a><br/>
unknownhttp://www.blogger.com/profile/15190790785934095924noreply@blogger.com0tag:blogger.com,1999:blog-8771673127918263645.post-80377594777207352062013-12-03T20:00:00.000+09:002014-04-23T09:48:37.984+09:00Redmineのインストール手順(mysql,apache,ruby,ImageMagick)<h2 class="sub_title">インストール環境とバージョン</h2>
今回、インストールするサーバとRedmineのバージョンは以下のようになります。<br />
<table class="table_system_info01">
<tbody>
<tr>
<th>名前</th>
<th>バージョン</th>
<th>ダウンロード元</th>
</tr>
<tr>
<td class="td-subject">ubuntu</td>
<td>10.04.4(64bit)</td>
<td><a href="http://releases.ubuntu.com/lucid/" target="_blank" title="ubuntu-10.04.4">http://releases.ubuntu.com/lucid/</a></td>
</tr>
<tr>
<td class="td-subject">Apache Httpd Server</td>
<td>2.4.6</td>
<td><a href="http://httpd.apache.org/" target="_blank" title="Apache">http://httpd.apache.org/</a></td>
</tr>
<tr>
<td class="td-subject">MySQL</td>
<td>5.6.14</td>
<td><a href="http://dev.mysql.com/" target="_blank" title="MySQL-5.6.14">http://dev.mysql.com/</a></td>
</tr>
<tr>
<td class="td-subject">Ruby</td>
<td>2.0.0</td>
<td><a href="http://ftp.ruby-lang.org/pub/ruby/" target="_blank" title="http://ftp.ruby-lang.org/pub/ruby/">http://ftp.ruby-lang.org/pub/ruby/</a></td>
</tr>
<tr>
<td class="td-subject">ImageMagick</td>
<td>6.8.7</td>
<td><a href="http://www.imagemagick.org/" target="_blank" title="http://www.imagemagick.org/">http://www.imagemagick.org/</a></td>
</tr>
<tr>
<td class="td-subject">Redmine</td>
<td>2.4.1</td>
<td><a href="http://www.redmine.org/" target="_blank" title="Redmine-2.4.1">http://www.redmine.org/</a></td>
</tr>
</tbody>
</table>
<h2 class="sub_title">
インストールする前の準備作業</h2>
開発パッケージが設置されてない場合は、<code class="path">apt-get</code>でインストールする必要があります。<br />
<pre class="brush:bash"># apt-get install build-essential curl libcurl3 libpcre3-dev libssl-dev libxml2-dev libbz2-dev libgd2-xpm-dev libmcrypt-dev
</pre>
<h2 class="sub_title">Apacheインストール</h2>
「<a href="/2013/11/apache-246.html" title="apache install">Apache2.4.6のインストール手順</a>」を参照してください。
<br />
<h2 class="sub_title">Mysqlインストール</h2>
「<a href="/2013/10/mysql-5614.html" title="mysql install">MySQL 5.6.14のインストール手順</a>」を参照してください。
<br />
<h2 class="sub_title">RubyとBundlerのインストール</h2>
※パッケージがない場合は、インストールしてください。
<pre class="brush:bash">
# apt-get install -y make gcc g++ wget libssl-dev zlib1g-dev libreadline-dev libxslt-dev libxml2-dev libyaml-dev paco libcurl4-gnutls-dev
</pre>
<br />
続いて、Rubyをインストールします。<br />
<pre class="brush:bash">
# cd /usr/local/src/
# wget http://ftp.ruby-lang.org/pub/ruby/ruby-2.0.0-p353.tar.gz
# tar xvf ruby-2.0.0-p353.tar.gz
# cd ruby-2.0.0-p353
# ./configure
# make
# paco -D make install
# ruby --version
ruby 2.0.0p353 (2013-11-22 revision 43784) [x86_64-linux]
</pre>
<br/>
<h2 class="sub_title">ImageMagickのインストール</h2>
※ImageMagickが既に設置されている場合はスキップしてください。<br/>
<pre class="brush:bash">
# cd /usr/local/src/
# wget ftp://ftp.kddlabs.co.jp/graphics/ImageMagick/ImageMagick-6.8.9-0.tar.gz
# tar xfvz ImageMagick-6.8.9-0.tar.gz
# cd ImageMagick-6.8.9-0
# ./configure
# make
# make install
ライブラリ登録後、確認
# ldconfig /usr/local/lib
# identify -version
# /usr/local/bin/identify -list configure
</pre>
<br/>
gem installをする際にドキュメントが生成されうように<code class="path">~/.gemrc</code>を修正します。<br/>
<pre class="brush:bash">
# vi ~/.gemrc
gem: --no-ri --no-rdoc
</pre>
<br/>
bundlerをインストールします。<br/>
<pre class="brush:bash">
# gem install bundler
</pre>
<br/>
<h2 class="sub_title">Redmin用のデータベースを作成</h2>
まず、データベースがutf-8になっているか確認します。<br/>
<pre class="brush:bash">
# mysql -u root -p
mysql> show variables like 'character_set%';
+--------------------------+-----------------------------------------------+
| Variable_name | Value |
+--------------------------+-----------------------------------------------+
| character_set_client | utf8 |
| character_set_connection | utf8 |
| character_set_database | utf8 |
| character_set_filesystem | binary |
| character_set_results | utf8 |
| character_set_server | utf8 |
| character_set_system | utf8 |
| character_sets_dir | /usr/local/mysql/mysql-5.6.14/share/charsets/ |
+--------------------------+-----------------------------------------------+
8 rows in set (0.00 sec)
mysql> \q
</pre>
<br/>
※utf8になっていない場合は「my.cnf」ファイルにて文字コードを修正してください。<br/>
<br/><br/>
Redmine用のMySQLデータベースとユーザを作成します。<br/>
※パスワードは変更してください。<br/>
<pre class="brush:bash">
$ mysql -u root -p
mysql> create database redmine default character set utf8;
mysql> grant all on redmine.* to redmine@localhost identified by 'redmine';
mysql> flush privileges;
mysql> \q
</pre>
<br/>
<h2 class="sub_title">Redmineをインストールする</h2>
Redmineをインストールします。
<pre class="brush:bash">
# mkdir /usr/local/redmine
# cd /usr/local/src/
# wget http://www.redmine.org/releases/redmine-2.4.1.tar.gz
# tar xfvz redmine-2.4.1.tar.gz
# mv redmine-2.4.1 /usr/local/redmine
# cd /usr/local/redmine
# ln -s /usr/local/redmine/redmine-2.4.1 /usr/local/redmine/current
</pre>
<br/>
データベースへの接続設定を変更します。<br/>
<pre class="brush:bash">
# cp /usr/local/redmine/current/config/database.yml.example /usr/local/redmine/current/config/database.yml
# vi /usr/local/redmine/current/config/database.yml
production:
adapter: mysql2
database: redmine
host: localhost
username: redmine
password: "redmine"
encoding: utf8
socket: /usr/local/mysql/current/tmp/mysql.sock
</pre>
<br/>
メールサーバの設定を変更します。<br/>
<pre class="brush:bash">
# cp /usr/local/redmine/current/config/configuration.yml.example /usr/local/redmine/current/config/configuration.yml
# vi /usr/local/redmine/current/config/configuration.yml
production:
email_delivery:
delivery_method: :smtp
smtp_settings:
address: "localhost"
port: 25
domain: 'example.com'
</pre>
<br/>
GemパッケージのMYSQLインストールします。<br/>
<pre class="brush:bash">
# cd /usr/local/redmine/current
# gem install mysql2 -- --with-opt-include=/usr/local/mysql/current/include --with-opt-lib=/usr/local/mysql/current/lib
# bundle install --without development test postgresql sqlite
</pre>
<br/>
Redmineのセッションとデータベースを更新します。<br/>
<pre class="brush:bash">
# cd /usr/local/redmine/current
# rake generate_secret_token
# RAILS_ENV=production rake db:migrate
# RAILS_ENV=production rake redmine:load_default_data
</pre>
<br/>
問題なく設置されたのかテストをしてみます。(Apacheは停止してください。)<br/>
<pre class="brush:bash">
# cd /usr/local/redmine/current
# ruby script/rails server webrick -e production -p80
</pre>
<br/>
Passengerのインストールとapacheとの連携<br/>
<pre class="brush:bash">
# gem install passenger
....
Successfully installed passenger-4.0.26
2 gems installed
# passenger-install-apache2-module
</pre>
<br/>
※passenger-install-apache2-module実行中、以下のようなエラーで失敗する場合は、<code class="path">/etc/profile</code>にapacheの経路を登録してください。<br/>
<pre class="brush:bash">
* Checking for Apache 2...
Found: no
* Checking for Apache 2 development headers...
Found: no
* Checking for Apache Portable Runtime (APR) development headers...
Found: no
* Checking for Apache Portable Runtime Utility (APU) development headers...
Found: no
# vi /etc/profile
export APACHE_HOME=/usr/local/httpd/current/
PATH=${PATH}:/usr/local/lib/:${APACHE_HOME}/bin/
# source /etc/profile
# passenger-install-apache2-module
</pre>
<br/>
<h2 class="sub_title">Apacheの設定を変更する</h2>
Apacheの<code class="path">httpd.conf</code>ファイルにredmine関連設定を追加します。
<pre class="brush:bash">
# vi /usr/local/httpd/current/conf/httpd.conf
LoadModule passenger_module /usr/local/lib/ruby/gems/2.0.0/gems/passenger-4.0.26/buildout/apache2/mod_passenger.so
PassengerRoot /usr/local/lib/ruby/gems/2.0.0/gems/passenger-4.0.26
PassengerDefaultRuby /usr/local/bin/ruby
RailsBaseURI /redmine
</pre>
<br/>
redmineのhtmlファイルをApacheに公開します。<br/>
<pre class="brush:bash">
# ln -s /usr/local/redmine/current/public /usr/local/httpd/current/htdocs/redmine
# /usr/local/httpd/current/bin/apachectl restart
</pre>
<br/><br/>
画面から接続すると以下のようになります。<br/>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhChqcbG1FBX4HgmPdODI-qL86MshfQuBYCS8cizOUymTVvw-eXp_gvBZZLaEqy0H7FF4v0PWHvEtSdyi3CAdeSe_3x-MrmZ6BBBpOhy_LuaXIXYGctuuyEI-oU1wRpKcgtqO2kbiQgnAM/s1600/test.png" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhChqcbG1FBX4HgmPdODI-qL86MshfQuBYCS8cizOUymTVvw-eXp_gvBZZLaEqy0H7FF4v0PWHvEtSdyi3CAdeSe_3x-MrmZ6BBBpOhy_LuaXIXYGctuuyEI-oU1wRpKcgtqO2kbiQgnAM/s1600/test.png" /></a>
<br/>
最初のID/PWは「admin/admin」になります。<br/><br/>
・Redmineのテーマ変更及び、設定につきましては以下のURLを参照してください。<br/>
<a href="/2013/12/redmine-theme.html" title="Redmine Theme" target="_blank"><u><i>Redmineの詳細設定とテーマ変更(GitHub)</i></u></a><br/>
<br/>unknownhttp://www.blogger.com/profile/15190790785934095924noreply@blogger.com0tag:blogger.com,1999:blog-8771673127918263645.post-47421879638081908742013-11-13T20:00:00.000+09:002014-01-22T10:13:02.614+09:00PHP5.5.5,PHP-FPMのインストール手順(Apache, Mysql)
<h2 class="sub_title">インストール環境とバージョン</h2>
今回、インストールするサーバとPHPのバージョンは以下のようになります。<br />
<table class="table_system_info01">
<tbody>
<tr>
<th>名前</th>
<th>バージョン</th>
<th>ダウンロード元</th>
</tr>
<tr>
<td class="td-subject">ubuntu</td>
<td>10.04.4(64bit)</td>
<td><a href="http://releases.ubuntu.com/lucid/" target="_blank" title="ubuntu-10.04.4">http://releases.ubuntu.com/lucid/</a></td>
</tr>
<tr>
<td class="td-subject">Apache Httpd Server</td>
<td>2.4.6</td>
<td><a href="http://httpd.apache.org/" target="_blank" title="Apache">http://httpd.apache.org/</a></td>
</tr>
<tr>
<td class="td-subject">MySQL</td>
<td>5.6.14</td>
<td><a href="http://dev.mysql.com/" target="_blank" title="MySQL-5.6.14">http://dev.mysql.com/</a></td>
</tr>
<tr>
<td class="td-subject">PHP</td>
<td>5.5.5</td>
<td><a href="http://www.php.net/" target="_blank" title="PHP5.5.5">http://www.php.net/</a></td>
</tr>
</tbody>
</table>
<h2 class="sub_title">
インストールする前の準備作業</h2>
開発パッケージが設置されてない場合は、<code class="path">apt-get</code>でインストールする必要があります。<br />
<pre class="brush:bash"># apt-get install build-essential curl libcurl3 libpcre3-dev libssl-dev libxml2-dev libbz2-dev libgd2-xpm-dev libmcrypt-dev
</pre>
<br />
Curlオプションを利用する場合は、apt-getコマンドでlibcurl4-gnutls-devをインストールする必要があります。<br />
<pre class="brush:bash"># apt-get install libcurl4-gnutls-dev
</pre>
<br />
<h2 class="sub_title">Apacheインストール</h2>
「<a href="/2013/11/apache-246.html" title="apache install">Apache2.4.6のインストール手順</a>」を参照してください。
<br />
<h2 class="sub_title">Mysqlインストール</h2>
「<a href="/2013/10/mysql-5614.html" title="mysql install">MySQL 5.6.14のインストール手順</a>」を参照してください。
<br />
<h2 class="sub_title">PHPインストール</h2>
PHPをインストールします。(オプションは環境に合わせて、変更する必要があります。)
<pre class="brush:bash">
# mkdir -p /usr/local/php/php-5.5.5/conf
# cd /usr/local/src/
# wget -O 'php-5.5.5.tar.gz' http://us3.php.net/get/php-5.5.5.tar.gz/from/jp1.php.net/mirror
# tar xvf php-5.5.5.tar.gz
# cd php-5.5.5
# ./configure --prefix=/usr/local/php/php-5.5.5 \
--enable-bcmath \
--enable-calendar \
--enable-dba \
--enable-exif \
--enable-fpm \
--enable-ftp \
--enable-pdo \
--enable-gd-native-ttf \
--enable-mbstring \
--enable-mbregex \
--enable-shmop \
--enable-sigchild \
--enable-soap \
--enable-sockets \
--enable-sysvmsg \
--enable-wddx \
--enable-xml \
--enable-zip \
--with-apxs2=/usr/local/httpd/current/bin/apxs \
--with-freetype-dir=/usr/lib64 \
--with-config-file-path=/usr/local/php/php-5.5.5/conf \
--with-mysql=/usr/local/mysql/current \
--with-mysql-sock=/usr/local/mysql/current/tmp/mysql.sock \
--with-pdo-mysql=/usr/local/mysql/current \
--with-png-dir=/usr/lib64 \
--with-jpeg-dir=/usr/lib64 \
--with-zlib-dir=/usr/lib64 \
--with-libdir=lib64 \
--with-bz2 \
--with-curl \
--with-gd \
--with-gettext \
--with-libxml-dir=/usr/lib64 \
--with-mcrypt \
--with-mhash \
--with-mysqli \
--with-openssl \
--with-iconv \
--with-xmlrpc
# make
# make install
# cd /usr/local/php/
# ln -s php-5.5.5 current
</pre>
<br/>
PHP環境変数<code class="path">/etc/profile</code>を追加します。
<pre class="brush:bash">
# vi /etc/profile
export PHP_HOME=/usr/local/php/current
PATH=${PHP_HOME}/bin:${PATH}
# source /etc/profile
# php -v
</pre>
<br/>
PHP、PHP-FPMの設定ファイルと起動スクリプトを作成します。<br/>
<pre class="brush:bash">
# cp /usr/local/src/php-5.5.5/php.ini-production /usr/local/php/php-5.5.5/conf/php.ini
# cp /usr/local/src/php-5.5.5/sapi/fpm/php-fpm.conf /usr/local/php/php-5.5.5/etc/
# cp /usr/local/src/php-5.5.5/sapi/fpm/init.d.php-fpm /etc/init.d/php-fpm
# chmod 755 /etc/init.d/php-fpm
</pre>
<br/>
viを利用して<code class="path">php.ini</code>設定ファイルを編集します。<br/>
<pre class="brush:bash">
# vi /usr/local/php/current/conf/php.ini
date.timezone = "Asia/Tokyo"
memory_limit = 256M
post_max_size = 32M
upload_max_filesize = 32M
max_execution_time = 3600
max_input_time = 7200
error_log = /usr/local/php/current/var/log/php.log
Encoding追加(必要であれば)
mbstring.http_input = UTF-8
mbstring.encoding_translation = On
mbstring.internal_encoding = UTF-8
mbstring.substitute_character = "?"
default_charset = UTF-8
</pre>
<br/>
viを利用して<code class="path">php-fpm.conf</code>設定ファイルを編集します。<br/>
<pre class="brush:bash">
# vi /usr/local/php/current/etc/php-fpm.conf
pid = run/php-fpm.pid
error_log = log/php-fpm.log
pm.max_children = 70
pm.start_servers = 20
pm.min_spare_servers = 5
pm.max_spare_servers = 35
pm.max_requests = 500
rlimit_files = 102400
user = apache
group = apache
</pre>
<br/>
iniファイルの経路確認<br/>
<pre class="brush:bash">
# php -i | grep php.ini
</pre>
<br/>
php-fpmを起動します。<br/>
<pre class="brush:bash">
# /etc/init.d/php-fpm start
</pre>
<h2 class="sub_title">ApacheとPHP-FPM連動設定</h2>
Apacheの設定ファイルを変更します。<br/>
<pre class="brush:bash">
# vi /usr/local/httpd/current/conf/httpd.conf
以下の2行のコメントアウトを外します。
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so
拡張子がphpの場合、PHP-FPMへ処理させるようにRewrite設定
(127.0.0.1:9000は「/usr/local/php/current/etc/php-fpm.conf」の「listen = 127.0.0.1:9000」に設定した内容です。)
※VirtualHostを利用しても構いません。
<LocationMatch "^/.*\.php$">
ProxyPass fcgi://127.0.0.1:9000/usr/local/httpd/current/htdocs/
</LocationMatch>
</pre><br/>
<br/>
テストのため、<code class="path">index.php</code>生成<br/>
<pre class="brush:bash">
# echo '<?php echo phpinfo(); ?>' > /usr/local/httpd/current/htdocs/index.php
</pre>
<br/>
Apache再起動<br/>
<pre class="brush:bash">
# /usr/local/httpd/current/bin/apachectl restart
</pre>
<br />
ページから接続してみる…<br/>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi21sdTuDxQbVVei6_QsjiFaYmUvIEbcOpnBDXODJWULxWyiQf0N-Nqts7uwNMGgPaFnOQDF16TRo5XGAeK2me-3oAaLNcv7s9xKzFAmvXlMpuxhh4zXoorCtFSbD3ZG8vX4HKyW_zbT4g/s1600/11.jpg" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi21sdTuDxQbVVei6_QsjiFaYmUvIEbcOpnBDXODJWULxWyiQf0N-Nqts7uwNMGgPaFnOQDF16TRo5XGAeK2me-3oAaLNcv7s9xKzFAmvXlMpuxhh4zXoorCtFSbD3ZG8vX4HKyW_zbT4g/s1600/11.jpg" /></a>
<br/>unknownhttp://www.blogger.com/profile/15190790785934095924noreply@blogger.com0tag:blogger.com,1999:blog-8771673127918263645.post-66087034623298251002013-11-12T21:33:00.002+09:002014-01-22T10:14:39.072+09:00Apache2.4.6のインストール手順
<h2 class="sub_title">インストール環境とバージョン</h2>
今回、インストールするサーバとApacheのバージョンは以下のようになります。<br />
<table class="table_system_info01">
<tbody>
<tr>
<th>名前</th>
<th>バージョン</th>
<th>ダウンロード元</th>
</tr>
<tr>
<td class="td-subject">ubuntu</td>
<td>10.04.4(64bit)</td>
<td><a href="http://releases.ubuntu.com/lucid/" target="_blank" title="ubuntu-10.04.4">http://releases.ubuntu.com/lucid/</a></td>
</tr>
<tr>
<td class="td-subject">Apache Httpd Server</td>
<td>2.4.6</td>
<td><a href="http://httpd.apache.org/" target="_blank" title="Apache">http://httpd.apache.org/</a></td>
</tr>
<tr>
<td class="td-subject">Apache Runtime Runtime(APR)</td>
<td>1.4.8</td>
<td><a href="http://apr.apache.org/" target="_blank" title="APR">http://apr.apache.org/</a></td>
</tr>
<tr>
<td class="td-subject">APR-util</td>
<td>1.5.2</td>
<td><a href="http://apr.apache.org/" target="_blank" title="APR-util">http://apr.apache.org/</a></td>
</tr>
<tr>
<td class="td-subject">Perl Compatible Regular Expressions(PCRE)</td>
<td>8.33</td>
<td><a href="http://pcre.org/" target="_blank" title="PCRE">http://pcre.org/</a></td>
</tr>
<tr>
<td class="td-subject">Open-SSL</td>
<td>1.0.1e</td>
<td><a href="http://www.openssl.org/" target="_blank" title="Open-SSL">http://www.openssl.org/</a></td>
</tr>
</tbody>
</table>
<h2 class="sub_title">
インストールする前の準備作業</h2>
開発パッケージが設置されてない場合は、<code class="path">apt-get</code>でインストールする必要があります。<br />
<pre class="brush:bash"># apt-get install build-essential curl libcurl3 libpcre3-dev libssl-dev libxml2-dev libbz2-dev libgd2-xpm-dev libmcrypt-dev
</pre>
<br />
Apacheユーザを作成します。尚、既にApacheユーザが存在する場合はこの作業はスキップしても構いません。<br />
<pre class="brush:bash"># groupadd apache
# useradd -g apache -s /bin/false apache
</pre>
<br />
Apacheをインストールをする前にApr,Apr-Util,PCREを設置して置く必要があります。<br />
<h2 class="sub_title">
APRをインストールする</h2>
<pre class="brush:bash">
# mkdir /usr/local/apr
# cd /usr/local/src/
# wget http://archive.apache.org/dist/apr/apr-1.4.8.tar.gz
# tar xvf apr-1.4.8.tar.gz
# cd apr-1.4.8
# ./configure --prefix=/usr/local/apr/apr-1.4.8
# make && make install
# cd /usr/local/apr
# ln -s apr-1.4.8 current
</pre>
<br />
<h2 class="sub_title">
APR-UTILをインストールする</h2>
<pre class="brush:bash">
# mkdir /usr/local/apr-util
# cd /usr/local/src/
# wget http://archive.apache.org/dist/apr/apr-util-1.5.2.tar.gz
# tar xvf apr-util-1.5.2.tar.gz
# cd apr-util-1.5.2
# ./configure --prefix=/usr/local/apr-util/apr-util-1.5.2 --with-apr=/usr/local/apr/current
# make && make install
# cd /usr/local/apr-util
# ln -s apr-util-1.5.2 current
</pre>
<br />
<h2 class="sub_title">
PCREをインストールする</h2>
<pre class="brush:bash">
# mkdir /usr/local/pcre
# cd /usr/local/src/
# wget ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-8.33.tar.gz
# tar xvf pcre-8.33.tar.gz
# cd pcre-8.33
# ./configure --prefix=/usr/local/pcre/pcre-8.33
# make && make install
# cd /usr/local/pcre
# ln -s pcre-8.33 current
</pre>
<br />
<h2 class="sub_title">
OpenSSLをインストールする</h2>
<pre class="brush:bash">
# mkdir /usr/local/openssl
# cd /usr/local/src/
# wget http://www.openssl.org/source/openssl-1.0.1e.tar.gz
# tar xvf openssl-1.0.1e.tar.gz
# cd openssl-1.0.1e
# ./config --prefix=/usr/local/openssl/openssl-1.0.1e -fPIC
# make && make install
# cd /usr/local/openssl
# ln -s openssl-1.0.1e current
バージョン確認後、新しいバージョンに変更
# openssl version
# mv /usr/bin/openssl /usr/bin/openssl.old
# ln -s /usr/local/openssl/current/bin/openssl /usr/bin/openssl
# ls -al /usr/bin/openssl
# openssl version
</pre>
<br />
<h2 class="sub_title">
httpd(Apache)をインストールする。</h2>
※configureオプションは変更必要<br/>
<pre class="brush:bash">
# mkdir /usr/local/httpd
# cd /usr/local/src/
# wget http://archive.apache.org/dist/httpd/httpd-2.4.6.tar.gz
# tar xvf httpd-2.4.6.tar.gz
# cd httpd-2.4.6
# ./configure \
--prefix=/usr/local/httpd/httpd-2.4.6 \
--enable-so \
--enable-ssl \
--enable-rewrite \
--enable-proxy \
--enable-proxy-http \
--enable-proxy-connect \
--with-mpm=prefork \
--disable-imagemap \
--with-apr=/usr/local/apr/current \
--with-apr-util=/usr/local/apr-util/current \
--with-pcre=/usr/local/pcre/current \
--with-ssl=/usr/local/openssl/current
# make && make install
# cd /usr/local/httpd
# ln -s httpd-2.4.6 current
# chown -R apache:apache /usr/local/httpd/
</pre>
<br />
Apache起動
<pre class="brush:bash">
# /usr/local/httpd/current/bin/apachectl start
# ps -ef | grep httpd
起動されなかった場合はログを確認し、
# cat /usr/local/httpd/current/logs/error_log
AH01177: Failed to lookup provider 'shm' for 'slotmem': is mod_slotmem_shm loaded??
というエラーが発生した場合
# vi /usr/local/httpd/current/conf/httpd.conf
の「LoadModule slotmem_shm_module modules/mod_slotmem_shm.so」部分のコメントアウトを解除する
</pre>
<br/>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhnLkkjPJ7fSQqEFlbyc3HwJ6qtQCXh_9L-jqRKrKUNLFdyaNv0-YE2CTMgWE1ZUNuNmxU9pF6mcBAwV6_Z8Yq6k1O9Spy-PClRX4_Q1fQpOfsvrbiQbn6cQVBJByJ6FyEs7nIqVdR7fp0/s1600/aa.jpg" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhnLkkjPJ7fSQqEFlbyc3HwJ6qtQCXh_9L-jqRKrKUNLFdyaNv0-YE2CTMgWE1ZUNuNmxU9pF6mcBAwV6_Z8Yq6k1O9Spy-PClRX4_Q1fQpOfsvrbiQbn6cQVBJByJ6FyEs7nIqVdR7fp0/s1600/aa.jpg" /></a>
<br/>unknownhttp://www.blogger.com/profile/15190790785934095924noreply@blogger.com0tag:blogger.com,1999:blog-8771673127918263645.post-89197535631683490022013-11-06T22:27:00.000+09:002013-12-05T10:12:06.061+09:00JSPのCookie暗号化<a id="_top"></a>
<h2 class="sub_title">
Cookieとは?
</h2>
Cookieはクライアントのブラウザのメモリ(ブラウザを終了時にはHDDへ)にサーバとの通信における持続的な情報を保持しています。<br />
主にショッピングサイトにおけるカートやログイン状態、告配信業者などがクライアントの詳細なアクセス履歴を取得する用途で使われます。<br />
<br />
<h2 class="sub_title">
Cookie情報を暗号化して、セキュリティ向上へ…
</h2>
Cookieは様々な分野で便利に使える反面、簡単に設定した値の確認・改ざんが出来るため、何らかのセキュリティの対応をせず、値をそのままCookieに設定すると<u>権限のないページへの接続</u>、<u>不正ログイン</u>、<u>xss</u>、<u>sql injection</u>などの攻撃の対象になります。<br />
<br />
今回は、Cookieを簡単に改ざん出来ないように暗号化するソースを整理してみました。<br /><br />
<div>
<b>・Cookieに値を設定する流れ</b>
<ol style="margin-top:5px;">
<li>CookieDataクラスに設定したい値をセットする(MapもしくはBean)<br/>Class:<a href="#CookieData">CookieData.java</a></li>
<li>CookieDataクラスをシリアライズ(serialize) ⇒ 暗号化 ⇒ HEX に変換する<br/>Class:<a href="#CookieSecurity">CookieSecurity.java</a></li>
<li>HEXデータをミックスし、Cookieにセットする<br/>Class:<a href="#CookieUtil">CookieUtil.java</a></li>
</ol>
</div>
<div>
<b>・Cookieから値を取得する流れ</b>
<ol style="margin-top:5px;">
<li>Cookieから値を取得する</li>
<li>取得した値をアンミックス(ミックスされてない状態に)する</li>
<li>HEX ⇒ 復号化 ⇒ デシリアライズ(deserialize)しObjectに変換する</li>
</ol>
</div>
<br/><br/>
<a id="CookieSecurity"></a>
・[CookieSecurity.java]:クラスをシリアライズ、デシリアライズ、暗号化、復号化するクラスです。<br/>
>><a href="https://sites.google.com/site/kongbab04/file/CookieSecurity.java">CookieSecurity.javaダウンロード</a>
<pre class="brush:java">
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
/**
* <PRE>
* Filename : CookieSecurity.java
* Class : xxx.xxx.CookieSecurity
* Function :
* Comment : Cookieを暗号化、復号化などに使われる
* History : 2013/11/01, su min park, develop
*
* </PRE>
* @version 1.0
* @author su min park
* @since JDK 1.7
*/
public class CookieSecurity {
private static CookieSecurity instance = new CookieSecurity();
private final String CIPHER_ALGORITHM = "AES";
private final String CIPHER_TRANSFORMATION = CIPHER_ALGORITHM + "/ECB/PKCS5Padding";
private Cipher _encrypt;
private Cipher _decrypter;
private CookieSecurity() {
String password = "12345678901$3456"; // パスワードは16文字で
//パスワード生成
Key key = createKey(password);
try {
//暗号化モジュール初期化
initializeCipher(key);
} catch (InvalidKeyException e) {
System.out.println("xxx.xxx.CookieSecurity_constructor : InvalidKeyException " + e.getMessage());
} catch (NoSuchAlgorithmException e) {
System.out.println("xxx.xxx.CookieSecurity_constructor : NoSuchAlgorithmException " + e.getMessage());
} catch (NoSuchPaddingException e) {
System.out.println("xxx.xxx.CookieSecurity_constructor : NoSuchPaddingException " + e.getMessage());
} finally {
password = null;
}
}
/**
* シングルトン・パターン(Singleton Pattern)
*
* @return CookieSecurity instance
*/
public static CookieSecurity getInstance() {
return instance;
}
/**
* HEXデータを復号化し、そのデータを元にオブジェクトを生成する<br/>
* Cookieに設定されていた値をこのメソッドを利用してClassに変換する。
* @param hexData String 復号化するHexデータ
* @return Object 成功した場合はObject、失敗した場合はnull
*/
public Object getHexToObj(String hexData) {
if (hexData == null) { return null; }
try {
//復号化
byte[] decrypted = decrypt(hexToByteArray(hexData));
//シリアライズ
return objFromString(new String(decrypted));
} catch (ClassNotFoundException e) {
System.out.println("xxx.xxx.CookieSecurity_getCookieData : ClassNotFoundException " + e.getMessage());
} catch (IOException e) {
System.out.println("xxx.xxx.CookieSecurity_getCookieData : IOException " + e.getMessage());
} catch (Exception e) {
System.out.println("xxx.xxx.CookieSecurity_getCookieData : Exception " + e.getMessage());
}
return null;
}
/**
* 暗号化するためのメッソド<br/>
* CookieDataクラスをシリアライズし、暗号化する
* @param cookieData CookieData データがセットされたcookieDataクラス
* @return String 成功した場合はString、失敗した場合はnull
*/
public String getCookieDataToHex(CookieData cookieData) {
if (cookieData == null) { return null; }
String hexData = null;
try {
//シリアライズ
String seriStr = objToString(cookieData);
//暗号化
byte[] encrypted = encrypt( seriStr.getBytes() );
hexData = byteArrayToHex(encrypted);
} catch (IOException e) {
System.out.println("xxx.xxx.CookieSecurity_setCookieData : IOException " + e.getMessage());
}
return hexData;
}
/**
* byte[] to hex : unsigned byte(バイト) 配列を16HEXの文字列に変更
*
* @param ba byte[]
* @return
*/
public String byteArrayToHex(byte[] ba) {
if (ba == null || ba.length == 0) {
return null;
}
StringBuffer sb = new StringBuffer(ba.length * 2);
String hexNumber;
for (int x = 0; x < ba.length; x++) {
hexNumber = "0" + Integer.toHexString(0xff & ba[x]);
sb.append(hexNumber.substring(hexNumber.length() - 2));
}
return sb.toString();
}
/**
* hex to byte[] : 16HEX 文字列をバイトに変換する
*
* @param hex hex string
* @return
*/
public byte[] hexToByteArray(String hex) throws Exception {
if (hex == null || hex.length() == 0) { return null; }
byte[] ba = new byte[hex.length() / 2];
for (int i = 0; i < ba.length; i++) {
ba[i] = (byte) Integer.parseInt(hex.substring(2 * i, 2 * i + 2), 16);
}
return ba;
}
/**
* bit数のパスワードを生成する。
* @param password String パスワード
* @param bitNum int Bit数
* @return Key 生成されたkey
*/
public Key createKeyRandom(String password, int bitNum) {
SecureRandom random = new SecureRandom(password.getBytes() );
byte buff[] = new byte[bitNum >> 3];
random.nextBytes(buff);
return new SecretKeySpec(buff, CIPHER_ALGORITHM);
}
/**
* SecretKeySpecを利用してkeyを生成する<br/>
* パスワードは16文字
* @param password String パスワード
* @return Key 生成されたkey
*/
public Key createKey(String password) {
return new SecretKeySpec(password.getBytes(), CIPHER_ALGORITHM);
}
/**
* 暗号化・復号化に必要なクラスを初期化する
* パスワードは16文字
* @param key Key パスワード
*/
public void initializeCipher(Key key) throws NoSuchAlgorithmException,
NoSuchPaddingException, InvalidKeyException {
_encrypt = Cipher.getInstance(CIPHER_TRANSFORMATION);
_encrypt.init(Cipher.ENCRYPT_MODE, key);
_decrypter = Cipher.getInstance(CIPHER_TRANSFORMATION);
_decrypter.init(Cipher.DECRYPT_MODE, key);
}
/**
* 暗号化する。
* @param encrypt_byte byte[] バイトデータ
* @return byte[] 暗号化された結果
*/
public byte[] encrypt(byte[] encrypt_byte) {
try {
return _encrypt.doFinal(encrypt_byte);
} catch (Exception exc) {
exc.printStackTrace();
return null;
}
}
/**
* 復号化する。
* @param decrypt_byte byte[] バイトデータ
* @return byte[] 復号化された結果
*/
public byte[] decrypt(byte[] decrypt_byte) {
try {
return _decrypter.doFinal(decrypt_byte);
} catch (Exception exc) {
exc.printStackTrace();
return null;
}
}
/**
* Base64文字列からオブジェクト(class)を読み込む
* @param base64 String オブジェクトに変換する文字列(Base64文字列)
* @return Object 変換されたオブジェクト
* @throws IOException シリアライズ途中エラーが発生した場合
* @throws ClassNotFoundException readObject途中エラーが発生した場合
*/
private Object objFromString( String base64 ) throws IOException ,
ClassNotFoundException {
/** commons-codecライブラリーを使わない場合 */
//byte [] data = Base64Coder.decode( s );
byte [] data = Base64.decodeBase64(base64);
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(data));
Object o = ois.readObject();
ois.close();
return o;
}
/**
* オブジェクト(class)を文字列に変換する。<br/>
* 文字列に変換されるclassは Serializableを継承している必要がある。 (implements Serializable)
* @param obj Serializable オブジェクトシリアライズ(Object Serialization)するオブジェクト
* @return String シリアライズされた文字列
* @throws IOException シリアライズ途中エラーが発生した場合
*/
private String objToString( Serializable obj ) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = null;
try {
oos = new ObjectOutputStream( baos );
oos.writeObject(obj);
} finally {
if (oos != null ) oos.close();
}
return new String( Base64.encodeBase64(baos.toByteArray(), false) );
/* commons-codecライブラリーを使わない場合 */
//return new String( Base64Coder.encode( baos.toByteArray() ) );
}
}
</pre>
<p class="gotoTop"><a href="#_top">TOPへ</a></p>
<a id="CookieUtil"></a>
・[CookieUtil.java]:実際のCookieに値をSetしたりGetしたりするためのクラスです。<br/>
>><a href="https://sites.google.com/site/kongbab04/file/CookieUtil.java">CookieUtil.javaダウンロード</a>
<pre class="brush:java">
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* <PRE>
* Filename : CookieUtil.java
* Class : xxx.xxx.CookieUtil
* Function :
* Comment : CookieにSet,Getするためのクラス
* History : 2013/11/01, su min park, develop
*
* </PRE>
* @version 1.0
* @author su min park
* @since JDK 1.7
*/
public class CookieUtil {
private CookieSecurity cookieSecurity = CookieSecurity.getInstance();
private static CookieUtil instance = new CookieUtil();;
private final String SEC_COOKIE_NM1 = "SEC_CN1";
private final String SEC_COOKIE_NM2 = "SEC_CN2";
private final String CK_CHECK = "CK_CHECK";
private final int MIX_SIZE1 = 15;
/**
* シングルトン・パターン(Singleton Pattern)
*
* @return CookieUtil instance
*/
public static CookieUtil getInstance() {
return instance;
}
/**
* cookieにセットする(オーバーロード)
* @param response HttpServletResponse レスポンス
* @param ckNm String Cookie名称
* @param ckVal String Cookie名称の値
* @throws Exception
*/
public void setCookie(HttpServletResponse response, String ckNm, String ckVal) throws Exception {
setCookie(response, ckNm, ckVal, null, -1, false);
}
public void setCookie(HttpServletResponse response, String ckNm, String ckVal, int maxAge) throws Exception {
setCookie(response, ckNm, ckVal, null, maxAge, false);
}
public void setCookie(HttpServletResponse response, String ckNm, String ckVal, int maxAge, boolean sec) throws Exception {
setCookie(response, ckNm, ckVal, null, maxAge, sec);
}
public void setCookie(HttpServletResponse response, String ckNm, String ckVal, String domain) throws Exception {
setCookie(response, ckNm, ckVal, domain, -1, false);
}
/**
* cookieにセットする
* @param response HttpServletResponse レスポンス
* @param ckNm String Cookie名称
* @param ckVal String Cookie名称の値
* @param domain String Cookieを設定するドメイン
* @param maxAge int Cookieの維持時間 Default = -1(ブラウザを閉じたとき)
* @param sec boolean セキュア(SSL)仕様有無 Default = false
* @throws Exception
*/
public void setCookie(HttpServletResponse response, String ckNm, String ckVal, String domain, int maxAge, boolean sec) throws Exception {
Cookie cookie = new Cookie(ckNm, ckVal);
if (domain != null && domain.length() > 0) {cookie.setDomain(domain);}
cookie.setPath("/");
cookie.setSecure(sec);
cookie.setMaxAge(maxAge);
response.addCookie(cookie);
}
/**
* CookieDataタイプの情報を暗号化し、Cookieにセットする。
* @param response HttpServletResponse レスポンス
* @param cookieData CookieData Cookieに設定する値
* @throws Exception setSecCookie hexData is null
*/
public void setSecCookie(HttpServletResponse response, CookieData cookieData) throws Exception {
if (response == null || cookieData == null) { return; }
//現在の日時(セキュリティチェックのため)
java.text.SimpleDateFormat format = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:SS:ss");
String secUpdDt = format.format(new java.util.Date());
//cookieDataに更新時間を更新
cookieData.setSecUpdDt(secUpdDt);
//cookieDataをHexに変換し、ミックスする
String hexCookieData = cookieSecurity.getCookieDataToHex(cookieData);
hexCookieData = getMixCookieValue(hexCookieData, false);
if (hexCookieData == null) {
throw new Exception("setSecCookie hexData is null ");
}
//成功した場合、Cookieの修正日も一緒にCookieにセットする
byte[] encrypted = cookieSecurity.encrypt( secUpdDt.getBytes() );
String hexSecUpdDt = getMixCookieValue(cookieSecurity.byteArrayToHex(encrypted), false);
setCookie(response, CK_CHECK, hexSecUpdDt);
//Cookieにセットする
int dataSize = hexCookieData.length();
setCookie(response, SEC_COOKIE_NM1, hexCookieData.substring(0, dataSize));
setCookie(response, SEC_COOKIE_NM2, hexCookieData.substring(dataSize));
}
/**
* setSecCookieを利用して設定した情報を復号化し、CookieData形式で返す
* @param request HttpServletRequest リクエスト
* @return CookieData 結果データ
* @throws Exception getSecCookie SecUpdDt Check fail
*/
public CookieData getSecCookie(HttpServletRequest request) throws Exception {
/** get cookies **/
Cookie[] headerCookies = request.getCookies();
int headerCookisSize = 0;
if (headerCookies != null) { headerCookisSize = headerCookies.length; }
CookieData cookieData = null;
String secCookieValue1 = "";
String secCookieValue2 = "";
String cookieCheck = "";
for (int hcsInx = 0; hcsInx < headerCookisSize; hcsInx++) {
Cookie headerCookie = headerCookies[hcsInx];
if (headerCookie.getName().equals(SEC_COOKIE_NM1)) {secCookieValue1 = headerCookie.getValue();}
else if (headerCookie.getName().equals(SEC_COOKIE_NM2)) {secCookieValue2 = headerCookie.getValue();}
else if (headerCookie.getName().equals(CK_CHECK)) {cookieCheck = headerCookie.getValue();}
}
String secCookieValue = secCookieValue1 + secCookieValue2;
if (secCookieValue.length() > 0) {
secCookieValue = getMixCookieValue(secCookieValue, true);
cookieData = (CookieData)cookieSecurity.getHexToObj(secCookieValue);
//修正日のデータを取得する
byte[] decrypted = cookieSecurity.decrypt(cookieSecurity.hexToByteArray(getMixCookieValue(cookieCheck, true)));
String cookieCheckRst = (decrypted == null ? null : new String(decrypted));
if (cookieData != null) {
if (cookieCheckRst == null) {throw new Exception("getSecCookie cookieCheckRst is null ");}
if (!cookieCheckRst.equals(cookieData.getSecUpdDt())) {
throw new Exception("getSecCookie SecUpdDt Check fail ");
}
}
}
return cookieData;
}
/**
* Cookieにset,getするデータを混ぜる<br/>
* 混ぜる方式は決める必要がある
* @param cookieValue String ミックスする文字列
* @param isUnMixed boolean Mixする(false)かMixされたデータを元に戻す(true)かの判定
* @return 結果データ
*/
private String getMixCookieValue(String cookieValue, boolean isUnMixed) {
if (cookieValue == null || cookieValue.length() < (MIX_SIZE1+1)) {
return cookieValue;
}
if (isUnMixed) {
cookieValue = cookieValue.substring(MIX_SIZE1) + cookieValue.substring(0, MIX_SIZE1);
} else {
int cutInt = cookieValue.length() - MIX_SIZE1;
cookieValue = cookieValue.substring(cutInt) + cookieValue.substring(0, cutInt);
}
return cookieValue;
}
/**
* 全てのCookieを削除する
* @param request HttpServletRequest リクエスト
* @param response HttpServletResponse レスポンス
* @return 処理結果
*/
public static boolean removeAllCookies(HttpServletRequest request, HttpServletResponse response){
if (request == null) { return false; }
String url = request.getRequestURL().toString().replace("http://", "").replace("https://", "");
int cutInx = url.indexOf("/");
url = url.substring(0, (cutInx == -1 ? url.length() : cutInx));
Cookie[] initHeaderCookies = request.getCookies();
if (initHeaderCookies != null) {
for (int inx = 0; inx < initHeaderCookies.length; inx++) {
String cookieNm = initHeaderCookies[inx].getName();
Cookie cookie = new Cookie(cookieNm, "");
cookie.setMaxAge(0);
cookie.setDomain(url);
response.addCookie(cookie);
System.out.println(request.getRemoteAddr() + " : cookieUtil delete : " + cookieNm);
cookie.setDomain("." + url);
response.addCookie(cookie);
}
}
return true;
}
}
</pre>
<p class="gotoTop"><a href="#_top">TOPへ</a></p>
<a id="CookieData"></a>
・[CookieData.java]:値を保持するクラスです。(値はCookieに保存するのではなく、Class(Bean)に設定してシリアライズ⇒暗号化するため)<br/>
>><a href="https://sites.google.com/site/kongbab04/file/CookieData.java">CookieData.javaダウンロード</a>
<pre class="brush:java">
import java.io.Serializable;
/**
* <PRE>
* Filename : CookieData.java
* Class : xxx.xxx.CookieData
* Function : get, set
* Comment : Cookieを保存しておくクラス
* CookieデータはMAPもしくはBeanで処理する。
* Beanの場合、変数を追加したりすると追加する前のCookie情報と衝突するので、
* 管理が必要。
* History : 2013/11/01, su min park, develop
*
* </PRE>
* @version 1.0
* @author su min park
* @since JDK 1.7
*/
class CookieData implements Serializable {
/**
* Cookieを暗号化する際にユーザのIPも一緒に指定することで、セキュリティの向上が出来る。
* ※但し、(固定IPではないので)IPが変更された場合もう一度ログインして貰ったりする(アプリの)機能が必要である */
private String secUserIp = ""; //Cookieを暗号化する際にその都度、値が変わるためupdDt追加
/** Cookieを更新する際にsecUpdDtも更新する。Cookieを取得した時、そのクッキーの改ざん有無などのチェックに使われる */
private String secUpdDt = "";
//Cookieに設定される変数(Mapタイプも構わない)
private String svcNm = "";
private String svcKey = "";
private String svcMemNm = "";
private String svcMemKey = "";
private String svcMemKey2 = "";
//get, set
public String getSecUserIp() { return secUserIp; }
public void setSecUserIp(String secUserIp) { this.secUserIp = secUserIp; }
public String getSecUpdDt() { return secUpdDt; }
public void setSecUpdDt(String secUpdDt) { this.secUpdDt = secUpdDt; }
public String getSvcNm() { return svcNm; }
public void setSvcNm(String svcNm) { this.svcNm = svcNm; }
public String getSvcKey() { return svcKey; }
public void setSvcKey(String svcKey) { this.svcKey = svcKey; }
public String getSvcMemNm() { return svcMemNm; }
public void setSvcMemNm(String svcMemNm) { this.svcMemNm = svcMemNm; }
public String getSvcMemKey() { return svcMemKey; }
public void setSvcMemKey(String svcMemKey) { this.svcMemKey = svcMemKey; }
/**
public String toString(){
return "SomeClass instance says: Don't worry, " +
"I'm healty. Look, my data is svcNm= " +svcNm + ", svcKey = " + svcKey + ", svcMemNm = " + svcMemNm;
}
*/
}
</pre>
<p class="gotoTop"><a href="#_top">TOPへ</a></p>
<br/>
<h2 class="sub_title">
テストのために…
</h2>
以下のロジックを利用するとテストが出来ます。<br/>
<pre class="brush:java">
CookieData cookieData= null;
CookieUtil cookieUtil = CookieUtil.getInstance();
try {
cookieData = cookieUtil.getSecCookie(request);
/* データをGET */
} catch (Exception e) {
//エラー処理
e.printStackTrace();
}
if (cookieData == null) {
System.out.println("cookieData Create");
cookieData = new CookieData();
}
//Cookie保存処理
cookieData.setSvcKey("--2---");
try {
cookieUtil.setSecCookie(response, cookieData);
} catch (Exception e) {
//エラー処理
e.printStackTrace();
}
</pre>
<p class="gotoTop"><a href="#_top">TOPへ</a></p>
<br/>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgU03SG4SNLvr5AuiTG0TvaKIdPRuBGJwa53lleVeg2LyzIYNQkm8qc8G5dgIdIdJd3pdq3dFrXxC_t6kDsAW7z7NB1LB5Ficmke15rl9W31fJFh-4dPrgm_ouvc_Msjfx1-aAwUO3ad5k/s1600/1.jpg" imageanchor="1" ><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgU03SG4SNLvr5AuiTG0TvaKIdPRuBGJwa53lleVeg2LyzIYNQkm8qc8G5dgIdIdJd3pdq3dFrXxC_t6kDsAW7z7NB1LB5Ficmke15rl9W31fJFh-4dPrgm_ouvc_Msjfx1-aAwUO3ad5k/s1600/1.jpg" /></a>
<br/><br/>
<br/>
※【<b>java.security.InvalidKeyException: Illegal key size or default parameters</b>】エラーが発生する場合は、
<code class="path">local_policy.jar</code>, <code class="path">US_export_policy.jar</code>ライブラリーを
更新してください。<br/><br/>
・ライブラリー位置:<b>/Java設置ディレクトリ/jre/lib/security</b><br/>
例)/usr/local/java/jre/lib/security<br/>
・ダウンロードする方法:<b>設置されているJavaのバージョンを確認し、Sunサイトから<code class="path">JCE</code>をダウンロード</b><br/><br/>
過去のバージョンをダウンロードする方法は以下のようになります。(ダウンロードする方法は変わる可能性があります。)<br/>
<a href="http://www.oracle.com/technetwork/java/javase/downloads/index.html" target="_blank">http://www.oracle.com/technetwork/java/javase/downloads/index.html</a><br/>
↓<br/>
Previous Releases ボタン<br/>
↓<br/>
Java Platform Technologies ボタン<br/>
↓<br/>
設置されているJavaバージョンのJCEをダウンロード<br/>
↓<br/>
Zip中身の<code class="path">local_policy.jar</code>, <code class="path">US_export_policy.jar</code>ファイルを<code class="path">/Java設置ディレクトリ/jre/lib/security</code>に上書き<br/>
<br/>unknownhttp://www.blogger.com/profile/15190790785934095924noreply@blogger.com0