Logstash

/var/log/named:/var/log/named
sudo vi ~/docker-elk/logstash/pipeline/bind.conf
input {
    file {
        type => "BIND_DNS"
        path => [ "/var/log/named/query.log" ]
        start_position => "beginning"
    }
}

filter {
    if [type] == "BIND_DNS" {
        grok {
            match => ["message", "(?%{MONTHDAY}[-]%{MONTH}[-]%{YEAR} %{TIME}) client %{IPV4:clientip}#%{POSINT:clientport} \(%{GREEDYDATA:query1}\): query: %{GREEDYDATA:query2} IN %{GREEDYDATA:querytype} \(%{IPV4:dns}\)"]
        }
        date {
            match => ["logdate", "dd-MMM-yyyy HH:mm:ss.SSS"]
            timezone => "America/Los_Angeles"
        }
    }
}

output {
    elasticsearch {
        hosts => "elasticsearch:9200"
    }
}
03-Aug-2017 00:55:29.005 client XXX.XXX.XXX.XXX#54501(www.google.com): query: www.google.com IN A + (XXX.XXX.XXX.XXX)
  • 這次的目的是要分析 BIND9 的 query.log 檔,主要需要修改的地方是 Logstash 結構化 log 的設定
  • 先將 log 檔案所在的目錄 volume 到 docker container,在 volumes 區塊新增
  • ~/docker-elk/docker-compose.yml
  • 根據 BIND9 的 query.log 新增結構化設定
  • ~/docker-elk/logstash/pipeline/bind.conf
  • input > file > path 分析 log 檔案的位置
  • filter > grok 分析並透過他的 patterns 重構 log 字串
  • into
    {
      "_index": "logstash-2017.08.03",
      "_type": "BIND_DNS",
      "_id": "AV2nF6AFU4gS5SfvUHc1",
      "_version": 1,
      "_score": null,
      "_source": {
        "path": "/var/log/named/query.log",
        "@timestamp": "2017-08-03T00:55:29.005Z",
        "logdate": "03-Aug-2017 00:55:29.005",
        "clientip": "203.75.167.229",
        "query1": "www.google.com",
        "query2": "www.google.com",
        "@version": "1",
        "host": "690ab8796350",
        "dns": "172.31.10.132",
        "message": "03-Aug-2017 00:55:29.005 client 203.75.167.229#54501 (www.google.com): query: www.google.com IN A + (172.31.10.132)",
        "type": "BIND_DNS",
        "clientport": "54501",
        "querytype": "A +"
      }
    }
    
  • (?<logdate>%{MONTHDAY}[-]%{MONTH}[-]%{YEAR} %{TIME}) 是自訂 pattern,因為原始 pattern 沒有符合 query.log 的日期格式,參考來源是 logstash-patterns-core
  • 其他關於 grok 寫法的判斷與模擬,可以透過 Grok Debugger 測試
  • filter > date 是將自訂參數 logdate 取代預設 timestamp 的寫法。因為預設 timestamp 是指 Logstash 分析匯入的時間,而不是 log 紀錄的時間,所以要特別替換後才方便給 Kibana 分析使用
  • 如果記錄檔 EC2 機器時區有另外設定,timezone 也要設定

Kibana

  • 一開始會先選擇 Elasticsearch 資料來源,因為沒有特別修改設定,直接使用預設的 logstash-* 即可
  • 因為時區預設使用瀏覽器設定,所以要先到 Management > Advanced Settings > dateFormat:tz 強制設定為資料的時區
  • 建立一個 IP COUNT/DATE 的圖表
    1. 建立新圖表 Visualize > Create a visualization
    2. 選擇長條圖 Basic Charts > Vertical Bar
    3. 選擇資料來源 From a New Search, Select Index > logstash-*
    4. Y 軸選擇欄位 clientip 的數量 Y-Axis > Aggregation[Unique Count] > Field[clientip.keyword]
    5. X 軸選擇日期 X-Axis > Aggregation[Date Histogram] > Field[@timestamp] > Interval[Daily]
    6. 點選右上角的箭頭 Apply changes
    7. 右上角時間範圍選擇 This week 就可以看到一周內 IP COUNT/DATE 的長條圖
    8. 5185654_raw.png

文章標籤

danielhuang030 發表在 痞客邦 留言(0) 人氣()

 

Info

 

  • ELK 並不是單一程式,而是分別由 Elasticsearch, Logstash, Kibana 所組成
  • Elasticsearch 擔任資料儲存,可以把它看成是資料庫的一種,同時他也可以實現全文檢索
  • Logstash 收集並處理資料,可以透過正規式將 log 的字串結構化
  • Kibana 則是提供網頁的呈現,串接 Elasticsearch 之後可以表現出簡潔美觀的視覺化報表

Installation

sudo apt-get update
sudo apt-get install docker.io
sudo usermod -aG docker $USER
sudo curl -L "https://github.com/docker/compose/releases/download/1.15.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose sudo chmod +x /usr/local/bin/docker-compose
sudo sysctl -w vm.max_map_count=262144
git clone https://github.com/deviantony/docker-elk.git
cd docker-elk
# 建議先不要背景執行,有錯誤可以比較容易發現
docker-compose up
  • 傳統安裝方式是一個一個來,不過要串連三個程式並調整環境設定,非常容易卡關;一開始裝到一半我就遇到各種困難…後來突然想到這種需要安裝不同程式的環境,一定已經有人提供整合後的 docker images,後來一找果然有!網路上推薦使用:docker-elk
  • 基本環境需求:
    • 硬體需求較高,原本我使用 AWS EC2 t2.micro 一直當機,後來升級到 t2.medium 後才成功啟動
    • Docker version 1.10.0+
    • Docker Compose version 1.6.0+
    • git
  • ubuntu 16.04 Docker & Docker Compose 安裝(1.15.0 是寫文章時 Docker Compose 的最新版本,請依安裝時釋出的最新版本號自行更換)
  • 調整系統參數
  • git clone 並建立 docker container
  • 如果沒有錯誤,這個時候 http://domain:5601 應該已經可以看到 Kibana 的畫面(EC2 請開啟 port 5601)
  • 5185647_raw.png

  • http://domain:9200 也會看到 Elasticsearch 的 JSON 回應(EC2 請開啟 port 9200)
  • 5185648_raw.png

  • 另外建議可以安裝 Chrome extension ElasticSearch Head,只要連接 http://domain:9200/ 就可以直接連到 Elasticsearch 並看到原始數據
  • 5185649_raw.jpg

文章標籤

danielhuang030 發表在 痞客邦 留言(0) 人氣()

其實這篇文章內容跟 AJAX 沒有關係...(囧)不過之前似乎沒有編輯 JavaScript 的分類,所以就沿用下去吧!(完全題外話)

最近遇到需要結合二個設定的情況,在,在 PHP 時 array 是 key-value 的形式,所以可以使用 array_merge() 結合二個 array;不過在 JavaScript 中 key-value 算是物件。要怎樣結合二個物件呢?後來在網路上蒐尋到 jQuery 就有提供很好用的函式 $.extend()簡單的使用方式如下:

var foo = {
set1: {
name: 'test1',
color: ['red', 'blue']
},
set2: {
name: 'test2'
}
};

var bar = {
set2: {
name: 'testSub2'
},
set3: {
name: 'test3',
color: ['green']
}
};

alert($.extend(foo, bar).toSource());

要注意的一點是,如果二個物件有相同屬性時,後面的物件屬性會蓋過前面的物件屬性。

另外在 PHP 實作上常常會用到「變數的變數」這種寫法,後來發現 JavaScript 好像也有類似的函式可以達到這個目的:eval()簡單的使用方式如下:

var foo = 'bar';

var bar = 'test';

alert(eval(foo));

很多東西真的沒有用到過就不會知道啊~(遠目)PHP 真的提供很多好用的函式,可惜在別的語言中就不一定有;不過還是會有相類似的解決方法的,畢竟基本思考的邏輯是相同的嘛!^^

文章標籤

danielhuang030 發表在 痞客邦 留言(0) 人氣()

Yii Framework

本身對資料庫的操作除了提供 Active Record 以外,也有提供類似 ZendFramework Zend_Db_Table 以物件透過函式組合 SQL 語法的方法:CDbCommand

基本的使用方式是:

<?php
// 取得 tbl_user 資料表中,id = 1 的資料列
$row = Yii::app()->db->createCommand()
->select('username, password')
->from('tbl_user')
->where('id = :id', array(':id' => 1))
->queryRow();
?>

其中 where 的用法是需要特別說明的地方,因為 Yii 在底層也是使用 PDO 實作,為了防止 SQL Injection 的發生,提供非常類似的使用方法;where() 函式可以引用二個參數:$conditions、$params。$conditions 是 array 型態時,包含連結方式、欄位、值;也可以使用單純 string 型態的字串。$params 非必填,是 array 型態,對應 $conditions 設定的值做 quote 的處理。範例如下:

<?php
$id = (int) $id;
$typeId = (int) $typeId;
$conditions = array(
'and',
'id = :id',
'type_id = :typeId'
);
$params = array(
':id' => $id,
':typeId' => $typeId
);
// 取得 tbl_table 資料表中,id = $id AND type_id = $typeId 的資料列
$row = Yii::app()->db->createCommand()
->from('tbl_table')
->where($conditions, $params)
->queryRow();
?>

其他關於 where 更詳細的用法,請參考 casahama 熱心的翻譯文章(簡體)。

其實相比較之下,個人覺得 Zend_Db_Table 比較好用一點,因為他的 where() 函式可以一直串接下去,但 CDbCommand 的 where() 必須先自己依造規則組好,而且只能下一次...(後面下的參數會蓋過前面下的參數)不過在這些 Framework 提供的 Query Builder 的幫助下,能確實減少我們在撰寫 SQL 語法時可能發生的錯誤,同時過濾有可能造成 SQL Injection 的參數。感謝 Framework 製作者的貼心,提供這麼方便的工具^^

文章標籤

danielhuang030 發表在 痞客邦 留言(0) 人氣()

簡單紀錄一下幾個在 PHP 中讓效能更好的方法,其實基本的原則就是「少用函式,多用 isset()empty() 取代」

1. 用 (int) $var 取代 intval($var)
PHP 是一種弱型別的語言,所以在面對外部傳進來的變數時,我們通常會在作一次型別的轉換處理;PHP 內建提供型別的強制轉換,如:(int)、(string)、(array),強制型別轉換比函式如:intval()strval() 來的有效率。

2. 用 isset($var[0]) 取代 0 < strlen($var)
當變數是字串型態時,我經常會用 strlen() 這個判斷字串長度的函式檢查他是否為空字串;不過其實 isset() 再檢查字串變數時的效率更高。其他像是在判斷字串長度時,也可以用它來代替。

3. 用 strpos($var, 'str') !== FALSE 取代 preg_match('/str/', $var, $matches)
在字串查找時,第一個想到的函式通常是 preg_match(),但是如果尋找的字串很單純時,使用 strpos() 的效能會更好。

其他還有許多撰寫 PHP 程式時增進效能的小技巧,請參考 Tsung's Blog 有更詳盡的說明。

文章標籤

danielhuang030 發表在 痞客邦 留言(1) 人氣()

喔~大概有八百年沒有寫文章了...(汗)最近遇到一個需求,需要用到 cookie 紀錄;不過在實作的過程中,發現明明以 AJAX 在 PHP 中 setcookie(),重新整理後卻無法取得 $_COOKIE 資訊的問題。後來以關鍵字餵了 google 大神以後,才找到解決的方法:

1. 設定 setcookie() $path 參數:
以 AJAX 設定 cookie 時,如果沒有指定 $path 參數程式會自動指定一個虛擬目錄給它,但依照 cookie 的特性:「僅有它的目錄以及以下的子目錄能夠存取」;所以未指定 $path 參數的 cookie 可能會造成在其他目錄下的程式無法存取。一勞永逸的方式就是直接指定 $path 參數為根目錄「/」:

<?php
// 第三個參數是 cookie 的存活時間,0 表示存活至瀏覽器關閉為止
setcookie('variable', $value, 0, '/');
?>

2. PHP 伺服端回傳變數,由 JavaScript 寫入 cookie:
做法有很多種,不過大概就是由 JavaScript 寫入 cookie 的概念。

最後我是使用第一種方式,有些問題還真是沒有碰到就不會知道呢~google 大神真是大家的好朋友!(拇指)

文章標籤

danielhuang030 發表在 痞客邦 留言(0) 人氣()

PHP

從 PHP5 開始,在資料庫操作方面新增了 PDO(PHP Data Objects)的 extension,利用物件導向的方式與資料庫進行溝通。捨棄以往透過單一函式的方式,而是透過物件導向程式設計的抽象化概念,操作時使用統一的方法,如果需要更換資料庫時,只要在建立物件時給予資料庫的形式,而不用更動到原來的程式碼。這也是物件導向程式設計擁有優良靈活性的最佳表現!

連線的方式:

<?php
// 給定資料庫變數
$dbtype_sql = 'mysql';
$host_sql = 'localhost';
$dbname_sql = 'dbname';
$username_sql = 'username';
$password_sql = 'password';


// 資料庫連線
try {
$dbh = new PDO($dbtype_sql . ':host=' . $host_sql . ';dbname=' . $dbname_sql, $username_sql, $password_sql);
// 資料庫使用 UTF8 編碼
$dbh->query('SET NAMES UTF8');
} catch (PDOException $e) {
echo 'Error!: ' . $e->getMessage() . '<br />';
}
?>

一般的 SELECT 查詢方式:

<?php
// 使用 quote 避免 SQL Injection;相當於 mysql_real_escape_string()
$id = $dbh->quote(2);
$name = $dbh->quote('John');

// 組合 SQL 語法,取得符合 id = 2、name = 'John' 的資料
$query = sprintf("SELECT * FROM table WHERE id = %s AND name = %s", $id, $name);
foreach ($dbh->query($query) as $row) {
print_r($row);
}
?>

利用預載的方式:(推薦使用)

<?php
// 組合 SQL 語法,取得符合 id = 2、name = 'John' 的資料
$sth = $dbh->prepare('SELECT * FROM table WHERE id = :id AND name = :name');
$where = array(':id' => 2, ':name' => 'John');
// 使用 execute(),會自動 quote $where 的參數
$sth->execute($where);

foreach ($sth->fetchAll(PDO::FETCH_ASSOC) as $row) {
print_r($row);
}
?>


統一採用物件的方式來操作資料庫,不僅增加系統的彈性,透過相同的 quote() 方法,即可針對不同的資料庫形式進行 SQL Injection 的預防;真的非常方便!雖然於其他專業的 ORM(如:Doctrine)比較,仍有不足;但是在比較簡單的功能的實作上,PHP5 內建的 PDO 的確提供良好的資料庫操作模式~推薦使用!^^

文章標籤

danielhuang030 發表在 痞客邦 留言(2) 人氣()

今天發現了一個我以前就知道的東西(我在說什麼啊...?):Augmented Reality 擴增實境。最早看到應用類似技術的商品是在日本的遊戲 AR-FIGURE 中:利用 Web Cam 與遊戲廠商提供的實體方塊,建立一個存在電腦螢幕中真實環境裡的虛擬人偶(好繞口...)。第一次看到這玩意兒的時候真是嚇死我了,原來遊戲也可以這樣玩!擴增實境其實也是 Virtual Reality 虛擬實境的一種;但不同於 VR 中所有東西都是虛擬的,AR 是一種與現實環境結合的虛擬。隨著現代科技的進步,攝影機技術已經被廣泛運用生活中;也因為如此,以往印象中虛擬實境所需的厚重眼鏡與手套,已經可以藉由我們生活中常見的手機:攝影鏡頭與觸控螢幕來實現!

Google 前陣子提出的 Google Goggles,似乎就有結合類似的技術;透過即時的影像擷取與分析,立即透過網路取得相關資訊。當然這只是非常小部分的應用,更多的應用可以參考「iGarden – NSS ICT Education Blog 擴增實境Augmented Reality(AR)教學」的相關介紹文章,有非常令人驚艷的展示效果!

今天跟 Jace 提到這個技術,他提到 MIT 有個印度的學生已經結合此技術,實作出更接近未來世界的裝置;後來我 google 了一下,發現了 sixthsense 這個專案。這個專案利用成本大約 320 美金的材料,改裝成一個結合攝影與顯示於一身的特殊裝置,透過這個裝置就能夠即時擷取眼前的影像,並直接投影在物體上,利用手指上的顏色標籤作手勢操作,完全就像電影《關鍵報告》的操作方式!超屌!

以往覺得離我們好遠好遠的未來科技,突然有一種近在咫呎的感覺!Google Goggles 已經實現了動畫《東之伊甸》所描繪的技術,或許不久的將來就能體驗,動畫《電腦線圈》中透過「電腦眼鏡」看世界的科技未來!

P.S 這個影片整個很有《魔鬼終結者》的 fu...墨鏡才是本體啊!(噗)

文章標籤

danielhuang030 發表在 痞客邦 留言(0) 人氣()

從出社會工作以來,經常接觸到的幾乎所有的程式,都是開放原始碼。不過對於它的定義與其衍生的自由軟體所採用的授權方式,一直以來都是一知半解。前幾天在 PTT Soft_Job 版看到一篇討論【[請益] 請問要如何規避GPL?】,引起我想要弄清楚的興趣;這些不同的授權方式各自到底代表著什麼意義呢?

詳細看了 Wiki 以及網路上一些前輩們的介紹,發現這些不同的軟體授權方式其實還蠻複雜的...就我理解的部分,稍微介紹一些常用的授權許可證;不一定正確,只是簡單紀錄一下(整個想要逃避責任的口氣):

1. GPL
(1)其出發點在於開放程式碼、免費使用和引用、修改或衍生程式碼的開放與免費使用。
(2)符合 Copyleft 機制的授權條款。所以修改或衍生的程式碼,也必須強制繼承 GPL 的規範;確保所有使用 GPL 的自由軟體,能一直保持自由開放的原則。
(3)因為強迫繼承的關係,GPL 也引來一些批評,所以在 PTT 才會引起想要規避的討論。畢竟公司發售軟體,目的當然是為了賺錢;在遇到這種有「傳染性」的授權方式時,難免會感到困擾...

2. BSD
(1)在使用此授權方式的軟體或程式碼時,必須保留版權宣告、三條件表列以及免責聲明。
(2)可以自由的使用,修改原始碼,也可以將修改後的原始碼作為開放原始碼或者專有軟體再發佈。
(3)是使用時限制很少,寬鬆的授權方式。

3. Apache License
(1)在使用此授權方式的軟體或程式碼時,必須保留版權宣告、三條件表列以及免責聲明。
(2)可以自由的使用,修改原始碼,也可以將修改後的原始碼作為開放原始碼或者專有軟體再發佈。
(3)與 BSD 非常類似,不過在修改原始碼後,必須在版權宣告後加注。

4. MIT
(1)可根據程式的需要修改授權條款為適當的內容;但在軟體和軟體的所有副本中仍必須包含版權聲明和許可聲明。
(2)可以自由的使用,修改原始碼,也可以將修改後的原始碼作為開放原始碼或者專有軟體再發佈。
(3)與 BSD 同屬限制少又寬鬆的授權方式;唯一的不同點在於 MIT 的內容可依照程式著作權者的需求而更改。

jQuery 這個 JavaScript Library 為例,它使用的授權協議為 GPL 和 MIT 雙協議,故在使用上符合自由軟體的精神,而且限制也很寬鬆;在去年微軟也曾經發布要將 jQuery 加入 Visual Studio的相關新聞

參考資料:
(1)開放原始碼促進會(英文)
(2)OSSF::自由軟體鑄造場(中文)
(3)五種開源協議的比較(BSD,Apache,GPL,LGPL,MIT) - 整理(中文)

P.S 後來拜讀 OSSF::自由軟體鑄造場【軟體的授權觀念與自由軟體授權類別】投影片(by 自由軟體鑄造場 2008 林誠夏)後,又得到更明確的一些觀念:

自由軟體,擁有六大特性、四大自由
六大特性:開放程式原始碼、不特定授權對象、不限制使用地域、不收取授權金、不隨附擔保、釋放四大自由予後手。
四大自由:執行、研究、改良、重製散佈

另外之前我以為使用或繼承 GPL 條款的自由軟體,就不能收取費用;但其實只要收取費用的名目並不是「授權金」(其他名目如:軟體服務費),作為商業軟體販售是完全合法的!但是因為大部分軟體公司在開發專案時,會將原始碼也當作專案明細的一部分販售;如此一來就與 GPL 必須開放原始碼的宗旨相違背,所以一般軟體公司會想要規避 GPL 的原因就在這裡。

自由軟體的原始概念立意良善,是為了不讓程式撰寫人員閉門造車;如果已經有人發明了輪子,就沒有必要自己再重新設計!拜網際網路發達之賜,讓來自世界各地的程式設計師集思廣益,能更自由的運用前人的智慧,發展更好的功能、更穩定的程式,這不是很棒的一件事嗎!^^

文章標籤

danielhuang030 發表在 痞客邦 留言(0) 人氣()

從本網誌回應數最高的文章得知,大家似乎對多重下拉式選單的功能情有獨鍾啊!Ajax 能夠在不換頁的情況下,達到資料庫連結,是許多人夢寐以求的功能;而 jQuery 易上手與輕鬆操作的特性,讓我們能更簡單的運用 Ajax 達成目的。然而隨著時間的推移,過去介紹的 cascade 已經有很長一段時間沒有更新,而且在使用上其實存在不少綁手綁腳的地方;距離 jQuery 的宗旨「Write Less, Do More」似乎是還差那麼一小段距離...

經由公司的 jQuery 教育訓練,Jace 介紹了一個超讚的 jQuery Plugin:Select box manipulation。透過這個外掛的幫助,可以更輕鬆的實現多重下拉式選單的功能唷,甚至連 cascade 不容易做到的「預設值」也完全沒問題,所需要撰寫的程式碼也少於 cascade,整個就是夢幻的 Plugin!這麼神奇的外掛要怎麼用呢?以下簡單的範例,給有需要的人參考吧:範例是三階層的關聯式多重下拉式選單,分為index.php(呈現頁)、action.php(Ajax 後端資料處理頁)、index.js(JavaScript 處理)、以及 selectboxes

文章標籤

danielhuang030 發表在 痞客邦 留言(65) 人氣()

Close

您尚未登入,將以訪客身份留言。亦可以上方服務帳號登入留言

請輸入暱稱 ( 最多顯示 6 個中文字元 )

請輸入標題 ( 最多顯示 9 個中文字元 )

請輸入內容 ( 最多 140 個中文字元 )

reload

請輸入左方認證碼:

看不懂,換張圖

請輸入驗證碼