2014年12月18日 星期四

解決 Splunk Forwader 傳送 WLS Log to Splunk Server 中文亂碼問題

這個問題困擾了我很久,雖然有比較不好的解法(效率較差,such as FTP)
但現在單純修改 Splunk Forwarder內的設定即可

一開始看官網,很容易會以為是要修改 Splunk Server上的設定
實際上是要修改 Splunk Forwarder的設定即可
首先至 Splunk Forwarder安裝的目錄下 /etc/system/default
複製一份 props.conf 至 /etc/system/local [這是 Splunk 官方的建議]
就是以後修改,以修改此 props.conf為主,不要修改 default.conf

在檔案的最下方,新增如下2行(注意大小寫)

[wls_log]
CHARSET = BIG5

*****這兩行的意思是,傳輸 sourcetype=wls_log的檔案,將編碼設定 BIG5*****

將Splunk Forwarder停止
登入至Splunk Server,刪除先前由此台WLS Log Server所傳進來的檔案

sourcetype=wls_log | delete  (注意,admin必須事先設定擁有刪除的權限)

重新啟動 Splunk Server

啟動 Splunk Forwarder

建立一筆有中文的 Log, 至Splunk Server查詢吧!

2014年11月30日 星期日

Using Oracle jrockit jConsole monitor WebLogic with remoto server

最近在研究使用jmx來monitor WebLogic
首先我使用的WebLogic版本是10.3.3,安裝時設定成 Production mode
若有安裝過的話,通常 Oracle建議 Production mode使用 jrockit ,developer mode則用 jdk
因此我們現在應該是透過 jrockit 來 monitor,首先找到 jConsole的執行檔
它位於你安裝 jrockit 所在的目錄下/bin裡面

找到後,你可以直接點二下執行,但這是採用 Local 的方式去monitor,會抓取你目前的 java instance,這邊我們不討論。

那麼該如何使用 remote 的方式去 monitor 呢?
首先至你想要 monitor 的 WLS Server 開啟 WLS Admin Console-->伺服器-->your server name-->通訊協定-->啟用 IIOP(勾選)-->點選進階後設定 IIOP預設帳密,如圖


接著在你的 cmd 下 使用指令呼叫 jConsole吧!
我這邊示範是基本的呼叫方式,呼叫完後一樣會出現 jConsole的視窗
請在上面打上
service:jmx:iiop://hostname:port/jndi/weblogic.management.mbeanservers.runtime
請自行替換你的 hostname and port,下面就是你剛剛設定的IIOP帳密
如圖:

如果看到上圖畫面,就代表你成功嘍!,接著你就可以點選你想要看的資訊了。



2014年11月25日 星期二

處理Splunk 與 WebLogic Log 時間不一致問題

最近使用Splunk導入WebLogic時發現時間不夠一致,甚至假設我自己撰寫程式來印出Log時,在Log檔裡顯示的時間是正確的,但在Splunk中卻被視為同一時間,由於我的Splunk Search非常依賴時間來做查詢條件,因此為了解決這種問題,我決定為WLS Log的時間新增一個欄位(Field)叫作 log_time。
另外WLS Log在我的Log File中原本時間顯示為中文,但是進入Splunk時,卻變成了亂碼,這個問題我試過不少方法也暫時無法解決(我是透過Forwarder,Splunk & WLS不同台機器)。
於是我試圖先讓WLS Log時間變成單純的數字日期,而不在出現中文。




步驟依序如上面圖示,至WebLogic AdminConsole中點選 伺服器-->欲修改的Log伺服器所在位置-->點選日誌記錄-->進階,在「日期格式樣式」把原本有中文 時分秒的設定 改成
 yyyy/M/d HH'-'mm'-'ss'-' z
重新啟動 Server,再至Log檔觀察,就可以發現時間格式改變了。
實際至Splunk 觀察也是一樣,另外我已經定義好 log_time 欄位的 pattern了如圖
如上圖所示,藍色是Splunk定義的時間,而紅色部分是Log的真實時間,以及我定義log_time欄位的時間,而為了使用我定義的時間來做查詢,在程式呼叫curl指令時需要將時間作轉換,注意"2014-11/26" 與 "10-37-33"之間是有空白的。
程式如下

Calendar calendar1 = Calendar.getInstance();
System.out.println("calendar1 : " + calendar1.getTime());
calendar1.add(Calendar.MINUTE, -5);
System.out.println("calendar2 : " + calendar1.getTime());
Date date = calendar1.getTime();
SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy/MM/dd HH-mm-ss");
String date1 = DATE_FORMAT.format(date);
System.out.println("Date1 : " + date1);
String[] tokens = date1.split(" ");
    for (String token:tokens) {
  System.out.println(token);
}
String finalDate = tokens[0]+"\\%20"+tokens[1];
System.out.println("finalDate: " + finalDate);
String log_time = "2014/11/25\\%2014-21-02";

注意我在程式碼第三行,已將實際時間減5分鐘,因為我的目的是查詢現在時間與前5分鐘之間的Log(假設Splunk時間若正確等同於Splunk執行earliest="-5m"),而最後得到的樣式就會像程式最後一行一樣  "2014/11/25\\%2014-21-02";
細心的你會發現我們中間的空白是使用\\%20取代,這是在Windows執行Java的作法

之後就是Splunk厲害的地方,他可以使用String表示時間後,依然可以比較時間,如下圖

因此我們可以放心的使用log_time當作時間基準查詢了,另外介紹Windows2003時間同步
我將Splunk Server與 WLS Server同步至我的DC Server
w32tm /config /manualpeerlist:dc.test.com.tw /syncfromflags:MANUAL
w32tm /config /update
w32tm /resync

讓時間更一致,WLS Log實在不夠精準,看來目前使用自定義的欄位查詢最精準。

**********************更好的方式  最新更新*******************************
修改WLS Date Format Pattern,修改成  yy/M/d HH':'mm':'ss  like as  14/12/12 16:52:09
重新啟動 WLS Server,則Splunk就可以認出正確的時間格式,並將其傳入 _time default index中,已 _time 的時間正確的話 ,就可以 如常的 使用 Splunk Time Modifier 
ex: earliest="-5m" or latest








Java Call Splunk Restful Service with curl On Linux

之前文章已經實現了使用Java搭配Curl and openssl 來呼叫 Splunk Restful API
但那是透過 CMD 也就是 Windows平台,現在假設我們程式需要佈署在Linux平台上
則語法也會不同。首先在Linux平台上有個好處,那就是大多數已經內建了curl
但是使用Java呼叫curl時,我必須先知道 curl 需在哪執行,你可以在Linux 下執行which curl
一樣使用ProcessBuilder
程式範例如下:
import java.io.*;
import java.util.*;

public class ProcessBuilderTest {
  public static void main(String args[]) 
     throws InterruptedException,IOException 
  {
  final List<String> commands = new ArrayList<String>();                

commands.add("/usr/bin/curl"); 
 commands.add("-k"); 
 commands.add("-u"); 
 commands.add("admin:hello"); 
 commands.add("-s"); 
 commands.add("https://localhost:8089/services/search/jobs/"+sid+"/results/");

ProcessBuilder builder = new ProcessBuilder(commands);
File dir = new File("/home");
builder.directory(dir);

    final Process process = builder.start();
    
    InputStream is = process.getInputStream();
    InputStreamReader isr = new InputStreamReader(is);
    BufferedReader br = new BufferedReader(isr);
    String line;
    while ((line = br.readLine()) != null) {
      System.out.println(line);
    }
    System.out.println("Program terminated!");
  }
}

如上面程式所示,只要能先得到Splunk Restful 回傳的 SID後加入程式,即可得到與Splunk Server上搜尋一樣的結果。
此外由於程式可能需要同時於Windows及Linux執行,所以可以使用下面程式來判別以決定command的組合模式
private static String OS = System.getProperty("os.name").toLowerCase();

private static boolean isWindows() {  
return (OS.indexOf("win") >= 0);
}
private static boolean isUnix() { 
return (OS.indexOf("nix") >= 0 || OS.indexOf("nux") >= 0 || OS.indexOf("aix") > 0 );

當然Windows與Linux上指令上還有一些小差別,另外Linux可以使用空白,但Windows要使用%20或一些需要使用跳脫字元的用法,才可正確執行呼叫CURL,歡迎大家一起研究討論。

}

2014年7月7日 星期一

Java呼叫CMD的另一種方式使用ProcessBuilder(calling Splunk Restful API)

前幾天的文章已經可以順利的使用Java呼叫CMD
現在介紹另一種方式是使用ProcessBuilder呼叫,搭配前一篇Java處理字串中含有雙引號的字串
可以完整的呈現不使用批次檔,不用下 cd command to executing directory(可直接設定cmd執行目錄)

程式碼如下

import java.io.*;
import java.util.*;

public class ProcessBuilderTest {
  public static void main(String args[]) 
     throws InterruptedException,IOException 
  {
 final List<String> commands = new ArrayList<String>();                

 commands.add("cmd.exe");
 commands.add("/C");
 commands.add("curl -k -u admin:!QAZxsw2 -s https://localhost:8089/services/search/jobs/ -d\"search=| savedsearch selectFromDual\"");
 //在Java中若是字串中含有字串例如 " "name" " 應表示為 "\"name\" "
 //commands.add("curl -k -u admin:!QAZxsw2 -s https://localhost:8089/services/search/jobs/"+sid+"/results/");
 commands.add("start");

    //ProcessBuilder builder = new ProcessBuilder("cmd.exe", "/C", "start");
ProcessBuilder builder = new ProcessBuilder(commands);
File dir = new File("C:\\Users\\Peter\\Desktop\\openssl-0.9.8h-1-bin\\bin");
builder.directory(dir);

    final Process process = builder.start();
    
    InputStream is = process.getInputStream();
    InputStreamReader isr = new InputStreamReader(is);
    BufferedReader br = new BufferedReader(isr);
    String line;
    while ((line = br.readLine()) != null) {
      System.out.println(line);
    }
    System.out.println("Program terminated!");
  }
}

Java如何在字串中含有另一個雙引號的字串

最近遇到這樣的情形,使用cURL工具 search Splunk時 search的字串中含有另一個字串
想要以Java的方式呈現,都會出現錯誤!

今天終於找到方法了

如下程式碼

public class Test{  
  
    public static void main(String[] args){  
        String str1 = "\"Peter\"";//字串兩邊含有雙引號
        String str2 = "Peter \"is\" boy";//字串中間含有雙引號
        String str3 = "\\Peter";//使用\字符可以使字串包含其他字串  
          
        System.out.println("字串一:" + str1);  
        System.out.println("字串二:" + str2);  
        System.out.println("字串三:" + str3);  
    }  
}

執行結果

請注意看 字串一的寫法 在中間的字串雙引號前 先加一個 \  雙引號結尾前 再加一個 \

參考Java处理本身包含双引号的String

2014年7月3日 星期四

使用 Java 呼叫 cmd.exe 並下指令(下)-Splunk Java Solution

跟著上一篇文章,除了讓CMD幫我們做事情外,我還需要將資料直接可以在Java中取用
則更改前一篇文章,改使用以下程式碼,如圖就可以在Eclipse Console看到如CMD裡顯示的狀態啦!

import java.io.*;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.parser.Parser;
public class AppLauncher {
  public static void main(String[] args) throws Exception
  {
      /*
       *若需外部傳入可用下列語法,執行時ex:java AppLauncher "cmd.exe /c c:123.bat"
       */     
    //String cmd = args.length == 0? "java -version" : args[0];
    String[] cmd = new String[3];
    cmd[0] = "cmd.exe" ;
    cmd[1] = "/C" ;
    //填入執行程式路徑
    cmd[2] = "D:/SplunkSearchId.bat" ;
   
    //-s 為curl 不顯示download進度訊息
    //String cmd = "java -version";
    Process process = Runtime.getRuntime().exec(cmd);
    new Thread(new SubTask(process.getInputStream())).start();
    new Thread(new SubTask(process.getErrorStream())).start();
    process.waitFor();
    //多印一空白行
    System.out.println();
    System.out.println("====================Application terminated=======================");
  }
}
class SubTask implements Runnable {
  public SubTask(InputStream istream)
  {
    if (istream == null){
      iReader = new BufferedReader(new InputStreamReader(System.in));
    }
    else
      iReader = new BufferedReader(new InputStreamReader(istream));
  }
  public void run()
  {
    try {
      String input = iReader.readLine();
      while (input != null)
      {
        //若需執行結果可將input傳出
        System.out.println(input);
        
        /*String html = input;
Document doc = Jsoup.parse(html, "", Parser.xmlParser());
   //String testValue = "0";
for (Element e : doc.select("sid")) {
       //System.out.println(e);
    System.out.println("hi: " + e.text());
    //testValue = e.text();
   }*/
        
        input = iReader.readLine();
      }
    }
    catch (IOException ioe) {
    }
  }
  private BufferedReader iReader;
}


另外請注意一下 程式碼中有註解的地方 是 XML Parser的方式,這邊使用JSOUP jar
因為Splunk Restful API回傳的default格式是XML,其實這樣已經是一個完整的Splunk with JAVA Solution (Java+CMD+cURL+JSOUP)


使用 Java 呼叫 cmd.exe 並下指令(上)

如題,最近由於研究 Splunk Restful API
想透過 API 得到我所要的資料,但Splunk Default支援使用cURL工具來做查詢
由於我cURL安裝好了後,還是得使用cmd下指令,而將來也必須一併整合至
Java,所以以下範例程式為 撰寫一支Java程式呼叫cmd,並執行一個.bat檔案(splunk curl 指令)
目的是取回Splunk Job ID, 圖示為程式的執行結果~*


import java.io.*;

public class CMD {

public static void main(String args[]) {
    String path = "D:\\SplunkSearchId.bat";

   Runtime run = Runtime.getRuntime();   
   try {   
        
    /*cmd /c dir 是執行完dir命令後關閉命令窗口。
 cmd /k dir 是執行完dir命令後不關閉命令窗口。
              cmd /c start dir /b會打開一個新窗口後執行dir指令,原窗口會關閉。
               cmd /k start dir 會打開一個新窗口後執行dir指令,原窗口不會關閉。*/
       Process process = run.exec("cmd /k start " + path);
   
        
       InputStream in = process.getInputStream();
       
       
   } catch (Exception e) {            
       e.printStackTrace();   
   }   
}

}




使用WLS SNMP Monitor CMD

最近某個專案要利用SNMP來監測WLS的狀態
在現在新的版本都建議要使用WLS的SNMP Agent功能(請參考WLS設定Trap http://weblogic-wonders.com/weblogic/2010/12/19/weblogic-snmp-to-monitor-jdbc-connection-pool/)
但是 假設我們手邊沒有其它工具可以觀察是否設定成功
WLS本身有提供Command Line的方式來供使用者測試

首先打開命令提示字元後,必須將WEBLOGIC_PATH加入
意思是使用cmd會根據PATH尋找對應的class

由於我安裝的WLS並沒有事先把WEBLOGIC_PATH設定好
所以請參考下圖至%WLS_HOME/server/bin下使用setWLSEnv.cmd or setWLSEnv.sh(Linux)
再echo看看是否已設定成功,接著就可以使用 WLS提供的monitor cmd了
注意第三張圖 -p(port) 是 你在WLS Admin Console設定 Trap的 port喔!




2014年4月21日 星期一

Java Project 讀取 config.properties 設定檔的方式 Part 2

此法是採用 commons-configuration-1.x.jar (apache的OpenSource可以download)所提供的API
還需要commons-lang-2.x.jar

首先一樣把參數設定檔config.properties放在/src下
之後建立一個Class取名為 Constants,內容如下

import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.PropertiesConfiguration;

public class Constants {

private final static String test_property;

static {
PropertiesConfiguration configuration = null;
try {
configuration = new PropertiesConfiguration("config.properties");
} catch(ConfigurationException e) {
e.printStackTrace();
System.out.println(e.getMessages());
}

test_property = configuration.getString("test_property");

}

public String getConfig(){
return test_property;
}

假設您的設定檔(.properties)內容為
test_property = this is a test

如果利用Constants Class來取得您要的設定檔內容呢!?如下

首先建立一個 ConfigTest.java

將剛才建立的Constants import進來(假設在同個package則不必)

接著

Contants cons = new Contants();

String test = cons.getConfig();

則此時 test 已經等於了 "this is a test"


此法的好處在於設定檔所有的內容都可經由Constants Class來取得
不需像上個方法一樣冗長的程式碼一一初始化


缺點是 修改參數後必須重新佈署程式,而且在 config.properties中

前面的 property key 不可含有 . 沒錯 就是點(上個範例可以)
而且等號後面的 key value不可有 , 沒錯就是逗號

以上面 test_property = this is a test 來說不可改為

test.property = this , is a test
這就2個錯誤都有了,其實第一個錯誤是 java String 類別不給使用
而第二個錯誤是 apache 會把逗號判斷成停止點,所以只能抓到 this 後面的字串就抓不到了




Java Project 讀取 config.properties 設定檔的方式

首先
        將設定檔的位置放至在/src下,接著在想要使用設定檔的java class內加上程式碼

private Properties props;

private void loadProperties() throws FileNotFoundException, IOException {
props = new Properties();
try {
InputStream inputStream =      this.getClass().getClassLoader().getResourceAsStream("config.properties");
props.load(inputStream);
//System.out.println("Get Config Properties Successful");
} catch(FileNotFoundException e) {
e.printStackTrace();
} catch(IOException e) {
e.printStackTrace();
}

}

private String getConfig(String key) {
return props.getProperty(key);
}

public ConfigTest() throws NamingException, SQLException, FileNotFoundException, IOException {
init();
}

private void init() throws FileNotFoundException, IOException {
loadProperties();
}


假設你的設定檔的內容可能為
test.Property = justTest (注意test後面有個點,其實也可以合在一起,只是特別註明此法可以用不同的符號區隔)

那麼接下來再你需要讀取設定檔的method裡(與剛才程式碼同個class)

String test = getConfig("test.Property");

則此時 test ="justTest"

此法的缺點是當別支class呼叫到些class時,每次都會重新讀取設定檔
但優點也可以說,我不需重新佈署程式,只單純修改程式設定檔參數即可執行新的參數。








2014年4月8日 星期二

初探 Struts 2.x

初探 Struts 2

Structs 2 與 structs 1.x 大大不同

基本上必須認知一點是 Structs 2.x 並不是 Structs 1.x 的延伸
而是xWork(WebWork的核心) 的架構,可謂是集WebWork與Struct 1.x於大成,而且依然採用 MVC
所以從技術上來說 Structs 2.x 算是全新的框架

Structs 2所需採用的 jar檔為,通常需放在 WEB-INF的lib目錄下(版號會因版本不同,但前面大致相同)

struct2-core-2.x.jar
xwork-core-2.x.jar
commons-lang-2.x.jar
commons-fileupload-1.x.jar
freemarker-2.x.jar
ognl-3.x.jar
javassist-3.x.jar
commons-io-2.x.jar
commons-lang3-3.x.jar

通常網路上會提供懶人包,一次把所有的jar包成一個jar檔,但很容易讓整個專案變得太胖,而且
開發者理論上也應該要了解哪些是真的會用的,哪些不會用到

Structs 2.x 與 1.x 基本上配置有點不一樣

在 1.x 的時候,會使用一個叫做 structs-config.xml
而在 2.x 的時候 則是在 src目錄下 建立一個叫 structs.xml
並且在 1.x 時 對於 structs 在web.xml是配置一個 servlet
但在 2.x 時,則是視為一個 filter
如下:
    <filter>
        <filter-name>struts2</filter-name>
        <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

假設有使用過 Structs 1.x的人應該知道 structs-config 就是配置 action的地方
而 Structs 2.x 則是在 structs.xml下面有個基本範例

<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.1.7//EN"
    "http://struts.apache.org/dtds/struts-2.1.7.dtd">
    
    <struts>
        <package name="package" extends="struts-default">
            <action name="hello" class="com.company.MyStructs2" method="test">
                <result name="success">index.jsp</result>
            </action>        
        </package>
    </struts>

稍微解釋一下
package name 可隨意取
extends="structs-default" 代表直接使用 struts2.x.jar 中提供的標準設定
action name 就是 可以視為操作行為的名稱
class 就代表 class name,所以是 在 com.company.MyStructs2
method 指的是 在剛才那個 class中有個 method 叫作 test
<result name="success" index.jsp </result>
這是代表 假設 test這個method傳回的結果為 success 則將導向 index.jsp這個頁面

接著如上所示 建立一個 package 名為 com.company,接著 new一個 class名為 MyStructs2
import com.opensymphony.xwork2.ActionSupport;

public class MyStructs2 extends ActionSupport{

    public String test(){
        return "success";
    }

}

如上所示,注意 Struts 2.x 是 extends ActionSupport 而  1.x通常是 Action

接著 請隨意建一個 index.jsp 頁面,當我們要測試 structs 2.x是否運作成功時
則在瀏覽器上輸入 http://serverIP:port/projectName/hello.action

如上所示,測試時 URL 的結尾是採用 .action ,而 structs 1.x 則使用 .do




2014年4月7日 星期一

Invoking 'Spring Project Builder' on '/project' 花費時間太久

最近遇到在Ecslipse使用Spring開發程式時,常常Build WorkSpace時很慢
訊息僅顯示Spring Project Builder on /projectName

看了好幾篇文章,看來這是Spring的小Bug,我不想要撰寫幾行程式,一儲存就要等個
3-5分鐘甚至更久才能測試程式,這裡連續提供幾個我試圖解決的方法

1.在 Eclipse上方Windows-->Preference-->Spring-->Bean Support-->Timeout[sec]改成了600秒

本來還未改此設定之前,default是300秒,但由於專案太大,總是會花超過300秒,改成了600秒之後專案就沒有Error了<忘了Error是啥,意思好像是Build的時候timeout>

2.修改(1)剛開始沒問題,後來出現標題的問題,所以修改設定在
Windows-->Preference-->Spring-->Project Builders
把 Spring Bean Meta Data Builder 不要打勾,如圖
3.如果仍然有問題,因為Spring把所有Libris中所使用的jar檔中 import的class都搜尋了一遍
可以參考設定在 你的專案名字按「右鍵」-->Properties-->Spring-->Beans Support下面的Options把 Enable support <import/> elements in configuration files 試著勾或不勾看看

補充可加速 Spring Tool Initialize

  1. Disable validators: Preferences -> Validation: check Suspend all validators
  2. Disables Spring validation: Preferences -> Spring: uncheck unwanted validation rules
  3. Disable Build Automatically: Preferences -> General -> workspace: uncheck build automatically

參考資料
http://www.bmchild.com/2013/01/speeding-up-springsource-tool-suite-sts.html





2014年1月6日 星期一

解決 SQL Plus 在 Linux上無法使用 SQL History(按上) 使用 rlwrap 功能

在工作中常常遇到連線 Linux Oracle DB時,下SQL指令,打錯後要重新打無法使用向上鍵而必須重打的冏境,rlwrap是一個好用的工具,且安裝方便

首先至rlwrap官網download最新版本
http://utopia.knoware.nl/~hlub/uck/rlwrap/

之後將此檔案放至您想放的目錄下,我是放在/home/oracle下(我使用WinSCP工具)
記得使用 root下指令喔!解壓縮吧!

接著輸入如下指令(記得要到rlwrap-0.37目錄下喔!)
中間的訊息我就省略了
最後的訊息大概像這樣
接著準備 su - oracle 吧!
在.bash_profile加入
alias sqlplus=”rlwrap sqlplus”
alias rman=”rlwrap rman”


之後離開session(putty),重新登入os後試試sqlplus及上一步功能有沒有顯示上一個SQL Commad嘍!