星期六, 5月 25, 2013

apache 常用設定

250行 ServerAdmin root@localhost
           系統管理員的 email ,當網站出現問題時,錯誤訊息顯示的聯絡信箱
264行 ServerName www.example.com:80
            設定主機名稱,如果沒有指定的話,預設會以你的 hostname 為依據。填入的這個主機名稱要找的到 IP
354行 UserDir disable 修改成--> #UserDir disable
361行 #UserDir public_html 修改成--> UserDir public_html
390行 DirectoryIndex index.html index.html.var 修改成--> DirectoryIndex index.html index.htmindex.php 
                                                                                                       index.html.var
730行 LanguagePriority en zh-TW ...... zh-CN
            設定顯示語系的優先順序
746行 AddDefaultCharset UTF-8 
            有兩種作法,一種是『直接指定由 WWW 宣告 Big5 編碼,而不用網頁表頭的宣告』:
            AddDefaultCharset Big5   或 AddDefaultCharset  zh-TW
            另一種則是不要宣告預設語系,由網頁表頭宣告的啦!直接註解起來即可
            # AddDefaultCharset UTF-8

星期日, 5月 12, 2013

減少JavaScript記憶體使用量

以下截錄 Ajax in Action (Ajax 實戰手冊)
  • Reuse DOM Nodes (重用DOM節點)
    Create Always 與 Create If Not Exists
  • Unlink On Hide (隱藏時斷開連結)
    即不用display=none 而用 node.parentNode.removeChild(node);
  • Break Cyclic References (斷開循環參考)
    node = null 及 node內的用到的obj也要 null
表8.4 ClickBox Benchmark
IDReuse DOM NodesUnlink On HideBreak Cyclic RefsFinal Memory Use (IE)
ANNN166 MB
BNNN84.5 MB
CNYN428 MB
DYNN14.9 MB
EYNY14.6 MB
FYYN574 MB
GYYY14.2 MB

~
本以為reuse會最省,沒想到F居然會佔最高
有使用Unlink On Hide只有G才會降低記憶間用量,C & F 都爆了
所以開發時不要用!(誤)

星期二, 3月 26, 2013

HessianPHP 中文亂碼問題

HessianPHP出了2.0,原則上v1.0才算有中文亂碼bug
但用2.0時,還是有遇到,雖然不是bug,不過總是先懷疑是別人的問題~ 哈哈
  • HessianPHP 2.0 解決方法
    install mbstring
    yum install php-mbstring
    哈 我就說過不是bug了... 只是mbstring沒用而已
    不過還有個小地方要設定,不然還是一樣亂碼~
    //php.ini
    mbstring.internal_encoding = UTF-8 

    不過本來以為沒設mbstring的encoding的話
    就手動寫utf8_decode(string), 沒想到一樣是亂碼~
  • HessianPHP 1.0 解決方法
    修改 HessianPHP的Protocol.php
    function readString(){
        return utf8_decode($string); //return $string;
    }

星期二, 1月 15, 2013

雲端迷思

最近看一篇,覺得真是見解精闢
台灣雲端計算的迷思與挑戰: Simon Chang (張善政)
幾句話就把一堆考量點打趴了
記得一開始說到雲端,就是提到資安問題

將商業資料丟給雲端廠商
講者以銀行為例,當年要大家把錢交給別人管理也引發很多問題
現在看起來可笑,不過在當時的時空背景確實會有這麼疑慮
有時怎麼解釋也說不清,換腦袋的確不是容易的事

自己公司的資安會做的比雲端業者好嗎?

對雲端沒那麼有興趣,只是覺得很多事都是相同的道理
很多人在鑽牛角針,考慮一些發生機率太低的事件
為了防止這件事,搞了一堆阻礙發展的措施
還記得一句話:「當你要討好所有人,你什麼人也討好不了」

保持腦袋清淅~

星期一, 1月 14, 2013

run commands in background


  • 將command設於背景執行
    # commandxxx &
    這時再下jobs -l 就可以看到目前背景執行的jobs
  • 將已執行中的command丟到background執行
    Ctrl + z # 先暫停目前command
    jobs -l  # 找出目前command的數值
    bg %1 

星期四, 11月 29, 2012

[書]Rapid Development - Taming Wild Software Schedules

已經忘了內容了,不過一句應該就可以帶出整本書的重點
「要快速沒有明確的方式,但避免已知的錯誤,就不會拖慢開發速度」


People

  • Undermined motivation
    Weak personnel
    Uncontrolled problem employees
    Heroics
    Adding people to a late project
    Noisy, crowded offices
    Friction between developers and customers
    Unrealistic expectations
    Lack of effective project sponsorship.
    Lack of stakeholder buy-in
    Lack of user input
    Wishful thinking

Process

星期一, 11月 05, 2012

Effective Java

8. Exceptions
條款39:只在異常情況下才使用異常機制

條款41:不要濫用checked exceptions
Checked exception會強制程式員處理異常狀態,因此過程使用會使API用起來很不方便。
如果API用戶無法做得更好,那麼他比較適合使用 unchecked 異常。
條款42:儘量使用Standard exceptions
常用的異常 (Effective Java p.177)

  • IllegalArgumentException
  • IllegalStateException
  • NullPointerException
  • IndexOutOfBoundsException
  • ConcurrentModificationException
  • UnsupportedOperationException
「選擇使用哪一種異常」並不是一種精確科學,因為並不互斥

星期二, 10月 30, 2012

eclipse 安裝 egit

兩種方法

  • Help > Install New Software
    開啟後,輸入 http://download.eclipse.org/egit/updates
    即會看到egit相關套件,點選安裝即可
  • Help > Eclipse Marketplace Client
    另一種方法,透過Eclipse Marketplace Client裝
    其實是第一種不知為何不起來,才試第二種
    開啟視窗後,輸入"egit",安裝即可

星期一, 10月 08, 2012

Eclipse “cannot be resolved to a type” error

不知什麼問題,明明上一次才compile過,也沒動到任何東西
發現在project name(右鍵)/properties裡的Java Build Path

改了JRE的環境,本身是裝jdk1.7 但這裡是寫1.5(如左圖)
就改了一下... 然後就... 好了...






後記...
跟java版本無關,而是重新compile的問題
maven不會對未更動的檔案重新compile,因此有更動的檔案(該檔案需重新compile)後
就會出現cannot be resolved to a type

解決方法:
就重新設定JRE環境,就會自動重新build一次
不曉得這是ecilpse問題還是maven問題

Reference
Eclipse “cannot be resolved to a type” error

星期三, 9月 19, 2012

ORA-24408: could not generate unique server group name

還以為是沒裝好oci8,試了半天最後把dba抓來問
才知道如果該server有設定主機名, 就要給ip對應主機名
vi /etc/hosts
192.168.1.10 localhost #將ip指向主機名

這樣就可以正常run了

Reference
ORA-24408: could not generate unique server group name

星期五, 9月 14, 2012

查linux相關process

  • 執行緒狀態 (ps)
    1. 自己 bash 程序
      ps -l
    2. 觀察系統所有的程序資料
      ps aux
    3. httpd是否執行中
      ps -ef | grep -i httpd
  • 網路連線狀態 (netstat)
    1. 顯示所有 port 80 的連線,並把結果排序
      netstat -an | grep :80 | sort
References

星期四, 9月 13, 2012

編碼問題

一堆encode方法,搞不清楚用的時機嗎
嗯  我承認我記不起來...
  • base64encode
    將資料利用64個字母(ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/)來表達,具不可讀性
    標準的Base64並不適合直接放在URL裡傳輸,因為URL編碼器會把標準Base64中的「/」和「+」字元變為形如「%XX」的形式,而這些「%」號在存入資料庫時還需要再進行轉換,因為ANSI SQL中已將「%」號用作通配符。
  • urlencode
    看完base64encode的問題,就應該瞭解為何需要urlencode了。urlendcode會轉成%XX
  • htmlentities

    如果要在網頁上出現html碼,就要透過htmlentities編碼
    也就tag的大於會變成%lt;,小於會變成%gt;
    decode: html_entity_decode()

    *htmlentities跟htmlspecialchars幾乎一樣,但htmlentities也會把中文轉成成html的東西,所以要注意

常見問題
GET傳送中文時會變成亂碼
用Big5編碼透過URL傳送GET不會有問題,但是如果使用UTF8編碼您會發現中文都會變成亂碼,這時候您要使用GET傳送時,必須先使用urlencode將要傳送的資料加密,這樣傳送中文則會正常。

星期五, 9月 07, 2012

UML各圖使用時機


  • 何時用類別圖
    類別圖是UML的主幹,隨時都用得到,而最大麻煩在包含太多東西
    • 不要試著用到所有表示法
    • 盡可能使用非常簡單的表示法
    • 不要畫出所有東西的模型。重心放在關鍵地方。常用得到、時時更新。
  • 何時用循序圖
    想知道幾個物件在某個使用案例中的行為時

Reference
UML精華第三版

星期三, 9月 05, 2012

jQuery相關extend用法

  • jQuery.extend
    說明:為jQuery增加method
    例:jQuery本身無$.add,為此增加個add method
    jQuery.extend( {     
        add:functioin(a,b){
            return a+b;     
        }   
    });
    用法
    alert($.add(5,3));  //print 8

  • jQuery.fn.extend
    說明:為selector增加jQuery method
    例:jQuery本身對selector有height(), width(),但沒有color(),為此增加color method
    jQuery.fn.extend({ 
        color: function (val) 
        { 
              if (val == undefined){           
                   return  $( this ).css( "color" ); 
                } else {      
                  return  $( this ).css( "color" , val); 
                } 
        } 
    }) );
    用法
    $("input").color("red"));  //所有input都是紅字

  • 匿名method寫法
    //1.一般function寫法
    function method1(m){alert(m);}   
    
    //2.暱名function,需有變數接
    var method2 = (function(m){alert(m);}) 
    method2("Hello");
    
    //3.直接傳參數進暱名function呼叫
    (function(m){alert(m);})("Hello")
  • (function ($){ ... })(functionName)
    指為了避$的衝突
    可以包在這裡面,如此一來$就不會衝到,即使設了jQuery.noConflict()
    常用在寫jQuery plugin
Reference jQuery.fn.extend 與jQuery.extend 用法 What a heck is a (function ($){ ... })(jQuery)

星期二, 8月 21, 2012

快樂寫程式

幾年前讀過Beyond Java,提到java的生產力太低,當時看不太懂作者提出的問題,例如強型別的宣告,自己覺得處處要宣告比較麻煩一點,不過這點會影響很大嗎?而作者大力推薦用ruby等語言,雖然有自己練習一下,可能還沒真正拿來開發過系統,所以沒有太大的感觸...

再去看看其他用ruby的使用者,都說只是想開心的寫程式,當時還以為是因為rails的關係,那年自己正在寫ORM及data mapper的東西,寫了一堆物件滿是覺得有點麻煩,看rails可利用指令去達成這些程式碼,不過這也跟程式語言本身無關呀。

原來如此

這幾年都用php開發,而最近有需要把一段php轉用.net實作,這才發現... 我的天啊,強型別這東西真是讓我想殺人!
  • 回傳值要宣告!(strong type, weak type)
  • 這感覺很直覺,可是有時我不知道我要回傳什麼,聽起來很怪,不過太常用,而且用的很順,例如取user的總數,當失敗時,不想用exception(上層要try catch,很煩 註1),想回個error code及error message 的object就沒辦法了。   
    再來php array,及 json用多了,要乖乖轉換成強型別的語言真的是要人命。php想加什麼就加,超級動態的亂加,可是.net方面,就得乖乖的宣告相對映的object,才能decode,如果有新增時,又得再去class定義,用到受不了,中途改用hashtable來存,又一直覺得用起來很不順手,再改回object,又定義到快起肖,這時才感受到弱型別真是好東西。 
  • 轉型
    int count = 10;
    System.out.println("index: " + String.valueOf(count));
    得自己把count轉成string,雖然沒什麼,不過實際在寫還挺煩的
  • overloading
  • beyond java裡,有提到overloading很不方便,只因參數不同,就得新宣告一個method,在讀完的當下認為本來就該宣告,不同參數會做不同的事,怎麼能寫在同一個method。 不過最近還真的覺得何止不方便,超煩的,有時參數只當config用,給不給都可,但就被逼著再寫一個method

後記:跟同事聊過,強型別問題,不過同事只用過java,對這沒感覺,我也說不上來


Reference

  • Beyond java (好.. 我承認我是看中文版「超越java」)

星期二, 7月 31, 2012

log4php結合FirePHP

firephp很好用,那怎麼跟log4php結合咧
download: 下載 利用ci寫的


由於ci使用library都得用new實體化
而log4php透過static method(getLogger)取得logger
用起來總是卡卡... 應該說會卡住...
所以寫成library

  1. FirePHP appender
    簡單說,就是多寫個FirePHP的Appender
    這樣log4php就可以使用FirePHP
    class LoggerAppenderFirePHP extends LoggerAppender {
         ...
        public function append(LoggerLoggingEvent $event) {
           if($this->layout !== null) 
               return;
    
           $ci = & get_instance();
           $level = $event->getLevel();
           if($level->isGreaterOrEqual(LoggerLevel::getLevelError())) {
           $ci->fb->error($this->layout->format($event));
           } else if ($level->isGreaterOrEqual(LoggerLevel::getLevelWarn())) {
           $ci->fb->warn($this->layout->format($event));
           } else {
           $ci->fb->info($this->layout->format($event));
          }
         
       }
    }
    p.s. 因為是套用在codeigniter下... 所以有出現個get_instance() XD
  2. config
    <configuration xmlns="http://logging.apache.org/log4php/">
            <appender name="firephp" class="LoggerAppenderFirePHP">
                    <layout class="LoggerLayoutPattern">
                            <param name="ConversionPattern" value="%m"/>
                    </layout>
            </appender>
            <root>
                    <appender_ref ref="firephp" />
            </root>
    </configuration>
  3. logging
        $this->load->library('Log4php');
    
        $this->log4php->log('info',"[behavior] info");
        $this->log4php->log('error',"error");
        $this->log4php->log('warn',"warn");
    結果如下



星期一, 7月 30, 2012

新人網頁程式練習題目

最近訓練新人,想了半天找了幾個練習題,儘可能常用的網站技術都有用練習到
  1. 月曆
    • 基本一週七日版型
      基礎程式邏輯
      html
    • 六、日、今日特殊底色
    • css練習 目前日期
    • 上、下月
      get參數練習
  2. 資料庫拉分頁

    sql
    分頁
    sql語法
  3. javascript練習
    九九乘法表(熟悉語法)
    dom物件操作
    事件觸發
  4. 購物車

    • 購買頁(即時計算金額)
      html
      sql
      javascript
    • 結帳頁
      session

以上應該是大部份有練習到了
再來應該是用MVC架構再重做一次...

install memcache for php

本想說這東西就yum一下就好了...
沒想到重裝時,還真卡住了,想不起來怎麼裝的
還是乖乖寫筆記吧

  • 架memcache server
    1. 事前準備
      yum install libevent
      yum install libmemcached libmemcached-devel
    2. 裝memcache server
      yum install memcached
    3. Start Memcached server
      memcached -d -m 512 -l 127.0.0.1 -p 11211 -u nobody
      d = daemon, m = memory, u = user, l = IP to listen to, p = port)
  • php存取memcache
    1. 事前準備
      利用pecl安裝,如果沒有的...
      yum install php-pear
    2. 安裝memcache
      pecl install memcache
    3. 設定php.ini
      將extension寫入php.ini
      extension=memcache.so
    4. 設定memcache server位置
      $memcache = new Memcache; 
      $memcache->connect('127.0.0.1', 11211) or die ("Could not connect"); //connect to memcached server   
      $mydata = "i want to cache this line"; //your cacheble data   
      $memcache->set('key', $mydata, false, 100); //add it to memcached server   $get_result = $memcache->get('key'); //retrieve your data   
      var_dump($get_result); //show it
就這麼簡單...

Reference

10 baby steps to install Memcached Server and access it with PHP


星期四, 7月 26, 2012

Coding Security Issues

  • 設計篇
    寫程式前先記好「電腦安全的七項設七項設計原則」
    1. 最小權限原則 ( least privilege )
    2. 經濟者是原則 ( econmy of mechanism )
    3. 安全檢測原則 ( complete mediation )
      每一筆資料存取之前,都必須先檢驗是否為合法授權行為
    4. 開放性設計原則  ( open design )
      嚴禁走系統後門的行徑
    5. 分權原則 ( separation of privilege )
    6. 最少共用性原則 ( least common mechanism )
    7. 可接受程度 ( psychological acceptability )
  • 實做篇
    理論太多沒感覺嗎?不然實做黃金三劍客記好就好...
    1. always validate your inputs
    2. always filter your outputs
    3. nerver trust users

    實做細節注意overflow
    避免使用建議使用
    gets()fget()
    strcpy()strncpy()
    stract()strncat()

星期四, 7月 12, 2012

ssl 在ie下網址錯誤

crt1: aa.com
crt2: host2.aa.com

appache裡設定ssl.conf
<VirtualHost *:443>
SSLCertificateFile /etc/pki/tls/certs/aa_com.crt
SSLCertificateKeyFile /etc/pki/tls/private/aa_com.key
SSLCertificateChainFile /etc/pki/tls/certs/aa_com.ca-bundle
</VirtualHost>

<VirtualHost *:443>
SSLCertificateFile /etc/pki/tls/certs/host_aa_com.crt
SSLCertificateKeyFile /etc/pki/tls/private/host_aa_com.key
SSLCertificateChainFile /etc/pki/tls/certs/host_aa_com.ca-bundle
</VirtualHost>
在firefox, chrome都正常
而在...ie時,host2.aa.com的憑證是失效的

研究了很久,發現網址不正確,這下有趣了,明明就是來驗證網址的
居然說網址不正確

這才發現原本應抓host2.aa.com的憑證,居然是抓aa.com,而判斷目前網址錯誤

後來將ssl.conf順序倒了一下就解決了
我想是virtualhost *:443的關係吧
不過寫成;VirtualHost aa.com:443 順序一樣要細的在上
而且還會有warnning指出前者overlap後者

最後發現是萬惡ie沒辦法分辨...
最後只能... 再架個server各自獨立

星期二, 7月 10, 2012

firefox 的 sec_error_unknown_issuer 問題

最近用了Comodo發的ssl憑證建了https
結果在firefox遇到了sec_error_unknown_issuer問題



查了一下得加個ca-bundle設定
在跟comodo申請憑證後,會拿到
  • YOUR_WEBSITE.crt
  • YOUR_WEBSITE.YOUR_WEBSITE.csr
  • YOUR_WEBSITE.bundle..ca-bundle
apache的話到/etc/httpd/conf.d/ssl.conf
SSLCertificateFile /etc/pki/tls/certs/YOUR_WEBSITE.crt
SSLCertificateKeyFile /etc/pki/tls/private/YOUR_WEBSITE.key
SSLCertificateChainFile /etc/pki/tls/certs/YOUR_WEBSITE.ca-bundle


#後記
後來遇到https都連不到,才發現原來在load balance的server上也要給


References

星期四, 7月 05, 2012

偵測新視窗的close event

如何偵測新視窗的close event咧
<script type="text/javascript">
    var win = window.open("secondwindow.html", "_blank");
    win.onunload =onun; 

    function onun() {
        if(win.location != "about:blank") // This is so that the function 
                                          // doesn't do anything when the 
                                          // window is first opened.
        {
            alert("closed");
        }
    }
</script>
不過這方法不能跨網域
也就是如果child開到不同網域,close不會觸發unload事件
解決方法先轉個空白的網頁,裡面夾iframe去連該網頁

後記-跨網頁問題
被同事嗆「閃開! 讓專業的來」 見下面程式碼
也不去bind event,只是持續monitor關了沒...真是好招...
var child = window.open('http://google.com','','toolbar=0,status=0,width=626,height=436');
var timer = setInterval(checkChild, 500);

function checkChild() {
    if (child.closed) {
        alert("Child window closed");   
        clearInterval(timer);
    }
}


References

星期一, 7月 02, 2012

mysql常用日期query

  1. 當天的資料
    select * from table where to_days(column_time) = to_days(now());
    select * from table where date(column_time) = curdate(); 
  2. Between日期
    WHERE (created BETWEEN '2012-06-19' and '2012-06-30 23:59:59' ); 
    注意結尾是最後一天一秒,否則只會出現到前一天的資料
  3. 最近7天,1個月
    WHERE DATE_SUB( CURDATE( ) , INTERVAL 7 DAY ) <= `created_date`;
    WHERE DATE_SUB(CURDATE(), INTERVAL INTERVAL 1 MONTH) <= `created_date`;
  4. 本周
    從當週的Sunday開始到星期六的七天資料
    select * from wap_content where week(created_at) = week(now);
    
Reference

星期四, 6月 28, 2012

常用sed與awk


  1. 統計行數
    單一檔案
    awk 'END{print FNR}' xxx.log

    多個檔案
    awk 'END{print FNR}' *.log
    用linux本身的wc指令也可達到效果
    wc -l *.log
  2. 取出重覆及不重覆次數
    [root@test]# cat a.txt
    12 1209185885333940
    12 1209185089989307
    12 1209185891525318
    13 1209186004855839
    13 1209185995006463
    13 1209185995006463

    awk '{a[$1]++}flag[$1,$2]!=1{b[$1]++}{flag[$1,$2]=1}END{for (i in a)print i,a[i],b[i]}' a.txt
    --
    12 3 3
    13 3 2
    reference: 请教awk如何同时统计 总数与不重复个数?
  3. 列出符合的資料
    • 單筆
      sed '0,/PARSE_FROM_HERE/' a.txt
      awk '/regex/ {getline;print}' a.txt
    • 之後(含符合項)
      awk '/regex/,0' a.txt
      awk '/regex/,G' a.txt
    • 之後(不含符合項)
      sed '0,/regex/d' a.txt
      awk '/regex/ {getline;print}' a.txt
    • 之前
      試半天用不出來,乾脆先倒過來讀,就可用上面的方法做出來了
      sed '1!G;h;$!d' test | awk '/regex/,0'

星期二, 6月 26, 2012

vim及tmux視窗常用指令

兩個切換視窗切到指令都亂了
  1. 合併兩個即有視窗
    • vim: vert sb#
    • tmux
  2. 將目前的pane抽成獨立視窗
    • vim:
    • tmux: CTRL-b !
  3. 分割頁切換
    • vim: CTRL-W 方向鍵
      或是CTRL-W j(往右) or w(往下),大寫則相反
    • tmux: CTRL-o

星期二, 6月 19, 2012

php與awk

  1.  在php中執行shell
    可利用shell_exec
    shell_exec('ls -l');
  2. 使用awk
    $data = shell_exec("awk '{print $1}' " . $filepath );
  3. 取得單行awk內容
    由於shell_exec是一次將每行內容回傳,如果要一行行取得awk的資料就要搭配exec
    $feeds = array();
    exec("awk '{print $1}' " . $filepath, $feeds );
    foreach($feeds as $feed)
        echo $feed . '< br/>';
    

星期二, 6月 12, 2012

將url字串的參數轉為array

  1. 取出query部份
    $url = 'http://username:password@hostname/path?arg=value#anchor';
    $urlinfo = parse_url($url);
    ------------------------
    Array
    (
        [scheme] => http
        [host] => hostname
        [user] => username
        [pass] => password
        [path] => /path
        [query] => arg=value
        [fragment] => anchor
    )
  2. 轉成array
    $str = "first=value&arr[]=foo+bar&arr[]=baz";
    parse_str($str);
    echo $first;  // value
    echo $arr[0]; // foo bar
    echo $arr[1]; // baz
    
    parse_str($str, $output);
    echo $output['first'];  // value
    echo $output['arr'][0]; // foo bar
    echo $output['arr'][1]; // baz

References

星期一, 6月 11, 2012

php連oracle stored procedure

  • sql
    1. 建立連線
      $conn = oci_connect('YOUR_ACCOUNT', 'YOUR_PASSWORD','//IP_ADDRESS:PORT/SERVICE_NAME');
    2. 下sql
      $sql = "SELECT ID, NAME as \"name\"
      FROM CATEGORY
      WHERE PARENT_ID = 0 AND STATUS = 1
      ORDER BY CATEGORY_ID ASC";
    3. 取資料
      $stid = oci_parse($conn, $sql);
      oci_execute($stid);
      $nrows = oci_fetch_all($stid, $res,0, -1, OCI_FETCHSTATEMENT_BY_ROW);

      //echo "$nrows rows fetched
      print_r( $res);*/
  • stored procedure
    1. 建立連線
      $conn = oci_connect('YOUR_ACCOUNT', 'YOUR_PASSWORD','//IP_ADDRESS:PORT/SERVICE_NAME');
    2. 連stored procedure
      假設sp名為myStoredProcedured,目的是將取到的時間轉為unit timestamp
      $sql ="begin
      :result := myStoredProcedured(:result => to_date(:myDate,'yyyy-mm-dd'));
      end; ";
      $stmt = oci_parse($conn,$sql) or die('could not parse statement.');

      //bind參數
      oci_bind_by_name($stmt,':result',$result,10); //回傳值需靠參數回傳
      oci_bind_by_name($stmt,':myDate',$myDate,10);

      //給值
      $myDate = '2012-06-12';

      //取值
      oci_execute($stmt) or die('execute');
      print_r($result);
    3. 給參數

星期日, 6月 03, 2012

linux個人環境設定

每次重灌或換個新環境就得憑記憶重設定
乾脆直接記下來省時間...
感謝Dockerfile等工具... 以後這些都可以不用理了...

  1. bashrc
    vim ~/.bashrc
    
    export TERM=screen-256color #註1
    

    註1: lose vim colorscheme in tmux mode

  2. vim 環境設定
    • 環境
    • 縮排
  3. tmux
    # General configuration.
    # $ tmux show-options -g
    set -g base-index 1
    set -g display-time 5000
    set -g repeat-time 1000
    set -g status-keys vi
    set -g status-utf8 on
    set -g status-bg black
    set -g status-fg white
    set -g status-justify left
    set -g status-interval 1
    set -g status-left-length 15
    set -g status-right-length 55
    set -g status-left "#[fg=white,bright] #[fg=yellow,bright]#S #[default] |"      # session-name
    set -g status-right "#[fg=red,bright][ #[fg=cyan]#(git branch --no-color | sed -e '/^[^*]/d' -e 's/* //') #[fg=red]]#[default] #[fg=yellow,bright] %Y-%m-%d #[fg=green]%H:%M:%S #[default]#[fg=magenta,bright]#[default]"
    
    # window setting
    setw -g utf8 on
    setw -g window-status-format " [#I] #W "
    setw -g window-status-current-format " [#I] #W "
    setw -g window-status-current-fg black
    setw -g window-status-current-bg green
    setw -g window-status-current-attr default
    
    # using function keyCtrl+A
    unbind C-b
    set -g prefix ^A
    bind a send-prefix
    
    # split window
    unbind %
    unbind '"'
    bind v split-window -h
    bind | split-window -h
    bind h split-window -v
    bind - split-window -v
    

    設好後,重啟config
    tmux source-file ~/.tmux.conf
  4. git

星期三, 5月 30, 2012

linux監控磁碟空間

  • df 監控可用磁碟空間與inode數舉
    • 語法
      df [options] [dir]
    • 說明
      顯示dir所的檔案系統磁碟空間用量。df會依據/etc/fastab 組態檔找出dir掛載點,然後顯示檔案系統資訊。若沒指定dir,則df會顯示所有已掛載的檔案系統資訊
    • 常用選項
      -h 以較容易辨識的單位(M、G)顯示數值
      -i 顯示inode用量資訊。若不指定,則顯示磁碟空間用量
      • 範例一
        檢視所有檔案系統的磁碟空間用量:
        # df -h
      • 範例二
        檢視所有檔案系統的inode用量:
        # df -i
      • 範例三
        查看目前工作目錄位於哪個分割區:
        # df .

  • du 監控磁碟用量
    • 語法
      du [options] [directories]
    • 說明
      顯示directories的磁碟使用資訊。如果省略directories,則顯示現行工作目錄的用量。
    • 常用選項
      -a 顯示所有檔案,不只是目錄。
      -c 累計所顯示的項目總用量
      -h 以較容易辨識的單位(M、G)顯示數值
      -s 僅印出指定目錄本身摘要資訊,而不是遞迴顯示每個子目錄
      -S 子目錄的用量不列入計算
      • 範例一
        檢祖/etc/rc.d 的disk用量
        # du /etc/rc.d
      • 範例二
        顯示 /etc 的disk用量:
        # du -sh /etc
      • 範例三
        顯示 /etc 的disk用量,但不包括其下的子目錄:
        # du -Ssh /etc
      • 範例四
        誰耗用最多空間(/home/*):
        # du -csh /home/*
        排序
        # du -cs /home/* | sort -nr  #用h會當成文字 ex, 1k,11k,2k

iframe autoresize

先前一直從iframe內部出發,向parent呼叫調整高度
後來發現... parent自己取iframe的內容高去調整就可以了


References
Iframe Auto Resize Height

將scroller移到最上面

兩個方法
//1.html本身的方法
top  //嗯 就這樣

//2.就把scrollTop設定為0就可以了
 $('html, body').scrollTop(0);

厲害點...加點滑動的感覺


test
top

References

星期六, 5月 26, 2012

php 時間轉換函式

  1. 轉換unix timestamp為可讀日期時間
    date("Y-m-d H:i:s", $timestamp);
    線上轉換
  2. 可讀日期轉換unix timestamp
    strtotime("2009-11-03 11:24:00PM");

星期三, 5月 23, 2012

php array轉xml, json

轉json就沒什麼好說的了,想說轉xml應該也是很簡單的東西,不過還真遇到一些問題
  1. array to xml
    原本在google了一段code後,後來發現有中文xml會掛掉因為有不合法字元,
    後來找到以下的code有編碼過,才知道原是編碼的問題
    function toXml($data = array(), $structure = NULL, $basenode = 'xml'){
       // turn off compatibility mode as simple xml throws a wobbly if you don't.
       if (ini_get('zend.ze1_compatibility_mode') == 1)
       {
          ini_set('zend.ze1_compatibility_mode', 0);
       }
    
       if ($structure == NULL)
       {
       $structure = simplexml_load_string("<?xml version='1.0' encoding='utf-8'?><$basenode />");
       }
    
       // loop through the data passed in.
       $data = $this->_force_loopable($data);
       foreach ($data as $key => $value)
       {
          // no numeric keys in our xml please!
          if (is_numeric($key))
          {
             // make string key...
             //$key = "item_". (string) $key;
             $key = "item";
          }
    
          // replace anything not alpha numeric
          $key = preg_replace('/[^a-z_]/i', '', $key);
    
          // if there is another array found recrusively call this function
          if (is_array($value) OR is_object($value))
          {
             $node = $structure->addChild($key);
             // recrusive call.
             $this->_format_xml($value, $node, $basenode);
          }
          else
          {
            // Actual boolean values need to be converted to numbers
            is_bool($value) AND $value = (int) $value;
    
            // add single node.
            $value = htmlspecialchars(html_entity_decode($value, ENT_QUOTES, 'UTF-8'), ENT_QUOTES, "UTF-8");
    
             $UsedKeys[] = $key;
    
             $structure->addChild($key, $value);
          }
       }
    
       // pass back as string. or simple xml object if you want!
       return $structure->asXML();
    }
    
    function _force_loopable($data){
       // Force it to be something useful
       if ( ! is_array($data) AND ! is_object($data))
       {
          $data = (array) $data;
       }
    
    return $data;
    }
    
  2. 下header
    browser才會當成xml,而不是html
    $array = array(...);
    header('Content-type: application/xml;charset=utf-8');
    exit(toXml($array)) ;
    

結合一下兩者,利用同一個function回覆
//給header用
$_supported_formats = array(
                'xml' => 'application/xml',
                'rawxml' => 'application/xml',
                'json' => 'application/json',
                'jsonp' => 'application/javascript',
                'serialize' => 'application/vnd.php.serialized',
                'php' => 'text/plain',
                'html' => 'text/html',
                'csv' => 'application/csv'
        );


function response($data, $format = 'json'){
    header('Content-type: '.$this->_supported_formats[$format]);
    switch (strtolower($format)){
        case 'xml':                                
                exit($this->toXml($data));
        case 'json':
        default:
            exit(json_encode($data));
    }
}

星期三, 4月 18, 2012

網站上線前測試項目

javascript測試事項
  • 是否支援json
    //檢查json是否存在
    if (typeof (JSON) == 'undefined') { //沒有 JSON 時才讓 browser 下載 json2.js
        $('head').append($("<script src="json2.js" type="text/javascript">
    ));
    
    }
  • 兼容性测试
    不同browser都要試一下

unit test測試事項
  • 邊界值及最大、最小值

get reals一書提到...

對於每一個新功能你需要……
  • 1. 對它說不
  • 2. 強迫它證明自己的價值
  • 3. 如果得到否定的答案,就此打住。如果是yes,繼續往下……
  • 4. 為界面繪製草圖
  • 5. 設計界面
  • 6. 編寫代碼
  • 7-15. 測試,改進,測試,改進,測試,改進,測試,改進……
  • 16. 檢查幫助文字是否需要修改
  • 17. 更新產品預覽流程(如果有必要的話)
  • 18. 更新用於銷售的拷貝(如果有必要的話)
  • 19. 更新服務條款(如果有必要的話)
  • 20. 檢查是否違背之前的任何許諾
  • 21. 檢查價格體系是否受影響
  • 22. 上線
  • 23. 深吸一口氣

星期六, 3月 17, 2012

firefox同步

這實在太強大了...
之前有擴充套件(add-on)可以同步記錄書籤
但現在firefox自己出了"選項/同步",只能記錄書籤已經不夠看了

試用了一下,真的是太棒了
除了書籤外,最重要的是每次換台新電腦就得要重安裝套件
居然連這也能同步,太強了... 我要按個讚

後記...
firefox不知為何在2012.7常當掉
發現是在輸入項(input)時,很容易掛
因為太頻繁了,所以只好先改用chrome

用完Chrome後...
好吧... 我改用Chrome了
因為browser是綁gmail帳號
chrome就自動把書籤、autocompleted都同步了...
firefox強項剩firebug...

星期五, 3月 09, 2012

linux prompt

  1. 設置檔
    • 全users
      /etc/profile or /etc/bashrc
    • 個別user
      ~/.bash_profile , ~/.bash_login , ~/.profile , ~/.bashrc or ~/.bash_logout
  2. 客製化prompt
    PS1='[\u@\h \w] \$ # ' #即為user@host ~

    PS1="\e[\u@\h \w]$ \e]" #即為[user@host ~]
    加框'[', ']',由於是key words所以要加\e
    而0;32m 是指顏色,其他以此類推應該就看的出來了
  3. 加上顏色
    PS1="\e[0;32m[\u@\h \w]\e]$ \e[m]" #即為[user@host ~]
  4. 啟使
    source .bashrc
    or
    . .bashrc
  5. Changing foreground and background bash prompt colors

    Syntax for changing colors in the bash is as follows:
    \033[ -> Indicates the beginning of color in the text
     x;yzm - Indicates color code
     \033[00m - Indicates the end of color in the text  

截錄常用的字元代表意思
Bash special characterBash special character explanationBash special characterBash special character explanation
\] end a sequence of non-printing characters \[ begin a sequence of non-printing characters, which could be used to embed a terminal control sequence into the prompt
\h the hostname up to the first `.' \H the hostname
\s the name of the shell, the basename of $0 (the portion following the final slash) \l the basename of the shell's terminal device name
\$ if the effective UID is 0, a #, otherwise a $ \u the username of the current user
\w the current working directory \W the basename of the current working directory
\D{format} the format is passed to strftime(3) and the result is inserted into the prompt string; an empty format results in a locale-specific time representation. The braces are required

個人配置檔
#prompt
if [ $TERM = 'xterm' ]
then
        PS1='\e[0;32m[\[\033[02;32m\]\u@\h\[\033[01;34m\] \w\e[0;32m]\$\e[m '
else
        PS1='[\u@\h \w] \$ # '
fi

# colorful man page 
export PAGER="`which less` -s"
export BROWSER="$PAGER"
export LESS_TERMCAP_mb=$'\E[01;36m'
export LESS_TERMCAP_md=$'\E[01;36m'
export LESS_TERMCAP_me=$'\E[0m'
export LESS_TERMCAP_se=$'\E[0m'
export LESS_TERMCAP_so=$'\E[01;44;33m'
export LESS_TERMCAP_ue=$'\E[0m'
export LESS_TERMCAP_us=$'\E[01;33m'

References

Bash prompt basics

星期二, 3月 06, 2012

FirePHP no message in FireBug console

忘記更新了什麼東西,結果FirePHP居然沒反應了
goolge了一下,也有人遇到,印象中是更新了FirePHP的套件就解決了

而最近公司更換網域,環境也跟著改變
重新安裝FireBug及FirePHP後,居然又沒反應了
又找不到原本解決的網頁,真是快瘋了

後來注意到firefox有個提醒列
提到要"enable Net Panel ..."
才去開放script及net panel,如下圖

才知道FirePHP需要開啟net panel才能動....

星期四, 2月 23, 2012

What is my IP? (Public IP address)

Using wget
wget -q -O - checkip.dyndns.org|sed -e 's/.*Current IP Address: //' -e 's/<.*$//'
Using curl
curl -s checkip.dyndns.org|sed -e 's/.*Current IP Address: //' -e 's/<.*$//'

curl -s http://whatismyip.org/
Using Lynx
lynx -dump checkip.dyndns.org

lynx -dump www.whatismyip.com | grep 'Your IP'
Reference Linux command: What is my IP? (Public IP address)

星期二, 2月 21, 2012

mysql grant

最近一個案子要連到廠商的db讀資料
不過不知卡在什麼地方,一直沒辦法連到db
後來想到是mysql沒開遠端連線的權限,想透過phpmyadmin去開
但是限制一堆,只能用ssh進mysql server下指令...
用慣了phpmyadmin.... 要用指令下授權...ㄟ... grant all db.... 什麼.... 放棄
下select就算了,下授權... 不知多久才用一次的東西...google一下吧..
  • 先連db囉
    $ mysql -u root -p
  • 查詢 某 User 的權限
    這樣就可以知道該User是否有從某ip連db的權限
    mysql> select User,Host from mysql.user;
    +------+---------------------------+
    | User | Host |
    +------+---------------------------+
    | root | localhost |
    +------+---------------------------+
    1 rows in set (0.00 sec)

  • add SELECT,INSERT privileges to a user using GRANT
    上例中,root未開放192.168.0.1的連線
    這裡假設開放root(密碼:ok1234)可從192.168.0.1連線db_base下的所有table(利用*來代表所有的table)的權限
    GRANT SELECT,INSERT ON db_base.* TO root@192.168.0.1 IDENTIFIED BY 'ok1234';

References

git增減remote及fetch and pull branch


  • 增加一個remote
    //增加一個在github的remote
    git remote add github https://github.com/username/Hello-World.git
    
    //origin也視成一個remote,所以一樣的方法,只是叫origin
    git remote add origin https://github.com/username/Hello-World.git

當origin或remote有local沒有的branhc要如何抓下來
  • 自己的
    #git branch
    * master
  • Origin或remote的
    #git branch
    check
    * master
  • 利用fetch抓回來
    #git fetch origin check:check 

星期五, 2月 10, 2012

ie中session遺失問題

先前寫個cross site的程式給廠商呼叫
結果最近在說只有ie會掛,firefox, chrome都通過
一試之下,還真的同事的全掛,最有趣的是我的ie卻能過
且我ie 7,8,9全試了,都可以,為什麼.. 還沒查出來

因為ie不能看iframe裡的內容,而自己的電腦又不會有問題
只能請同事看,查到快起肖了
最後發現是session值會不見

看到有人提到session的useragent不同,而ci裡的config會比對,只要關掉即可
可是還是失敗,總之查了半天,突然看到P3P的字眼...
才想到以前也有遇到ie跨網域取不到相關值的問題,加上後就解決了
friday night加班到9點...更~~~~~~~~~~~~

網上有人整理好了
  • How to set p3p http header in ASP.Net?
    HttpContext.Current.Response.AddHeader("p3p", "CP=\""IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT\""")
  • How to set p3p http header in PHP?
    header('P3P:CP="IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT"');
  • How to set p3p http header in JSP?
    response.setHeader("P3P","CP='IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT'")
  • How to set p3p http header in ColdFusion?
    <cfheader name="P3P" value="CP='IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT'">

References

星期四, 2月 09, 2012

利用 php 本身寫 error log 及 error/warning/notice message

  • error_reporting
    設定php回發生錯誤的等級
    error_reporting(0);  // Turn off all error reporting
    ini_set('error_reporting', E_ALL);  // Same as error_reporting(E_ALL);
  • error_log
    bool error_log ( string $message [, int $message_type = 0 [, string $destination [, string $extra_headers ]]] )
    Sends an error message to the web server's error log or to a file.
    需寫入file,因此需指定file path
    用法
    //log to file
    ini_set('error_log', dirname(__FILE__) . '/error_log.txt');  
    
    // Send notification through the server log if we can not
    // connect to the database.
    if (!Ora_Logon($username, $password)) {
        error_log("Oracle database not available!", 0);
    }
    
    // Notify administrator by email if we run out of FOO
    if (!($foo = allocate_new_foo())) {
        error_log("Big trouble, we're all out of FOOs!", 1,
                   "operator@example.com");
    }
    
    // another way to call error_log():
    error_log("You messed up!", 3, "/var/tmp/my-errors.log");
    
  • error/warning/notice message
    定義log level多配合log4php,不過也可透過trigger_error
    即可靠php本身達成此效果
    trigger_error("Notice Message",E_USER_NOTICE);
    trigger_error("Warning Message",E_USER_WARNING);
    trigger_error("Error Message",E_USER_ERROR);
    如此就不用再掛log4php,就能方便帶訊息
也就是說error_report 是設定php觸發回報錯誤的等級
如果想利用此機制寫自定的訊息就可透過trigger_error
而error_log就自己想log什麼就log什麼

error_report設定篇
開啟是否顯示error及log的等級
  • 在php.ini中設定
    display_errors = On 
    
  • 在.php中設定
    每次要到php.ini設定就太累了,這邊有方法可以直接在.php裡,直接設定log,這樣開發起來就方便多了,且不會動到整體環境
    ini_set('display_errors', 1);   //turn on display error on screen
    ini_set('log_errors', 1);     //turn on log error
    error_reporting(E_ALL); //log all errors and warnings


常見常數定義
列出常見的幾個,其他看官網Predefined Constants
Constant Description Note
E_NOTICERun-time notices. Indicate that the script encountered something that could indicate an error, but could also happen in the normal course of running a script.
E_STRICTEnable to have PHP suggest changes to your code which will ensure the best interoperability and forward compatibility of your code.Since PHP 5 but not included in E_ALL until PHP 5.4.0
E_ALLAll errors and warnings, as supported, except of level E_STRICT prior to PHP 5.4.0.

References

星期日, 1月 29, 2012

亂數order id

最近在寫銷售系統,由於會把order id給客戶,主管反應這樣會被會看出銷售量,所以要改成亂數,避免競爭對手等看出銷售數量。

研究了半天,自己用padding、加亂數的方法似乎還是會被察覺,google後,覺得還是用加密比較簡單

  • two way encryption
    先下載加密法encryption_class.php
    在encryption_class.php裡,有以下兩行
    $this->scramble1 = '! #$%&()*+,-./0123456789:;>=<?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~';
    $this->scramble2 = 'f^jAE]okIOzU[2&q1{3`h5w_794p@6s8?BgP<dFV=m D>TcS%Ze|r:lGK/uCy.Jx)HiQ!#$~(;Lt-R}Ma,NvW+Ynb*0X';
    此加密法是簡單的利用代換字母做加密,記得叫Caesar Cipher什麼的,主要利用自己的key,去對應scramble相同字母的位置
    當然這樣1對1的對應,很容易就被破,所以裡面的function _applyFudgeFactor(),就是在每次計算代換字母就偏移順序
    利用scramble1把key轉換成順序,每次再偏移位置,從scramble2取出該字母當祕文
  • 產生加密後的order id
    <?php
    include 'encryption_class.php';
    
    $crypt = new encryption_class(); 
    
    $key = "A-COMPLETELY-RANDOM-KEY-THAT-I-HAVE-USED";
    // Min length of 8 for encrypted string
    $min_length = 8;
    
    $order_id = 123456789;
    
    print "Original: " . $order_id . PHP_EOL;
    
    $encrypt_result = $crypt->encrypt($key, $order_id, $min_length); 
    
    print "Encrypted: " . $encrypt_result . PHP_EOL;
    
    // DECRYPT
    $decrypt_result = $crypt->decrypt($key, $encrypt_result);
    
    print "Decrypted: " . $decrypt_result . PHP_EOL;
    
    ?>
    結果如下
    Original: 123456789
    Encrypted: 2UD5UIK9S
    Decrypted: 123456789

  • 以數字實作
    不過問題又來了,因為order id用integer,所以要求全是數字
    • 轉ascii code
      就直接全轉3位數的ascii code

      $numeric_cipher='';
      for($i=0;$i<strlen($decrypt_result);$i++){
          $numeric_cipher .= str_pad(ord(substr($decrypt_result,$i,1)),3,'0',STR_PAD_LEFT); //不到3碼,左邊補0至3碼
      }
      

      不過實在太長了,5位數就要長到15個數字
      所以ascii百位數後全不用,即d(100),e(101),...
      這樣padding就只要2位,這樣5位數也只要10個數字
    • 還嫌太長!?最終極版大絕!!!
      由於key是對應scremble的排序...
      把key跟scremble都只放數字,這樣............ 應該夠短了吧...
      就是有點容易猜...不過一時間內應該也夠用了
      order id太長,將來要查也不好查
      • 改encryption_class.php
        //把scramble改成如下,不要重覆,順序可亂擺,不要一樣就好
        $this->scramble1 = '0123456789';
        $this->scramble2 = '2135794680';
      • 改key值
        因為要對應scramble,所以key有什麼值,scramble就要有什麼值,否則對應不到
        至於密文min length長度,當超過明文長度時,預設是在字串後方補上空格
        但因為得全為數字,所以scramble沒有空格,造成空格對應不到,因此不能超過order id的長度

        //key可隨意變化,但key的值一定要出現在scramble裡
        $key='1234534567890';   
        $key='11223344';   
        $key='68490';   
        
        $min_length = strlen($order_id); //因為1對1,所以不能超過order id的長度
        
      結果如下
      OriginalEncryptedDecrypted
      151
      70
      115011
      991999
      100583100
      101585101
      110505110
      111507111
      這就可以看出來,當key、scramble、偏移量相同,位於前面的字母相同時,代碼都會相同,變化不夠大,忘了那資安的名詞叫什麼,意思是當原文變化不大時,密文的變化仍要夠大,如md5等
      因為可變化的太少了,不過應該算堪用了
      另外還有兩個問題
      • original為7時,沒辦法反解
        原作者在decrypt用empty,所以遇到0會當false,改!isset即可
        相同的,當encrypt 0時,也會當成false,也需要改成!isset
      • decrypt result為0xx
        雖是正常,不過ordre id用integer,這個0就會不見,到時會解不回去
      min length問題
      由於是全數字,又密文長度不能超過明文長度,實在容易被猜出來
      那如何超過明文長度咧...
      解法:不補空格,補0,在明文字串前方補足0,由於integer前面有0,也是當成0,所以沒差
      ex. $id = 50; $min_length = 4;
      $id = '0050'; // 補2個0,足4位
      在encryption_class.php裡
      function encrypt(){
          ...
          //$source = str_pad($source, $sourcelen);              //原作法
          $source = str_pad($source, $sourcelen, '0', STR_PAD_LEFT); //新的作法
          ...
      


References
Four ways to generate unique id by PHP
How to generate Unique Order Id (just to show touser) with actual Order Id?

星期四, 1月 19, 2012

該死的ie form

在html包form實在是在平常不過的事了
在firefox, chrome都跑的好好的
沒想到ie跑版,馬上開F12來看一下
天殺的那是在iframe裡... 要到該網頁又要帶參數....好想殺人
查了半天的css實是看不出原因

亂搬了一下form,居然有變化了
最後把margin設為0... 更.. 好了....
同事事後也說,他也遇過,說這form實在很奧妙....

忘了是ie什麼版本影響了... 總之先記下來
ie我恨你...

星期日, 1月 15, 2012

PHP5.3, CentOS,裝Oci8, pdo_oci8

沒連過oracle,一開始要用還真搞不太懂
載了2個檔案,共2G回來,還是不會用
最後看只需載個client的basic,供oci連線即可
看完網路一裝教學,還是裝不起來,在交叉比對下,終於成功了~~~

os: CentOS 6.4
php: 5.3
download Instant Client Downloads
自己的環境是linux 64bit, 所以載了 Instant Client for Linux x86-64
  1. Install oracle instant client
    • oracle-instantclient11.2-basic-11.2.0.3.0-1.x86_64.rpm
    • oracle-instantclient11.2-devel-11.2.0.3.0-1.x86_64.rpm
    • oracle-instantclient11.2-sdk-11.2.0.1.0-1.x86_64.zip
    # rpm -ivh oracle-instantclient11.2-basic-11.2.0.3.0-1.x86_64.rpm
    # rpm -ivh oracle-instantclient11.2-devel-11.2.0.3.0-1.x86_64.rpm
  2. 設定ORACLE_HOME
    設定ORACLE_HOME的提示真是讓我暈倒,說要指到lib
    設好了,但在install oci時,會掛,最後試出只要到"HOME"就好了
    看下面設定 vi /etc/profile
    export ORACLE_HOME=/usr/lib/oracle/11.2/client64
    export ORACLE_OWNER=oracle
    export ORACLE_SID=ora1
    export LD_LIBRARY_PATH=$ORACLE_HOME/lib
    export PATH=$ORACLE_HOME/bin:$PATH
    export TNS_ADMIN=$ORACLE_HOME/network/admin
    export NLS_LANG="AMERICAN_AMERICA.AL32UTF8"
    啟動環境變數
    source /etc/profile
  3. 解壓sdk並把裡面的sdk裡的資料複製到/usr/include
    # unzip oracle-instantclient11.2-sdk-11.2.0.1.0-1.x86_64.zip 
    # cp -fr instantclient_11_2/sdk/include/* /usr/include
  4. install oci
    • Installing OCI8 from PECL 
      • Use 'pecl install oci8' to install for PHP 8.
      • Use 'pecl install oci8-2.2.0' to install for PHP 7.
      • Use 'pecl install oci8-2.0.12' to install for PHP 5.2 - PHP 5.6.
      • Use 'pecl install oci8-1.4.10' to install for PHP 4.3.9 - PHP 5.1.

      p.s. 基本上裝最新版即可,它有向下相融
            就這麼簡單,過程會要求輸入ORACLE_HOME的位置,如果第3步有做的話,就按enter即可 如果找不到pecl,就先安裝pear

      yum install php-pear
      #如果找不到的話,就先增加repository
      rpm -Uvh http://repo.webtatic.com/yum/centos/5/latest.rpm
      yum --enablerepo=webtatic install php-pear

  5. 設定php.ini
    vi /etc/php.ini , add the line extension=oci8.so
    再重開apache即可
    # service httpd restart

    這時下php -m 就會看到oci8了~ 開心
  6. 測試
    <?php
    $option = array(
        'ip'            => '10.0.3.20',
        'port'          => '15210',
        'account'       => 'web',
        'password'      => 'FEF00CB',
        'service_name'  => 'WXS4'
    );
    
        $db = "(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST={$option['ip']})(PORT={$option['port']}))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME={$option['service_name']})))";
    
        if(function_exists('ocilogon')){
            $c1 = ocilogon($option['account'],$option['password'],$db) or die('OCI Connect error, wrong connection string');
            echo 'OCI Connect pass. yes!!!';
        }else{
            echo 'ocilogon not exists, installment is not correct';
        }
有看到某些文章指出要安裝pdo,自己裝了也一直失敗
後來發現php5.3已經有了,所以不用裝了

全手動安裝

在公司封閉的網路,只能手動安裝可以參考這篇 PHP 5.3 連線 Oracle 的客戶端及 PDO_OCI 模組安裝

issue
  • pdo_oci unsupported oracle version 
由於oracle instantclient可能出了新版,而pdo_oci未更新,可以直接改pdo_oci/config.m4 ,自己加上要的版本,search 一下unsupported version字眼,就可以找到,詳細可參考這篇 

p.s. 改完記得要先phpize --clean,不然configure的內容不會生效哦!!!

星期三, 1月 11, 2012

教授比較強!?

以前唸專科時,學校裡有教授頭術及碩士畢業的講師
曾經有個交大畢業的碩士講師跟我說過
有些學生比較看不起講師,覺得教授等級才夠看

專科時期,算是個人進入資訊領域的起萌期
老師個人當然還是有強弱,不過都覺得可學習的滿多的
也沒有感覺有沒有教授的頭銜有什麼差別

後來進了大學
老師都至少助理教授以上等級,且大多為40多歲以上
且教授等級的老師在業界或學術界都頗具名氣
聽課時,就真的覺得有差,除了講義上的東西,還可以講的更深入
一些理論的東西,也能講的比較活,感覺比較實用

有位教授說了句玩笑話:「教授就是專門把簡單的東西教的很難。」
原本只是會心一笑,後來才體會到,教授已經多年研究這領域,且每年都重複教這東西,已經成精了,而我們這些小毛頭,一時要聽懂,真的不是件容易的事。

所以...
碩士畢業的講師不敢說弱
只能說教授真的滿強的...

星期六, 1月 07, 2012

tmux改 screen 256 color

改了tmux的設定後,發現顏色沒有改
查了一下,知道可用tput color來看
只有8色,不支援256
可在config裡給screen-256color
set -g default-terminal "screen-256color"

不過開vim時,卻發生Terminal entry not found in terminfo 'screen-256color' not known
所以讀預色的ansi
搞的vim都沒顏色了,而且很多vim指令不能下

又看了一下要用
export TERM=screen-256color

不改還好,一改連tmux也進不去
出現 missing or unsuitable terminal: screen-256color

想改回去 已經不知原本的值了
幸好另一台server也有灌,看了原來本的設定是
TERM=screen
改回來就進tmux了

結論...
還是沒顏色... 有改回來就偷笑了
不過應該centos 沒有screen-256color這東西
想辦法搞定,應該就能work了

References

星期四, 1月 05, 2012

ci取db錯誤

codeigniget在db出錯時,會自行印出錯誤訊息,如果要關掉有兩種方法
  • config/database.php設定
    $db['default']['db_debug'] = TRUE;
  • 程式裡設定
    $this->db->db_debug = false;  
關掉錯誤訊息,那如何取得錯誤訊息咧
$this->db->_error_message(); 
因為不管關不關錯誤訊息try-catch都抓不到
所以如要判斷中斷程式得利用affected row
ci論談已經有人寫好function,可配合暫時關掉錯誤訊息,中斷和印出錯誤訊息
function insert_quiet($table = ‘’, $set = NULL)
  {
      $oldv =$this->db_debug;
      $this->db_debug = false;     
      $this->insert($table, $set);
      $e = $this->_error_message();
      $aff = $this->affected_rows();
      $this->db_debug = $oldv;
      if($aff < 1) {
        return($e);
      } else {
        return(true);
      }
  }
Reference

星期四, 12月 22, 2011

轉:Setting up an SSL secured Webserver with CentOS

在apache裡建https就這麼簡單...
  1. Getting the required software
    yum install mod_ssl openssl
  2. Generate a self-signed certificate
    # Generate private key 
    openssl genrsa -out ca.key 1024 
    
    # Generate CSR 
    openssl req -new -key ca.key -out ca.csr
    
    # Generate Self Signed Key
    openssl x509 -req -days 365 -in ca.csr -signkey ca.key -out ca.crt
    
    # Copy the files to the correct locations
    cp ca.crt /etc/pki/tls/certs
    cp ca.key /etc/pki/tls/private/ca.key
    cp ca.csr /etc/pki/tls/private/ca.csr
  3. Setting up the virtual hosts
    #vim /etc/httpd/conf.d/ssl.conf
    -----------------------------
    #將<virtualhost>裡的內容修改為以下...
    <virtualhost *:443>
        SSLEngine on
        SSLCertificateFile /etc/pki/tls/certs/ca.crt
        SSLCertificateKeyFile /etc/pki/tls/private/ca.key
        <Directory /var/www/vhosts/yoursite.com/httpsdocs>
            AllowOverride All
        </Directory>
        DocumentRoot /var/www/vhosts/yoursite.com/httpsdocs
        ServerName yoursite.com
    </VirtualHost>
  4. Configuring the firewall
    yum install mod_ssl openssl

Reference

星期五, 12月 16, 2011

mysql存日期該用什麼data type

mysql存日期的data type有好幾種type,用int存秒數也是一種
一直很猶疑要用哪一種,想法是byte越少越好
所以整理了一下
TypeStorage(Bytes)Minimum Value(Signed/Unsigned)Maximum Value(Signed/Unsigned)
DATE3 bytes
TIME3 bytes
DATETIME8 bytes
TIMESTAMP4 bytes
YEAR1 bytes
INT4-21474836482147483647

所以我想... 利用INT存比較快吧...
created date就用int來存秒數,轉換日期就利用FROM_UNIXTIME(seconds)
last updated date就用timestamp來存,反正一樣大,而且會自動更新
References

星期四, 12月 15, 2011

active record使用memcached

一直用sql當memcached的key跑的順順的
不過最近在用ci在開發,發現用的active record不知抓什麼來當key
研究了一下,發現有last_query()可取出sql string
不過又看了一下發現是先execute後,才會有的query

而cache當然是要跑之前做,不然就沒有意義了
又serach了一下,發現有_compile_select()
差別當然在有執行跟沒執行,以下是片斷程式碼
有引用tomschlick寫好給ci用的memcached-library
 $key = $this->db->_compile_select();
$this->load->library('Memcached_library','','memcached');
$results = $this->memcached->get($key);

// If the key does not exist it could mean the key was never set or expired
if ($results) 
     echo 'hit';
else{
     echo 'miss';
     $results = $this->db->get()->row_array();
     $this->memcached->add($key, $results);
}
不過每個有用db的程式這樣寫太麻煩了
原本想改寫ci的db driver,看起來有點麻煩,先求有吧
所以先簡單的寫在helper裡,有空再來研究改寫driver
_compile_select());
        $ci = & get_instance();
        $ci->load->library('Memcached_library','','memcached');
        $results = $ci->memcached->get($key);

        // If the key does not exist it could mean the key was never set or expired
        if ($results) {

                $ci->fb->info('[memcache] hit', "info");
        }else{

                $ci->fb->warn('[memcache] miss', "memcached");
                $results = $db->get()->row_array();
                $ci->memcached->add($key, $results);
        }

        $db->_reset_select();  //clear sql query string
        return $results;
}
References Getting CodeIgniter Active Record's current SQL code

星期一, 12月 12, 2011

檢查遠端的檔案是否存在

這方法還不錯,只回傳header,不看body
function remoteFileExists($url) {
    $curl = curl_init($url);

    //don't fetch the actual page, you only want to check the connection is ok
    curl_setopt($curl, CURLOPT_NOBODY, true);

    //do request
    $result = curl_exec($curl);

    $ret = false;

    //if request did not fail
    if ($result !== false) {
        //if request was ok, check response code
        $statusCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);  

        if ($statusCode == 200) {
            $ret = true;   
        }
    }

    curl_close($curl);

    return $ret;
}

$exists = remoteFileExists('http://stackoverflow.com/favicon.ico');
if ($exists) {
    echo 'file exists';
} else {
    echo 'file does not exist';   
}
Reference

星期二, 12月 06, 2011

CodeIgniter - db active record常用指令

  • basic
    • 取得config中,名為group_one的db
      $DB1 = $this->load->database('group_one', TRUE); //給true才會產生實體給$DB1
      $this->db->select('title')->from('mytable')->where('id', $id)->limit(10, 20);
      
      p.s. 給true才會回傳個db object
    • 取sql string
      • last_query()
        執行的過程中,最後的一個sql query string
      • _compile_select()
        目前sql條件的sql query string,尚未實際執行
  • select
    $this->db->select('title, content, date'); //不下的話就是*
    $query = $this->db->get('mytable');
    foreach ($query->result() as $row)
    {
        echo $row->title;
    }
    
  • from、join
    $this->db->from('mytable');
    $this->db->select('*');
    $this->db->from('blogs');
    $this->db->join('comments', 'comments.id = blogs.id');
    
    $query = $this->db->get();
    
    // Produces:
    // SELECT * FROM blogs
    // JOIN comments ON comments.id = blogs.id
  • where 
    //法1.
    $query = $this->db->get_where('mytable', array('id' => $id), $limit, $offset);
    $this->db->or_where('id >', $id);  // Produces: WHERE name != 'Joe' OR id > 50
    
    //法2
    $this->db->select('title')->from('mytable')->where('id', $id);
    
  • insert
  • 新增欄位為now()的方法
    $data = array (
       'customer_id'=> $customer_id,
       'total' => $totalprice
      );
      $this->db->set('order_date', 'NOW()', FALSE);
      $this->db->insert('omc_orders', $data);


Reference

星期四, 12月 01, 2011

FirePHP

FireBug用久了,做php時,也很想要有這樣的好物
用過之後,覺得真的是超~~~~~~~~~~~~~~方便.......感動到想哭...
不過其他如ie要查時就... 無言了...

除了直接跟php搭外
還可以跟php的framework搭
[PHP] 好用 Debug PHP 工具 FirePHP for FireFox on CodeIgniter
這篇教學很完整,不再複製貼上了
  • CodeIgniter
  • Zend
    require_once('Zend/Log.php');
    require_once('Zend/Log/Writer/Firebug.php');
    
    $writer = new Zend_Log_Writer_Firebug();
    $logger = new Zend_Log($writer);
    
    $logger->info('info message');
    $logger->warn('warning message');
    $logger->err('error message');

讓config可以控制要不要輸出log

  • 配置config文件
    在application/config/目录下找到config.php,增加如下一行内容:
    $config['enable_firephp'] = true;
  • libraries/firephp.php文件
    $CI = & get_instance();
    if($CI->config->item('enable_firephp'))
       define('ENABLE_FIREPHP', true);
    else
       define('ENABLE_FIREPHP', false);
    
  • 每個class裡,使用firephp
    $this->fb->setEnabled(ENABLE_FIREPHP);
    $logger->info('info message');

References

星期五, 11月 25, 2011

書:Working Effectively With Legacy Code

一直對TDD很猶豫... 讀完後,決定好好的寫TDD了...
不想要再為了改個地方,而怕東怕西... 決定用這個可以放輕鬆的開發方法..

  • What is legacy code
    legacy code與non-legacy code的差別 - "test"
    接手的人不敢亂改,但如果有test機制,就能夠一步步修改維護
  • Test Coverings
    將程式佈滿測試,就不會害怕去改變他
  • Legacy Management Streategy
    1. Identify change points 
    2. Find an inflection point 
    3. Cover the inflection point a.
      1. Break external dependencies
        作者舉在testing時,重視測試結果,而常綁死gui的實作,造成testing不易
        作者寫了CustomerView的interface,當測試時,就可在不改變結構下,丟空的實作做測試,有mock的感覺
      2. Break internal dependencies
        在測試時是不必要的地方(如產生暫存等),就繼承該class,直接orverriding掉,不要做任何事即可,有stub的感覺
      3. Write tests 
    4. Make changes 
    5. Refactor the covered code.

待續...

星期五, 11月 18, 2011

SQL 常用查詢

  • 從url字串截取domain
    SELECT substring_index(substring_index(trim(leading "https://" from trim(leading http://" from trim(`URL`))), "/", 1), ":", 1) as domain FROM `uchome_app` WHERE 1 `redirect_uri`
    

星期四, 11月 10, 2011

linux切換多重視窗 - tmux

用pietty開發時,經常需要連到其他servers
懶得再開一個pietty,直接用ssh連線做完後,又得要exit掉,回到原本的環境
如果忘了做件事,又要再重連一次,指令密碼一直下,路徑也要一直切
環境一直切換覺得挺煩的,但再開一個pietty來做,切換視窗也是切到暈,常切到不知自己在哪...

今天同事也遇到以上問題,問我知不知道怎麼切換連線
說他有看過,但他不會...

這才一語驚醒夢中人... 對呀!!! 這東西應該有人有做出什麼神奇的工具
我怎麼都沒想過,即然同事都說有看過了,就jfgi了一下...
結果出現screen及tmux這好東西... 試用了一下,真是太感動了
個人覺得最方便的功能如下:
  • 同一個pietty連線,可以使用多個windows
    有點像是用本機登入linux,用F1,F2... 就可以切換多重視窗
    而且可以自定內部視窗的名字,這樣開再多也不怕
  • 視窗保留
    離開tmux後(tmux detach),再下tmux attach能夠保留上一次所有開啟的視窗連線狀態(session)。例如用vim開發常會開好幾個分頁,離開時要全關,下次再一一打開,有時只是離開一下座位,開著編輯畫面總覺得怪怪的,利用視窗保留就能不離開vim或當時的環境,等要用時再取回,這真是太酷了...
    而且能夠開多個session,保留不同的開發環境
  • 保留開發環境(多重seesions)
    個人是習慣每個專案即建相關的session,而該session下就是該專案相關的開發環境

    如此一來,切換專案時,所有的環境(該seesion下的windows)都保留著,在切換專案時,也不用花太多時間回想環境
Install tmux
  • install tmux
    # yum install tmux
    如果找不到套件,先加入epel的repo
    Install EPEL Repository On 32-bit CentOS Linux 5.5:
    # rpm -Uvh http://dl.fedoraproject.org/pub/epel/5/i386/epel-release-5-4.noarch.rpm
    
    Install EPEL Repository On 64-bit CentOS Linux 5.5:
    # rpm -Uvh http://dl.fedoraproject.org/pub/epel/5/x86_64/epel-release-5-4.noarch.rpm
    Reference: Install EPEL Repo CentOS RHEL
  • 啟動tmux
    # tmux
    畫面如下圖所示

    重點在1.session 及2.window
    把每一個session看成獨立一個連線
    而每個session都可如上圖有多個windows
    因此seesion 1 為project A,再對project A開啟多個windows
    而session 2 即為project B, 再對project B開啟多個windows
  • tmux指令(啟動tmux環境)
    • 取回視窗
      $ tmux attach 
      $ tmux attach -t session-id  //指定特定seesion
    • 列出所有sessions
      $tmux ls
    • 更改session名
      $ tmux rename-session -t session1 session2  //把session1改成session2
      或者直接下function key + $

  • tmux視窗指令 ()
    • Ctrl-b c Create new window
    • Ctrl-b d Detach current client
    • Ctrl-b l Move to previously selected window
    • Ctrl-b n Move to the next window
    • Ctrl-b p Move to the previous window
    • Ctrl-b & Kill the current window
    • Ctrl-b $ Rename the current session
    • Ctrl-b , Rename the current window
    • Ctrl-b % Split the current window into two panes
    • Ctrl-b ? List all keybindings
    • Ctrl-b s 切換session,如下圖,列出所有sessions,再選擇要切換的
  • 分割 / 切割視窗 (切出來的叫pane)
    • Ctrl-b q Show pane numbers
    • Ctrl-b alt按著,再按上下左右, 可以調整視窗大小
    • Ctrl-b % 直切
    • Ctrl-b :"split-window" 橫切
    • Ctrl-b Ctrl-o 調換 切割視窗 的 位置
    • Ctrl-b o Switch to the next pane
    • Ctrl-b 上下左右 跳到上下左右的分割視窗
    • Ctrl-b ! 將目前的pane抽成window
    • Ctrl-b x 移除目前的pane
  •  自定key組合
    切割視窗還是先設好key,不然還真不好用,以下是個人參考網路上的設定
    把預設的Ctrl-b改為Ctrl-a,手比較不會抽筋...
    # vi ~/.tmux.conf
    # General configuration.
    # $ tmux show-options -g
    set -g base-index 1
    set -g display-time 5000
    set -g repeat-time 1000
    set -g status-keys vi
    set -g status-utf8 on
    set -g status-bg black
    set -g status-fg white
    set -g status-justify left
    set -g status-interval 1
    set -g status-left-length 15
    set -g status-right-length 55
    set -g status-left "#[fg=white,bright] #[fg=yellow,bright]#S #[default] |"      # session-name
    set -g status-right "#[fg=red,bright][ #[fg=cyan]#(git branch --no-color | sed -e '/^[^*]/d' -e 's/* //') #[fg=red]]#[default] #[fg=yellow,bright] %Y-%m-%d #[fg=green]%H:%M:%S #[default]#[fg=magenta,bright]#[default]"
    
    # window setting
    setw -g utf8 on
    setw -g window-status-format " [#I] #W "
    setw -g window-status-current-format " [#I] #W "
    setw -g window-status-current-fg black
    setw -g window-status-current-bg green
    setw -g window-status-current-attr default
    set-option -g allow-rename off  #禁止rename,在tmux v1.8 在換路徑時,會一直rename window
    
    # using function keyCtrl+A
    unbind C-b
    set -g prefix ^A
    bind a send-prefix
    
    # split window
    unbind %
    unbind '"'
    bind v split-window -h
    bind | split-window -h
    bind h split-window -v
    bind - split-window -v
    
    
    設好後,重啟config
    tmux source-file ~/.tmux.conf
    git branch資訊不曉得為何,偶爾會有出現,後來發現要在git folder裡開tmux才會有,不曉得為什麼

星期二, 10月 18, 2011

php轉碼問題

利用iconv轉碼會有轉不回來的問題
可用mbstring來轉碼 就不會有問題了
當然apache要先安裝mbstring
  • 安裝
    yum install php-mbstring
  • big5轉utf8
    mb_convert_encoding($msg, "UTF-8", "BIG-5");
  • 配合自動偵測,統一轉utf8
    要注意要自己加上可能的碼,不然可能會找不到
    $encoding = mb_detect_encoding($this->content, "UTF-8,BIG-5,GB2312, ASCII, ISO-8859-1");
    $msg = mb_convert_encoding($msg, "UTF-8", $encoding);
    

星期四, 10月 13, 2011

php處理url函式

  • 組url字串
    利用http_build_query
    <?php
    $data = array('foo'=>'bar',
                  'baz'=>'boom',
                  'cow'=>'milk',
                  'php'=>'hypertext processor');
    
    echo http_build_query($data) . "\n";
    echo http_build_query($data, '', '&');
    
    //前置詞
    $data = array('foo', 'bar', 'baz', 'boom', 'cow' => 'milk', 'php' =>'hypertext processor');
    echo http_build_query($data, 'myvar_');  
    --
    foo=bar&baz=boom&cow=milk&php=hypertext+processor
    foo=bar&baz=boom&cow=milk&php=hypertext+processor
    myvar_0=foo&myvar_1=bar&myvar_2=baz&myvar_3=boom&cow=milk&php=hypertext+processor
    
  • 解url字串
    利用parse_str
    <?php
    $str = "first=value&arr[]=foo+bar&arr[]=baz";
    parse_str($str);
    echo $first;  // value
    echo $arr[0]; // foo bar
    echo $arr[1]; // baz
    
    parse_str($str, $output);
    echo $output['first'];  // value
    echo $output['arr'][0]; // foo bar
    echo $output['arr'][1]; // baz

星期一, 10月 10, 2011

git log

  • 一般
    • 查看commit歷程
      # git log    
      # git log --stat  // 更動檔案和異動的行數
      # git log <file> //指定檔案
      
      # git diff --name-only // 最近一次的commit有哪些檔案被修改
  • 排版
    • 圖形化commit歷程
      看了沒fu嗎… 用文字圖形化看吧
      git log --graph            //文字圖示版本
      
    • 異動的內容
      即為git diff的內容,太多不寫了,看reference裡有
      $ git log -p
      
    • 一列一版本
      查看版本一目瞭然...... 前提是commit的message要跟範例一樣清楚的話....
      git log --pretty=oneline
      --
      a6b444f570558a5f31ab508dc2a24dc34773825f dammit, this is the second time this has reverted
      49d77f72783e4e9f12d1bbcacc45e7a15c800240 modified index to create refs/heads if it is not 
      9764edd90cf9a423c9698a2f1e814f16f0111238 Add diff-lcs dependency
      e1ba1e3ca83d53a2f16b39c453fad33380f8d1cc Add dependency for Open4
      0f87b4d9020fff756c18323106b3fd4e2f422135 merged recent changes: * accepts relative alt pat
      f0ce7d5979dfb0f415799d086e14a8d2f9653300 updated the Manifest file
    • 特定資料夾
      $ git log fs/           # commits that modify any file under fs/
      
  • 搜尋及過濾
    • 誰異動的,何時,哪個commit
      # git blame filename
      commit    author when
      --------  ---- -------------------------
      394d743f (fish 2013-10-22 17:22:34 +0800  8)     public function getSource()
      394d743f (fish 2013-10-22 17:22:34 +0800  9)     {
      394d743f (fish 2013-10-22 17:22:34 +0800 10)         return "";
      394d743f (fish 2013-10-22 17:22:34 +0800 11)     }
    • 用文字找版本
      $ git log -S'foo()'     # commits that add or remove any file data matching the string 'foo()'
      
    • 最近二周
      $ git log --since="2 weeks ago" # commits from the last 2 weeks
      
      其他還有--after, --until, and --before
    • 不要顯示merge的版本
      $ git log --no-merges
      
其他
$ git log v2.5..        # commits since (not reachable from) v2.5
$ git log test..master  # commits reachable from master but not test
$ git log master..test  # commits reachable from test but not master
$ git log master...test # commits reachable from either test or
                        #    master, but not both
References

星期日, 10月 09, 2011

git stash 暫存

當要checkout b branch時,當下a branch的資料如果未commit 就會連當被帶過去b branch
//假設有a, b branches且都有file1內容為1-1
# echo '1-2' > file1
# git checkout b
M       file1
Switched to branch 'b'
# cat file1
1-2
  • 丟入暫存
    但如果未完成又不想commit時 可利用git stash
    # echo '1-2' > file1
    # git stash 
    # cat file1
    1-1     <-- 被reset, 這時就可以切換
  • 取出
    # git stash pop
    # cat file1
    1-2     <--再被改為stash的內容
    git stash可重覆使用,用法如stack 多下個幾次就堆疊起來,取法一樣pop囉
更多指令
  • git stash list (列出stash的清單)
    # git stash list 
    stash@{0}: WIP ...   //第1個暫存 
    stash@{1}: WIP ...   //第2個暫存
  • git stash pop (取出暫存)
       # git stash pop     // pop out 最後進入的stash
       # git stash apply  // 跟pop一樣. 但不會清掉stash
       # git stash apply stash@{1} //取出陣列1的stash
       # git stash drop stash@{1} //刪掉,不套用
       # git stash clear   // 不用解釋吧...

git還原 - revert, reset, checkout


  • 回復至最近一次commit(所有檔案)
    $ git reset --hard HEAD
  • 還原修改過的單一檔案
    有以下不同的方法
    //以下從staging取出
    $ git checkout hello.txt    //1
    $ git checkout -- hello.txt //2
    $ git checkout -f hello.txt //3
    
    //以下從HEAD最新版取出
    $ git checkout HEAD hello.txt //4
    

    ex. 假設HEAD的hello.txt 如果為hello
    $ echo 'hi' > hello.txt  //這時三者皆相同
    $ git add . //放到staging,這時1,2,3取到staging(hi),4取到hello
    
    感謝Charlie Lee的訂正,本以為-f也會取到hello
    話說不知道當初為何要看-f參數,這參數是用在"強制換"branch時,不理會當下修改的檔案,跟"還原"檔案沒什麼關係 XD
    可能當初還不太懂,看著人家寫就照抄
  • Staging(git add)後,要退回unstage
    $ git reset HEAD file
  • 回復特定版本
    雖說是回復,但其實是將指定的版本新增為最新的commit
    $ git revert commit_name
    不過通常回復到舊版本,是要繼續往下開發
    所以勢必得再一次commit
    所以如果只是要回復且不要commit 可以加 -n or --no-commit
    $ git revert -n commit_name
    如果要修改的話 得commit或放棄,否則沒辦法回復
    • fatal: Commit 137ea95 is a merge but no -m option was given.
      因為該commit為merge(兩個branches合併,所以得指定要回復的branch (-m or --mainline option) 搭配數字 1 or 2 指定第幾個commit
  • 從commit裡,指定checkout檔案
    格式:git checkout SHA /file/to/path
    $ git checkout 35216 controller/ui.php
  • 從branch裡,指定checkout檔案
    格式:git checkout <branch_name> <paths> #會在相同的資料夾找
    格式:git checkout <branch_name> -- <paths>
    $ git checkout branch_b test.php  //從branch_b取出test.php
  • 改變最後一次的 Commit的訊息
    git commit --amend (改git log的內容)
References

星期六, 10月 08, 2011

git 常見問題

  1. 程式改爛了,怎麼還原
    • 還原單一檔案
      $ git checkout hello.txt
      
    • 整個還原到最後commit版本
      $ git reset --hard HEAD
      
      只會還原上一版本有加入track的檔,還沒加入的新檔不會變更
  2. 回復特定版本
    雖說是回覆,但其實是將指定的版本新增為最新的commit
    $ git revert commit_name
  3. checkout某版本或分支的特定檔
    git checkout SHA-1 --  FILE_PATH
    git checkout BRANCH_NAME -- FILE_PATH
  4. 衝突了!怎麼解
    打開confilct的檔案
    <<<<<<<<     HEAD
    目前的版本
    ---------------------
    上一個版本
    >>>>>>>>>> 版本碼
    只要看哪個正確,改正就可以了
    
  5. 要切換branch,還不想commit
    1. 先丟到暫存區
      $ git stash
      
      這時會回到最後commit的結果
      不過未經commit的新檔不會改變,也不會被刪除
    2. 取回暫存
      $ git stash pop
      
  6. 圖示commit版本
    • $ git log --graph
    • commit後,想修改message
      $ git commit --amend
      
  7. 新增remote
    • 查目前所有的remote點
      $ git remote -v
    • 新增remote點
      $ git remote add remote別名 repository的url位置
    • 移除remote點
      $ git remote rm remote名

  8. push回origin權限不足
    通常創repository跟clone下來的帳號不同
    造成要push回去時,會有權限不足的問題
    可利用group的解決這問題
    sudo chmod -R g+ws *
    sudo chgrp -R YOUR_GROUP *
    
    git config core.sharedRepository true