2013年12月20日 星期五

postgresql9.1 extend postgis

其實就一行小小的指令~ 很好用~
這是為啥偶後來都喜歡9.1版的postgresql...

不然centos原生就有8了, 以前run了很多年的8也是很穩定~
沒事找事做很累的T___T....


前提的條件就是先裝好postgreql9.1...(extend的功能9.1才開始有的)
並且灌好postgis的plugin~

在自用的database 開好後~ 依情況~或是需要時再執行一行指令
CREATE EXTENSION postgis;

就馬上擁有postgis好用的功能^_^Y....
話說postgis2.0的好用之處~ 目前是還沒有特別發現~
因為最常用的還是距離運算, 空間包含之類的...這些在1.5版時就蠻齊的了

附上官網說明...
http://postgis.net/docs/postgis_installation.html#create_new_db_extensions

古早做法很麻煩的~ 要執行幾個sql匯入function, object....etc
早期為了怕有問題~ 是先做一個有geom的database起來~
然後再開database templet弄進來~

只是就有時候覺得owner或role的設定覺得不開心一_一a....

2013年12月13日 星期五

Java call command

這個其實也沒有太特別~ 算是Java的基本功能吧O_o...
只不過因為這次的整合, 屬於AP的方式...
所以就靠主流程一直下cmd來進行處理~~

主要就是使用Runtime來處理~
因為有些AP是直接將結果或exception, 直接output到console上, 所以就要好好的讀一下它output的內容~

只是單純的想使用簡潔的Runtim process會出現他沒辦法change 工作路徑過去~
這時候使用ProcessBuilder會比較好...
ProcessBuilder builder = new ProcessBuilder(cmd);
builder.directory(new File(home));

另外Process的waitfor()的使用上會卡住的原因, 好像前提是要把Process相關的inputStream(InputStream, ErrorStream)讀完後, 跟outputStream都關掉後~再執行, 就不會有問題...
不過我也只是要讀讀console上的東西~ 就算了XD...
因為當初就跟其他的lib講好~ 把結果output在console或是console+file裡...統一方式比較好處理...

實作上我也不想真的在java裡面寫很多次的cmd呼叫 , 所以主要是~ 先用java寫出動態的sh/bat檔...裡面依據需要給參數或是好幾行的依序執行內容~ 檔寫好後再去執行一次那個檔就好了...寫檔有個好處啦~ debug或只是測試lib, 重新操作比較方便~

public String runCmd(String home, String cmd) throws Exception {
       Process p = Runtime.getRuntime().exec(cmd, null, new File(home));
       InputStream is = p.getInputStream();

       StringBuffer sb = new StringBuffer();
       BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
       while (true) {
           String tmp = reader.readLine();
           if(tmp == null)  {
               break;
           }
           if(tmp != null)  {
               sb.append(tmp+"\n");
           }
       }
     
       return sb.toString();
   }

後來又有在某地方改一個應該是比較正統的寫法~加上p.waitfor()
public String runCmd(String home, String cmd) throws Exception {
       Process p = Runtime.getRuntime().exec(cmd, null, new File(home));
       InputStream is = p.getInputStream();

       BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
       while (reader.ready()) {
           ;
       }
       reader.close();

       reader = new BufferedReader(new InputStreamReader(p.getErrorStream()));
       while (reader.ready()) {
           ;
       }
       reader.close();

       p.getOutputStream().close();
       p.waitFor();

       return "";
   }

2013年12月10日 星期二

Nagwin

唉~前因後果不提~
總之...原本是要裝nagios, 一個監控主機套件~ 不過原生是在linex上
要裝的機器是windows server
這是他們家官網
http://www.nagios.org/

很妙的是~ 他們對其他平台的支援方式是提供"VM檔"...
不過我自己就已經是VM...要玩VM裡的VM這種遊戲嗎~囧?

所以後來就使用Nagwin...簡單的講~ 就是把nagios加上模擬linex運行環境的方式搞到windows上
https://www.itefix.no/i2/nagwin

這東東~ 我覺得並不是完美安裝包~
(完美安裝包~ 我會說像postgresql, apache httpd那種~  點兩下就會百分之百成功的)
不過主要的問題發生點我認為在於...帳號權限的處理問題上~

首先這包只有32bit的碼, 不過這個倒不是重點~ 能跑就好了~ 管他的一u一a...

另外安裝時~ 他會要求輸入windows帳號密碼, 推估除了是做為設定成windows服務用的(若有安裝完成, 去windows服務裡可以看到生出四個服務, 帳號就是剛剛打的那個), 不過windows帳號是個神奇的系統, 可以安裝又不見得可以跑...(因為我使用的帳號(非administrator), 是可以安裝該服務, 不過無法啟動喔...不過去服務裡面把user設定改掉後~ 就可以啟動了XD, 暫時還沒有看到其他奇怪的事)
Nagwin有提供帳號密碼登入他的網頁, 密碼變更是使用該指令~ 很可能會發生下了指令~ 但是無法寫入密碼的那個檔(看檔案更新日期應該就很清楚)...所以爛人解法~ 就是找一台權限夠能跑的~ 改好密碼~ 把那個檔案貼去失敗的那邊Orz...


不過nagwin的plugin就沒這麼幸運了...
winrpe (原nagios裡的nrpe,安裝在其他主機上, 提供給主要nagios資訊的agent)
https://www.itefix.no/i2/winrpe
不知道為啥(應該還是帳號權限問題, 因為像log那種都寫不進去, 要手動去改資料夾檔案的權限)~ 裝起來寫成功, 但是沒跑起來失敗就算了(該聽的port沒serivce)...
最慘的是居然跑去改該帳號的其他設定(目前最直接發現的就是他居然鎖了該帳號的遠端桌面服務, 還好最後有找到地方把黑名單清掉(本機安全性原則->使用者權限指派->拒絕遠端連線登入...), 還有其他後遺症還沒有碰到就不知道了Orz...
要說還好在測試機就先病發了一_一...不過測試機登不進去也是造成很大困擾.........
所以就先放生他吧...

安裝方式請參照官網...win安裝一直都沒什麼特別困難的...
https://www.itefix.no/i2/content/nagwin-installation
出事的地方都很奇怪~ 基本上都是系統環境問題...

而監控的設定基本上和nagios是一樣的~從他安裝好的路徑下應該很容易看出linex愛用的目錄資料結構~

改密碼指令是到bin/
htpasswd2 -b /etc/nginx/htpasswd nagiosadmin new-password

測試監控項目的指令check_xxx都放在plugin/下
在設定之前, 可以先在這邊試試check指令有沒有正常符合期待~
測試OK後再寫進設定檔做監控比較好~
以免一直看不出問題在那....

題外話: 那天爬了很久的nagios...然後偶發現偶在facebook上~ 居然出現nagios的專頁推薦!!

centos + ganglia

Ganglia是一套主機資源監控的軟體~
大概就是看看cpu/ram/網路資源使用量降子~
原生是linex系統的東東~

資源監控~偶看大概都不跳出這些作法~
會有一台主要server, 搜集資訊, 提供網頁/AP, 儀板表介面~

另外會有所謂像agent這樣的東西~ 裝在其他監控的主機上...
定期把資訊送到server, 或是由server從agent機器上拉過去...

不過這樣子也合理啦~ 因為監控很多是監控到主機硬體資源的使用部分~
正常主機~ 是不會讓其他主機access硬體資訊的...

ganglia分為三個部分~
ganglia-gmetad  --> 資料整合(server裝就好)
ganglia-web  --> 提供http介面(server裝就好), 使用的是php的套件, 所以要先裝好httpd
ganglia-gmond  --> 資料收集(要監控的機器都要裝)
上面套件安裝好後~ 會變成centos上的service, 所以需要開機啟動的話~ 就自己要再去開啟
web介面是沒有帳號權限的~ 就是裝好後~ 連網址就可以直接看到內容~

重點大概就是注意gmond, cluster的 name 要與gmetad的datasource名稱一致, 這樣才對得上..該名稱也會顯示在頁面上~就當成是server群組的名稱吧~

agent/server 溝通的port default是 8649, 要走別的port, gmetad主機後要加port

gmond裡, 還有可以改的大概就是host.location, 填主機的名字以方便識別
udp_send_channel改一下, ttl=1才會live, host給自己的IP, 其他check一下是否有差別

安裝方式如下:

   su
   rpm -Uvh http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
   yum install ganglia ganglia-gmetad ganglia-web ganglia-gmond
   #only client without server
   #yum install ganglia ganglia-gmond
  
   ##if everything OK, ganglia will be installed  /etc/ganglia/
   ## httpd page installed /usr/share/ganglia  
  
   vim /etc/ganglia/gmetad.conf
   ##Update data source name and ip address : data_source "OnSite_QA" 60 ipaddress
   ##If you define 60 every 60 seconds the data will poll from the ganglia monitoring daemons
  data_source "hadoop" 60 192.168.3.xx1   192.168.3.xx2   192.168.3.xx3   192.168.3.xx4

   vim /etc/ganglia/gmond.conf
cluster {
name = "hadoop"    ##modify
owner = "unspecified"
latlong = "unspecified"
url = "unspecified"
}
host {
  location = "host1"
}
udp_send_channel {
  #bind_hostname = yes # Highly recommended, soon to be default.
                       # This option tells gmond to use a source address
                       # that resolves to the machine's hostname.  Without
                       # this, the metrics may appear to come from any
                       # interface and the DNS names associated with
                       # those IPs will be used to create the RRDs.
  #mcast_join = 239.2.11.71
  port = 8649
  host = 192.168.3.xx1
  ttl = 1
}

udp_recv_channel {  
port = 8649
}
tcp_accept_channel {
port = 8649
}
  
   ##start service
   #/etc/init.d/gmetad restart
   #/etc/init.d/gmond restart
   service gmetad restart
   service gmond restart  <--better
  
   service httpd restart
  
   ##change php allow
   vim /etc/httpd/conf.d/ganglia.conf
  
  <Location /ganglia>
    Order deny,allow
    #Deny from all  ##modify here
    Allow from all  ##modify here
    Allow from ::1
    # Allow from .example.com
  </Location>

tomcat 設定docbase

起因是為了把某資料夾底下的檔案用http存取...
算當file server使用~
 話說湯姆貓平常的佈署路徑是在{tomcat_home}/webapps/xxxx下...
雖然說context.xml裡面可以設定docbase...

不過好像有限制...反正就是指不過去...

差別在於file server路徑是在別槽, 另外掛載上去的storege~
就只好更暴力一點~ 改在server.xml裡面下手

在server.xml最底下的host內加入
<Context path="/xxx" docBase="G:/ftp/xxx" debug="0" reloadable="false" crossContext="true" />
<Host> <----xml最後, 加在Host內

重起tomcat後~ 就可以了~
使用的連結大概會像降子...
http://{ip:port}/xxx/abc.jpg   --> (G:/ftp/xxx/abc.jpg)


win + apache proxy

在windows上裝apache 相信是很common的討論~
google大神不用認真拜就很多了~~

以往為了技術單純化~ 都用一隻湯姆貓解決比較簡單~
不過因為這次要整合四五個來源的http服務, 再統一從對外網站對外提供...
所以還是靠個有口碑的proxy比較輕鬆~~
(不然到時候一堆人又會吵是誰誰誰沒轉好~)

對於網頁proxy 的作法~
apache有提供蠻多的方式...
ex: 設定指定目錄, virtual host...etc, 在tomcat整合還有ajp等方式~~~

因為windows安裝完的設定與centos上不一樣~
(centos上懶人安裝, 功能較多)
仔細看~ 會發現httpd裡面的模組就有差~
在LoadModule 裡面, windows的vhost(virtual host), ajp預設都是沒有開啟~
而且可能也沒有相關lib..要另外download

所以為了簡單...所以直接採用單純的proxy...
在centos好像會自己弄成virtual host...

virtual host是比較高級~ 可以再設定限制連線~
不過我在這邊用已經是最外層對外服務的web了~
所以直接用轉導倒也是OK~

原則上基本就是...
1. 到官網下載安裝包
http://httpd.apache.org/download.cgi

2. 點兩下安裝...

3. 改改設定檔
httpd.conf 修改
Listen 80   <---改成需要的port

 啟用module
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so

4. 設定簡易proxy
httpd.conf 拉到最底下直接加上轉導路徑
ProxyPass /tomcat/ http://localhost:8080/
ProxyPassReverse /tomcat/ http://localhost:8080/

5. 啟動(重啟) apache服務

6. 測試

2013年12月4日 星期三

java wav 過濾頻率

這邊主要是將原wav過濾頻率, 只保留部分的音頻...
相信在google上也有很多的實作~

不過有找到一個方便的lib...
只要一個jar, 下個cmd就OK了~

使用dsp-collection.jar
出處:
http://www.source-code.biz/dsp/java/

用法很簡單~ 只要下cmd就好了
雖然偶不懂用那個演算法比較好XD..個人指導最高原則就是...能動就好了
ex:
java -cp dsp-collection.jar WavFilterFisher sample.wav bandpass chebyshev 4 -0.5 1000 5000 out.wav

來個檔案做圖解~ 雖然沒辦法濾得很乾淨, 但是看起來還是有差的+_+
原始檔頻譜


過濾後頻譜

java wav 轉 mp3

wav檔處理是OK的~ 不過因為檔案很大~ 不太適合做資訊發布...
所以最後發布就轉成mp3壓縮~

我這邊採用jave的lib...
http://www.sauronsoftware.it/projects/jave/

原因最主要也是輕量(只要一個jar)
win/centos通吃
可java呼叫
可以成功使用(重點)

呼叫的java sample code如下:

            File source = new File(fin);
            File target = new File(fout);
            AudioAttributes audio = new AudioAttributes();
            audio.setCodec("libmp3lame");
            audio.setBitRate(new Integer(128000));
            audio.setChannels(new Integer(2));
            audio.setSamplingRate(new Integer(44100));
            EncodingAttributes attrs = new EncodingAttributes();
            attrs.setFormat("mp3");
            attrs.setAudioAttributes(audio);
            Encoder encoder = new Encoder();
            encoder.encode(source, target, attrs);

java wav 計算db值

承上篇...
有計算音量的部分(算db值, 只是一個強度相對的大小值)

我忘了是從那邊copy出來的~
不過用google查該method name應該可以找到不少...

反正就把從WaveFile裡面讀到的raw data丟進去就有一個值生出來了XD"

主要計算db的method
/** Computes the RMS volume of a group of signal sizes ranging from -1 to 1. */
    public double volumeRMS(double[] raw) {
        double sum = 0d;
        if (raw.length==0) {
            return sum;
        } else {
            for (int ii=0; ii<raw.length; ii++) {
                sum += raw[ii];
            }
        }
        double average = sum/raw.length;

        double sumMeanSquare = 0d;
        for (int ii=0; ii<raw.length; ii++) {
            sumMeanSquare += Math.pow(raw[ii]-average,2d);
        }
        double averageMeanSquare = sumMeanSquare/raw.length;
        double rootMeanSquare = Math.pow(averageMeanSquare,0.5d);

        return rootMeanSquare;
    }

java WavFile 切檔案

處理wav檔資訊, 問google其實有不少的解決方案~

這次對於聲音採取lib的選擇順序重點是...
1. 要能動, 可以包成api呼叫
2. win/linex(centos) 都要相容
3. 以java原生/相關優先
4. 輕量/相依性較低

因為其實也不是只做一兩項處理而已~ ...每個人都說很簡單~
喵的~ 最好整四五個以上功能很簡單啦....

所以有很多有名的都不行T_T...
有名的大多都包成有UI了~ 很難從裡面拆method出來用@@...

我最後是採用一個有source檔的拿來回自己改...這個只能處理純wav...
有些運算可能不太正確~ 其原因為我並不了解wav本身的正確格式與內容~
不過就我需要的部分~ 能做到就好^^0....
選他是因為lib最單純(純java code, 不用lib/jar)~
然後有是有少數看懂source code用法|||Orz...
(某些lib/open source是看懂一半~ 硬改source code後就GG...因為套件流程綁太多~ 沒辦法一一找對地方改QQ)


先說明該source code的出處
http://www.labbookpages.co.uk/audio/javaWavFiles.html

至於應用上是拿來做兩件事
1. 處理切檔(ex: 2分鐘切出1分鐘)
2. 找音量相對大的位置(音量就等於內容資料強度...反正就是值越大, 音量越大)

合起來就變成~ 找出音量相對大的地方開始切N秒~ 成為新的wav檔案

這篇先放切檔案的method
基本上就是先建一個空的{secs}秒, wav, 然後從原本的wav檔, 某個位置開始讀寫...
有處理若是該位置是在原始檔的後面(會有可能造成只寫一部分的資料~ 但是新檔尾巴就空空的)
在原始檔長度小於新檔長度時就會丟excption出去了...(在偶低case裡, 原始檔長度不夠本來就不應該做處理)

/**cut wav file, start with buffersize * start, cut secs seconds
     * @param wavFile source
     * @param buffersize sample buffersize
     * @param start idx of the sample
     * @param secs cut how long seconds
     * @param target output file path*/
    public void process(WavFile wavFile, int buffersize, int start, double secs, String target) throws Exception {

        WavFile newFile = null;
        try  {
            long sampleRate = wavFile.getSampleRate();        // Samples per second
            double totalsecs = wavFile.getNumFrames()/buffersize;
            if(start+secs > totalsecs)  {
                start = (int)(totalsecs - secs);
            }
            if(start < 0)  {
                start = 0;
            }

            double duration = secs;        // Seconds
            // Calculate the number of frames required for specified duration
            long numFrames = (long)(duration * sampleRate);
            newFile = WavFile.newWavFile(new File(target),
                                             wavFile.getNumChannels(),
                                             numFrames,
                                             wavFile.getValidBits(),
                                             sampleRate);

              // Display information about the wav file
            //wavFile.display();
            //System.out.println("-----------");
            //newFile.display();

            // Get the number of audio channels in the wav file
            int numChannels = wavFile.getNumChannels();
            int frames = buffersize;

            // Create a buffer of 100 frames
            double[][] buffer = new double[numChannels][frames];

            int framesRead;

            int loop = 0;
            // Read frames into buffer
            do {
                framesRead = wavFile.readFrames(buffer, frames);

                if(loop >= start)  {

                    long remaining = newFile.getFramesRemaining();
                      int toWrite = (remaining > frames) ? frames : (int) remaining;

                    // Write the buffer
                       //newFile.writeFrames(buffer, toWrite);
                    newFile.writeFrames(buffer, toWrite);

                    if(toWrite < frames)  {
                        break;
                    }
                }

                loop++;
            }  while (framesRead != 0) ;

        }  catch(Exception e)  {
            throw e;
        }  finally  {
            if(newFile != null)  {
                try  { newFile.close(); }  catch(Exception eee) {}
            }
        }

    }