聚會時間公告: 因應COSCUP 2011, Kalug 8月份休會一次

五月 21, 2013

小惡魔AppleBOY
AppleBOY
小惡魔 - 電腦技術 - 工作筆記 - AppleBOY is about »

tag cloud

» Flickr 改版及收費方式改變

癮科技看到 Flickr大改版,收費方式也有異動Flickr 整個介面大改版,這個就算了,連收費方式也大改,本來 Pro 的用戶,以後不再有 Unlimited storage 的優惠了,等到 pro 帳戶到期,系統會將帳戶轉為 Free 機制,雖然容量有到 1TB 的空間,其實也用不太完,但是整個感覺非常不好。

Flickr 目前只有三種帳戶機制,Free, Ad Free, Doublr,三個差異沒有很多,Free 的帳戶幾乎同等於之前的 pro 帳戶,只是有容量限制上限 1TB,再來就是有廣告,接著 Ad Free 一年49美金,差別就是沒有廣告,最後 Doublr 只是容量變成 2TB,也沒有廣告,但是價錢 ….. 每年 499.9 美金 .. 這價位,真的還蠻高的,我想之後也不打算續約了。更多 FQA 可以參考 Free Accounts, Upgrading and Gifts

五月 19, 2013

小惡魔AppleBOY
AppleBOY
小惡魔 - 電腦技術 - 工作筆記 - AppleBOY is about »

tag cloud

» 2013 Javascript Conference: 你不可不知的前端開發工具

JSDC 2013JSDC 2013

台灣第 2 屆 JavaScript 研討會在 5/18, 5/19 登場,今年報到率到 95% 了,我也給了一場 Talk,關於前端工具介紹,包含 CoffeeScript, Compass, Livereload, Bower Package Manager .. 等,最後介紹主軸 Grunt.js 來整合這些工具。

最後附上 Github 專案,歡迎大家 fork。

五月 15, 2013

小惡魔AppleBOY
AppleBOY
小惡魔 - 電腦技術 - 工作筆記 - AppleBOY is about »

tag cloud

» IE 6 瀏覽器用戶全球分佈

IE_worldIE_world

此資料來自 The Internet Explorer 6 Countdown,大家注意上面圖示,沒想到台灣高居第二名,佔了 3.5% 僅次於大陸的 24%,大陸不感到意外,但是台灣的比例還真是高,難怪一堆程式開發者,抱怨連連 XD,這是統計到 2013 年 04 月,在這邊紀錄一下,等到明年這個時候再來看看此統計圖。

五月 9, 2013

小惡魔AppleBOY
AppleBOY
小惡魔 - 電腦技術 - 工作筆記 - AppleBOY is about »

tag cloud

» Backbone Routing pushState in IE

backbonebackbone

Backbone.js 幫忙處理掉所有瀏覽器 Html5 History pushState 功能,除了 IE 9 以下(含 IE 9)不支援 history.pushState()history.replaceState(),其他 Browser 幾乎都支援了,在 Backbone.js 如何處理 URL 變化呢?以往透過 handle URL hash 來決定網頁要處理哪些資料,這也是 Backbone 預設的處理方式,範例如下

URL:

http://xxx/#!/user/list
http://xxx/#!/user/add

Backbone.Router.extend({
  routes: {
    "!/user/:action": "user"
  },
  initialize: function() {

  },
  user: function(action, id) {
   
  }
});
Backbone.history.start();

上面方法是通解,在各種瀏覽器包含 IE 都適用,那如果是使用 history.pushState 請改成底下:

URL:

http://xxx/user/list
http://xxx/user/add

Backbone.Router.extend({
  routes: {
    "/user/:action": "user"
  },
  initialize: function() {

  },
  user: function(action, id) {
   
  }
})
Backbone.history.start({pushState: true, root: '/'});

此作法在支援 html pushState 時候是可以按照您定義的 url 運作,但是在 IE 9 版本,網址就會被改成

URL:

http://xxx/#/user/list
http://xxx/#/user/add

一樣會被加上 hash 值,該如何解決此問題呢,請把 Backbone.history.start 改成

Backbone.history.start({pushState: true, hashChange: false, root: '/'});

設定 hashChange property 為 false,讓 IE 9 不要使用 # 來取代網址,這樣就沒問題了。

五月 3, 2013

小惡魔AppleBOY
AppleBOY
小惡魔 - 電腦技術 - 工作筆記 - AppleBOY is about »

tag cloud

» 測試 Web Responsive Design Tool

responsive-website-design-tipsresponsive-website-design-tips

Web CSS Programer 在撰寫 Responsive CSS Style 時,手邊一定會有一堆 Device,來測試當畫面小於 480 px 或大於 768 px 時,呈現的版面是否有亂掉,公司也花費許多成本來測試,現在不需要這樣了,我們可以透過線上 Tool 或者是 Plugin 來測試 Responsive Web Page,首先來介紹 Viewport resizer,此工具用法很簡單,進入官網後,將官網 Javascript 連結加入到我的最愛或 bookmarks,之後打開您的測試網站,再點選該 bookmark,你會發現網站上面多了一條 tool bar,可以自訂或調整 view size,預設也給了平板手機等多種畫面調整,讓您測試 Media Queries 是否有錯誤。

另外一套 Tool 比較強大,那就是 Google Extension: Responsive Inspector (beta) released!,不過就是限制在 Google Chrome 瀏覽器才可以安裝,此擴充工具,還可以直接對應到 CSS Media Queries 位置,以及將自訂大小畫面存成圖檔並且上傳到 Server。底下是介紹影片

四月 30, 2013

小惡魔AppleBOY
AppleBOY
小惡魔 - 電腦技術 - 工作筆記 - AppleBOY is about »

tag cloud

» Install Nginx + spdy module on Ubuntu or Debian

nginx-logonginx-logo

上一篇提到 nginx 1.4.0 釋出並支援 SPDY,教學環境是 CentOS,這次在 Ubuntu 環境編譯遇到

/usr/bin/ld: cannot find -lperl

找不到 perl library,解法可以透過 aptitude 安裝 libperl5.14,安裝好後,到 /usr/lib 底下找到 libperl.so.5.14.2,由於檔案命名關係,請用 ln 將檔案 link 成 libperl.so

$ ln -s libperl.so.5.14.2 libperl.so

接著可以正確編譯了,底下安裝相關套件

$ aptitude -y install libpcre3-dev libgd-dev libgd2-xpm-dev libgeoip-dev

四月 29, 2013
» 從高鐵延誤看被輕視的專業

今天看到蘋果日報以大篇幅報導《幾分鐘可解決的故障 高鐵竟停擺4小時》(註1)這則新聞,讓筆者深深感受到台灣人如何作賤專業。 撰寫過軟體或是維護過資訊系統的人應該很清楚,一個系統出了問題,第一件事情絕對不是,也不該是重開機。有問題出現,代表一定是有程式在特定的系統環境下出錯了。要找出問題,除了從程式碼來尋找以外,還要從系統環境來找。這兩個要素湊起來才能找到問題。但重開機就直接把系統環境還原,因此引發問題產生的原因消滅了,就很難再次找到原因了。重開機看起來是短時間解決了問題,但是問題並沒有真正被解決。一旦滿足了問題發生的條件,這個問題還是會再度出現。所以,通常面對這種狀況,通常會立刻停止運作,在系統中尋找問題。若一時三刻找不到問題,也會立刻傾印(dump)當前系統,確定所有除錯相關數據都有紀錄後,先重開機或重置讓系統恢復運作,減少對線上服務的衝擊,

» 華人文化傳統的惡性循環

“Common sense is the collection of prejudices acquired by age eighteen.” -- Albert Einstein 「常識就是人到十八歲為止所累積的各種偏見。」 筆者來到中國(中華人民共和國,本文簡稱中國。)工作,距今也約兩三年左右。初來到中國的時候,心中想到的是在台灣時印象中的中國人:大聲喧譁,不守規矩,沒有公德心,短視近利。在中國和中國朋友相處過一陣子以後,筆者也常在中國人(中華人民共和國國民,本文簡稱中國人。)的口中聽到他們印象中的台灣人(中華民國國民,本文稱為台灣人。)。他們口中的台灣人,有禮貌,比較不會吵架,守規矩;但同時也貪小便宜。筆者常常思考,台灣人和中國人究竟差在哪裡?許多中國朋友認為文化大革命把中國(指文化上的中國。)的傳統給革除掉了。保有文化傳統的台灣人因而更為守規矩,更有公德心。

四月 28, 2013

小惡魔AppleBOY
AppleBOY
小惡魔 - 電腦技術 - 工作筆記 - AppleBOY is about »

tag cloud

» nginx 1.4.0 釋出並支援 SPDY

nginx-logonginx-logo

很高興看到 Nginx Release 1.4.0 版本,此新版本開始支援 SPDY module,對於 SPDY 還不熟悉了解的,可以參考今年 2013 WebConf 講師 ihower 介紹的 A brief introduction to SPDY – 邁向 HTTP/2.0,要提升整個 Web Performance,可以將 SPDY 導入,對於使用 Apache 使用者,請參考 mod_spdy,如果是 Nginx 用戶,在 1.3.x 版本,可以直接用官方 patch,升級到 1.4.x 就不需要 patch 了,但 OS 是 UbuntuCentOS 系列是需要自行編譯,這次會筆記在 CentOS 下將 spdy 編譯進系統。

安裝方式

先看 Ngix 是否有支援 spdy,直接下 nginx -V 觀看

nginx version: nginx/1.1.19
TLS SNI support enabled
configure arguments: –prefix=/etc/nginx –conf-path=/etc/nginx/nginx.conf –erth=/var/lib/nginx/body –http-fastcgi-temp-path=/var/lib/nginx/fastcgi –http-lb/nginx/proxy –http-scgi-temp-path=/var/lib/nginx/scgi –http-uwsgi-temp-path==/var/run/nginx.pid –with-debug –with-http_addition_module –with-http_dav_moith-http_image_filter_module –with-http_realip_module –with-http_stub_status__xslt_module –with-ipv6 –with-sha1=/usr/include/openssl –with-md5=/usr/includ/buildd/nginx-1.1.19/debian/modules/nginx-auth-pam –add-module=/build/buildd/d/nginx-1.1.19/debian/modules/nginx-upstream-fair –add-module=/build/buildd/ng


看到上述結果,沒有發現 http_spdy_module 模組,代表並無編譯進去,底下安裝過程,是基於 CentOS 6.4 Release 環境。安裝前請先下載 Nginx 1.4.0openssl 1.0.1e 版本。

# generate makefile
cd /tmp/nginx-1.4.0 && ./configure \
    --prefix=/usr/share/nginx \
    --sbin-path=/usr/sbin/nginx \
    --conf-path=/etc/nginx/nginx.conf \
    --error-log-path=/var/log/nginx/error.log \
    --http-log-path=/var/log/nginx/access.log \
    --pid-path=/var/run/nginx.pid \
    --user=nginx \
    --group=nginx \
    --with-http_realip_module \
    --with-http_addition_module \
    --with-http_xslt_module \
    --with-http_image_filter_module \
    --with-http_geoip_module \
    --with-http_sub_module \
    --with-http_dav_module \
    --with-http_flv_module \
    --with-http_mp4_module \
    --with-http_gzip_static_module \
    --with-http_random_index_module \
    --with-http_secure_link_module \
    --with-http_degradation_module \
    --with-http_stub_status_module \
    --with-http_perl_module \
    --with-mail \
    --with-mail_ssl_module \
    --with-http_ssl_module \
    --with-http_spdy_module \
    --with-openssl=/tmp/openssl-1.0.1e
cd /tmp/nginx-1.4.0 && make && make install

比較需要注意的事,假如系統已經安裝好 nginx 版本,預設執行程式會在 /usr/sbin/nginx,所以編譯時,請務必指定此路徑蓋掉原有的執行檔,這樣系統還是可以透過 init.d 啟動或關閉 nginx。

啟動 spdy 模組

為了將 https 及 spdy 同時 listen 443 port,OpenSSL 務必支援 Next Protocol Negotiation,所以版本要 1.0.1 以上。在 nginx.conf 設定如下

server {
    listen 443 ssl spdy;

    ssl_certificate server.crt;
    ssl_certificate_key server.key;
    ...
}

偵測伺服器是否支援 spdy

經過安裝完成 Nginx with spdy module,要確定伺服器有無支援,可以透過 Firefox addon 或 Chrome extension,底下是 SPDY indicator 下載連結

* Firefox SPDY indicator
* Chrome SPDY indicator

要如何測試呢?打開 Chrome 瀏覽器,輸入 Google 網址,你會發現網址列多一個綠色勾勾,那就代表伺服器有支援 SPDY Module。

四月 25, 2013

小惡魔AppleBOY
AppleBOY
小惡魔 - 電腦技術 - 工作筆記 - AppleBOY is about »

tag cloud

» Fabric 管理多台 Linux 機器的 command tool

python-logo-master-v3-TMpython-logo-master-v3-TM

相信 Administrator 管理過兩台以上的 Linux Server 都一定會找 tool 讓多台機器同時執行指令,這也應用在 Deploy 任何 application 到多台機器或者是同時更新系統套件…等,網路上有蠻多套 command line tool 像是 capistranoFabricpsshdsh…等都,本篇會以 Python 所推的 Fabric 來做介紹。另外 Ruby 所寫的 capistrano tool 也是不錯的選擇,這兩套其實大同小異,可以將 Deploy 的邏輯寫成單一 file 再透過 task 定義來決定執行的工作。當然你也可以透過此 tool 來管理 local 端動作,但是這有點多此一舉,因為基本的 Shell 就可以完成了,如果熟悉 Python 則選 fabric,如果喜歡寫 Ruby 則可以試試看 capistrano。

安裝方式(Installation)

如果是 CentOS 系列可以透過 yum 套件管理,UbuntuDebian 則是透過 aptitude 方式安裝。

Yum

# install python pip tool and fabric command
yum -y install python-pip
pip-python install fabric

APT

# install python easy_install
aptitude -y install python-pip
# install fabric command
pip install fabric

安裝 capistrano 可以透過 Ruby gem。

$ gem install capistrano

基本介紹

Fabric 可以透過 command line 或者是讀取 fabfile.py 檔案方式來執行,fabfile.py 務必放在執行 fab command 的目錄底下,也就是的命令列所在位置 。假設目前在 /home/appleboy 目錄下,就必須將 fabfile.py 存放在 /home/appleboy。

簡易設定 /home/appleboy/fabfile.py,內容

def hello():
    print("Hello world!")

該目錄底下執行

$ fab hello
Hello world!

Done.

如果不透過 fabfile.py 檔案的話,你直接打 fab 會得到 Couldn’t find any fabfiles!,看到這訊息沒關係,一樣可以用指令方式來達成上面的結果。學習 fabric 前,有一個很必要的條件,就是必需熟悉 Linux command 及 Shell script 用法,個人推薦鳥哥的網站,把基礎文件都看過後,就沒有任何 Linux 系統可以難倒你。如何用 fab command 直接得到上述的結果呢?

$ fab -p xxxx -H localhost -- 'echo "Hello world!";'

上述指令會產生下面結果

[localhost] Executing task '<remainder>'
[localhost] run: echo "Hello world!";
[localhost] out: Hello world!
[localhost] out:
Done.
Disconnecting from localhost... done.

執行 fab 就像是透過 ssh 登入機器,需要帳號及密碼,執行當下就必須提供使用者帳號及密碼,如果沒給參數,預設就是執行該 command 的使用者,-p 則是給密碼,這樣就不會詢問密碼了,-H 是指定要對哪個 host 執行該命令,也許同時 3 台機器,-H 請改寫成 -H web1,web2,web3。要換其他使用者直接加上 -u 參數

$ fab -u deploy -p xxxx -H localhost -- 'echo "Hello world!";'

接下來聊聊該如何寫 fabfile.py,fab 有分 local 端或 Host 端執行,如果只用在 local 端就跟寫 Shell script 沒啥不同,fabric 提供了 local function 執行 local command。對於專案而言,你可以建立 fabfile.py 設定檔,裡面寫入

from fabric.api import local

def prepare_deploy():
    local("git add -p && git commit")
    local("git push")

執行 fab prepare_deploy 會將專案已修改的 commit 到 server,當然你也可以拆開來執行

from fabric.api import local

def clone():
    local("git clone git@github.com:appleboy/minify-tool.git")

def commit():
    local("git add -p && git commit")

def push():
    local("git push")

def prepare_deploy():
    commit()
    push()

大家可以依照專案需求來定義工作項目,好讓團隊所有的成員都可以使用。

錯誤處理

看到上面例子,可以知道透過 fab clone 來初始化專案,執行後,發現多了 minify-tool 目錄,但是再執行同樣指令一次呢?會發現出現底下錯誤訊息

[localhost] local: git clone git@github.com:appleboy/minify-tool.git
fatal: destination path 'minify-tool' already exists and is not an empty directory.

Fatal error: local() encountered an error (return code 128) while executing 'git clone git@github.com:appleboy/minify-tool.git'

Aborting.

程式就停止了,但是如果底下有必須執行的工作,該怎麼辦,必須要 import with_statement 模組,將程式碼改成底下

from __future__ import with_statement
from fabric.api import local, settings, abort
from fabric.contrib.console import confirm

def clone():
    with settings(warn_only=True):
        result = local("git clone git@github.com:appleboy/minify-tool.git")
    if result.failed and not confirm("Tests failed. Continue anyway?"):
        abort("Aborting at user request.")

會發現畫面還是會出現錯誤訊息,最後跳出 confirm 視窗鍵入 Y,結果會得到 Done!,鍵入 N 則得到 Aborting 訊息。

[localhost] local: git clone git@github.com:appleboy/minify-tool.git
fatal: destination path 'minify-tool' already exists and is not an empty directory.

Warning: local() encountered an error (return code 128) while executing 'git clone git@github.com:appleboy/minify-tool.git'

Tests failed. Continue anyway? [Y/n] y

Done.

接著來定義 deploy 工作內容

def deploy():
    code_dir = 'minify-tool'
    with cd(code_dir):
        run("git pull")

上面多了二個函式,就是 cd 和 run,cd 很直覺,就跟 Linux command 一樣,run 跟 local 不同的地方就是 run 是用來管理遠端機器。

定義 Host

最前面有提到可以用 -H 方式定義,那也可以直些寫在 fabfile.py 設定檔

env.hosts = ['127.0.0.1']
env.hosts = ['localhost']
env.hosts = ['web1']

上面寫法都正確,host name 可以直接在 /etc/hosts 檔案內定義,將程式碼改為底下

env.hosts = ['my_server']

def deploy():
    code_dir = 'minify-tool'
    with settings(warn_only=True):
        if run("test -d %s" % code_dir).failed:
            run("git clone git@github.com:appleboy/minify-tool.git %s" % code_dir)
    with cd(code_dir):
        run("git pull")

如果沒有定義 env.hosts,你也可以執行

$ fab -H web1 deploy

這次先介紹到這裡,或許之後有機會來介紹進階用法,當然可以先參考看看 fabric document

四月 13, 2013

小惡魔AppleBOY
AppleBOY
小惡魔 - 電腦技術 - 工作筆記 - AppleBOY is about »

tag cloud

» Linode 最後優惠 升級記憶體

Linode VPSLinode VPS

Linode 最後的優惠出來了,之前寫了一篇 Linode VPS 升級網路及硬體設備,回顧 Linode 今年的優惠大清倉,第一次專注在網路效能及流量頻寬升級,第二次則著重在硬體升級,也就是升級 CPU,那這次要升級什麼呢,難不成 Linode 有聽到上一篇最後我講到的心聲,就是記憶體升級啦,Linode 大手筆將全部 Plan 的記憶體都 double,底下這張圖就是升級過後的價目表。

Linode - Xen VPS Hosting 2013-04-13 11-04-36Linode - Xen VPS Hosting 2013-04-13 11-04-36

最便宜的方案就有 1G 了 Ram,每個月 2TB 流量,8 CPU,一個月才 20美金,真的是蠻便宜的,現在問我 AWS 跟 Linode 選哪個,我會大力推薦 Lindoe 了,不過升級此 Ram,每個方案會多 0.05 美金,所以最低消費從每個月 19.95 USD 會變成 20 USD,不過還是很值得啦。現在可以馬上登入 Linode 後台按下升級按鈕,系統會自動升級,並且重新開機。

目前可以升級的區域如下

Fremont, CA: TBD
Dallas, TX: Upgrades are available
Atlanta, GA: Upgrades are available
Newark, NJ: Upgrades are available
London, UK: Upgrades are available
Tokyo, JP: Upgrades are available

日本那邊已經升級完成,但是我的 Linode 似乎沒看到升級按鈕,寫個 Ticket 詢問看看。Enjoy it。

四月 12, 2013

小惡魔AppleBOY
AppleBOY
小惡魔 - 電腦技術 - 工作筆記 - AppleBOY is about »

tag cloud

» [小技巧] JavaScript Cross Browser Best Practices

ie-logo-smallie-logo-small

先前寫了一篇 modern.IE 的使用方式及介紹,今天在 Facebook 上看到 Eric Shangkuan 說已經有了中文介面,如果你的瀏覽器是中文版,應該就可以直接看到中文介面了,裡面有篇文章非常重要,寫 Web 的工程師都必須注意,那就是 Cross Browser Best Practices,這篇文章教您如何撰寫相容於舊版 IE 瀏覽器的一些小技巧,這些技巧也不只用在 IE 上,更是教您在實做 CSS,JavaScript 的注意事項。我們來看看 Javascript 的小技巧。

不要再使用 navigator.userAgent

為了知道使用者 Browser 資訊,之前有寫篇 jQuery 偵測瀏覽器版本, 作業系統(OS detection),內容使用 navigator.userAgent 來取得使用者瀏覽器及裝置資訊,開發者為了 IE 各版本的相容,所以透過此方式來知道 IE 各版本,進而在 JS 做處理,但是有時候並不是這麼準確,因為目前市面上裝置實在是太多種了,手機,平板,電視一堆等等,為了支援各種裝置,請不要再用 navigator.userAgent 來判斷了,現在取而代之的就是用 Modernizr,用來偵測您的 Browser 有無任何您所想要的功能,像是 Html5 的 Canvas,利用 Modernizr 來判斷是否支援,這時候各種裝置就不會因為 JS 沒有判斷到而產生錯誤 ,尤其是在電視介面或 Android 平板,踩到很多雷阿。詳細資訊可以參考此連結

簡單來說 Canvas 在 IE9 才有支援,所以針對 IE 部份,我們使用 navigator.userAgent 來判斷

<script type="text/javascript">
    function getInternetExplorerVersion()
    // Returns the version of Internet Explorer or a -1 for other browsers.
    {
        var rv = -1;
        if(navigator.appName == 'Microsoft Internet Explorer')
        {
            var ua = navigator.userAgent;
            varre    = newRegExp("MSIE ([0-9]{1,}[\.0-9]{0,})");
            if(re.exec(ua) != null)
            rv = parseFloat( RegExp.$1 );
        }
        return rv;
    }
    function onLoad()
    {
        var version = GetInternetExplorerVersion()
        if (version < 9 && version > -1)
        {
            // Code to run in Internet Explorer 9 or earlier.
        }
    }
</script>

但是如果遇到 Safari, Chrome, Android, IPad, IPhone 版本呢,也很好解決,就是一直些判斷式,那為什麼不換個角度去想,直接判斷有無 Cnavas 功能即可,透過 Modernizr 套件可以簡單做到。另外 jQuery 在 1.9 版也直接捨棄了 jQuery.browser API 功能,取而代之的也是推薦 Modernizr

if (Modernizr.canvas) {
  console.info('Your browser support canvas');
}

在 document ready 內不要執行大量 script

現在大部分的網站缺少不了的就是 jQuery,jQuery 提供了 $(document).ready() 在 html load 完成後可以快速執行 JavaScript,在大多的狀況下都可以正確執行的,但是如果在 $(document).ready() 寫入大量及複雜的 Script,只會讓瀏覽器呆滯而不能使用,所以盡可能減少執行的程式碼,等到使用者真正要執行功能的時候在進行呼叫即可。通常像是 tooltip 或 dialog 可以延遲等到要出現的時候在初始化即可。

簡單舉個例子,在 form 表單大家常用的 jQuery Plugin datepicker,通常初始化會透過底下方式來寫:

$(document).ready( function() {
    $("input.date").datepicker({
        minDate: moment().subtract( "months", 1 ).toDate(),
        maxDate: moment().add( "months", 1 ).toDate(),
        dateFormat: "d M, y",
        constrainInput: true,
        beforeShowDay: $.datepicker.noWeekends
    });
});

用這缺點就是當 html 完成載入後,jQuery 會開始找 input 並且符合 class 為 date 的 元件,這會 delay 使用者正常使用網頁,比較好的解決方式就是 bind 在 input 的 focus 事件上。

$(document).on( "focus", "input.date:not(.hasDatepicker)", function() {
    $(this).datepicker({
        minDate: moment().subtract( "months", 1 ).toDate(),
        maxDate: moment().add( "months", 1 ).toDate(),
        dateFormat: "d M, y",
        constrainInput: true,
        beforeShowDay: $.datepicker.noWeekends
    });
});

此寫法有另外的優點就是當如果有建立新的 input.date 元件,可以動態初始化元件。初始過的元件,我們就動態增加 hasDatepicker class 來判斷是否已經初始化。

網頁開始先優先執行 AJAX

由於執行 AJAX 需要一段時間,所以請在 html load 之前就開始執行,並不需要等到 $(document).ready() 後才執行,另外在 AJAX 完成執行後的 Complete function 加入 $(document).ready() 函式確保 html 已載入完成。

延遲載入 social button(Facebook Like, Google +1, Twitter)

現在大多網站都有一大堆分享機制(social networks),像是 Facebook Like、Twitter 等等,但是這些 JS 的載入,都大大影響到網頁的載入時間,其實最主要的解決方式就是務必思考哪些頁面才需要這些 button,能減少載入外部 JS 就是提昇網頁載入速度,在以前載入外部 JS 的作法就是底下

<script>
(function(d, s) {
  var js, fjs = d.getElementsByTagName(s)[0], load = function(url, id) {
    if (d.getElementById(id)) {return;}
    js = d.createElement(s); js.src = url; js.id = id;
    fjs.parentNode.insertBefore(js, fjs);
  };
  load('//connect.facebook.net/en_US/all.js#appId=272697932759946&xfbml=1', 'fbjssdk');
  load('http://apis.google.com/js/plusone.js', 'gplus1js');
  load('//platform.twitter.com/widgets.js', 'tweetjs');
}(document, 'script'));
</script>

現在請改寫成底下

<script>
(function(w, d, s) {
  function go(){
    var js, fjs = d.getElementsByTagName(s)[0], load = function(url, id) {
      if (d.getElementById(id)) {return;}
      js = d.createElement(s); js.src = url; js.id = id;
      fjs.parentNode.insertBefore(js, fjs);
    };
    load('//connect.facebook.net/en_US/all.js#appId=272697932759946&xfbml=1', 'fbjssdk');
    load('http://apis.google.com/js/plusone.js', 'gplus1js');
    load('//platform.twitter.com/widgets.js', 'tweetjs');
  }
  if (w.addEventListener) { w.addEventListener("load", go, false); }
  else if (w.attachEvent) { w.attachEvent("onload",go); }
}(window, document, 'script'));
</script>

由於各瀏覽器相容問題,所以判斷是否支援 addEventListener 或 attachEvent,在 onload 後才開始執行。更多詳細內容可以參考 requesting these scripts

四月 5, 2013

小惡魔AppleBOY
AppleBOY
小惡魔 - 電腦技術 - 工作筆記 - AppleBOY is about »

tag cloud

» MySQL 用 MySQLDump 備份 InnoDB 注意事項

mysql_logomysql_logo

大家在備份 MySQL 資料庫時一定是使 mysqldump 指令,不管是 MyISAM 或 InnoDB 都一樣, 在處理 InnoDB 格式備份時使用 mysqldump -single-transaction,但是你會發現在大多的備份狀況都是 OK 的,只是有時候會發現有的資料表只有備份到 structure 而無備份到 Data?

MySQL Performance Blog 看到這篇講解 Best kept MySQLDump Secret,此問題出在 how MySQL’s Transactions work with DDL,ALTER TABLE 會建立一個 temporary table,並且將該資料表資料複製過去,接著刪除原有資料表,最後將 temporary table 命名為原來資料表。

底下是原作者提到的原因

How does data visibility works in this case ? DDLs are not transactional and as such the running transaction will not see the contents of old table once it is dropped, transaction also will see the new table which was created after transaction was started, including table created by ALTER TABLE statement. Transactions however apply to DATA which is stored in this table and so data which was inserted after start of transaction (by ALTER TABLE statement) will not be visible. In the end we will get new structure in the dump but no data.

最好的解法就是改用 mysqldump -lock-all-tables,但是備份的時候,資料庫是無法寫入,僅能讀取,也或者可以透過 Percona Xtrabackup 工具來備份 InnoDB。

三月 31, 2013

小惡魔AppleBOY
AppleBOY
小惡魔 - 電腦技術 - 工作筆記 - AppleBOY is about »

tag cloud

» Galera Cluster for MySQL Multi-master Replication

galera_mysql_replicationgalera_mysql_replication

最近公司買了幾台機架伺服器來處理 HTTP 跟 DB Load balancer,要做到 DB 的分散式架構,首先需要同步多台機器資料,也就是寫入或更動任意一台單筆資料,另外平行的機器也會同時進行更新。同步的好處可以用來做備援及分散處理連線,而要做到此功能,可子參考網路上評價不錯的 Galera Cluster for MySQL 方案。本篇會介紹在 UbuntuCentOS 6.x final 版本如何安裝 Galera 伺服器套件及設定。要架設 Galera Cluster Server,有兩種套件選擇,一個是 Percona XtraDB Cluster 另一個是 MariaDB Galera Cluster,這次作者會介紹後者的安裝。

Galera Cluster 介紹

為什麼要選擇 Galera Cluster Server,它有什麼優點及功能呢?MySQL/Galera 是一套可以同步多台 MySQL/InnoDB 機器的叢集系統,底下可以列出功能。

  • 同步複製資料
  • 可讀取和寫入叢集系統內任一節點
  • 自動偵測節點錯誤,如果有節點當機,則叢集系統自動移除該節點
  • 可任意擴充節點
  • 採用 row level 方式來平行複製資料

從上面功能看來,我們可以平行任意擴充節點,動態增加伺服器到叢集系統,要做到上面功能,就是利用 Galera library 來做到同步資料處理,同步的詳細細節,可以參考 Galera library 連結。這邊就不再多描述了。

安裝 Galera Cluster Server

本篇介紹的 MySQL Server 是使用 MariaDB 套件,而不是安裝原始的 MySQL。CentOS 和 Ubuntu 安裝方式雷同,前者是用 yum 後者則是 aptitude,在安裝前請先下載對應的 repository 設定檔

CentOS

$ yum -y update && yum -y upgrade
$ yum -y install MariaDB-Galera-server MariaDB-client galera

Ubuntu

$ aptitude -y update
$ aptitude -y install mariadb-galera-server-5.5 galera

啟動 MySQL

$ /etc/init.d/mysql start

設定 Galera Cluster Server

先講一下環境,目前總共兩台 Galera Server,IP 分別是:

Node_1: 192.168.1.100
Node_2: 192.168.1.101

建立 Node_1, Node_2 MySQL User,用來認證使用,先進入 MySQL Console.

$ mysql -u root -p
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 154
Server version: 10.0.1-MariaDB-mariadb1~precise-log mariadb.org binary distribution

Copyright (c) 2000, 2012, Oracle, Monty Program Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]>

建立 cluster 使用者,密碼為 1234,針對 % 跟 localhost 同時建立。

MariaDB [(none)]> GRANT USAGE ON *.* to cluster@'%' IDENTIFIED BY '1234';
MariaDB [(none)]> GRANT ALL PRIVILEGES on *.* to cluster@'%';
MariaDB [(none)]> GRANT USAGE ON *.* to cluster@'localhost' IDENTIFIED BY '1234';
MariaDB [(none)]> GRANT ALL PRIVILEGES on *.* to cluster@'localhost';

在 192.168.1.100 建立 Galera 設定檔 /etc/mysq/conf.d/wsrep.cnf

[MYSQLD]                                                                                                              
wsrep_provider=/usr/lib64/galera/libgalera_smm.so                                                                    
wsrep_cluster_address="gcomm://"                                              
wsrep_sst_auth=cluster:1234

重新啟動 mysqld 會看到多 listen 4567 port

tcp        0      0 0.0.0.0:3306            0.0.0.0:*               LISTEN      1118/mysqld
tcp        0      0 0.0.0.0:4567            0.0.0.0:*               LISTEN      1118/mysqld

在 192.168.1.101 建立 Galera 設定檔 /etc/mysq/conf.d/wsrep.cnf 並且將 cluster address 設定為 192.168.1.100

[MYSQLD]                                                                                                              
wsrep_provider=/usr/lib64/galera/libgalera_smm.so                                                                    
wsrep_cluster_address="gcomm://192.168.1.100:4567"                                              
wsrep_sst_auth=cluster:1234

設定完成後,重新啟動 mysql

$ /etc/init.d/mysql restart

要怎麼驗證設定成功呢?可以透過 mysql console 來確認

$ mysql -e "SHOW STATUS LIKE 'wsrep%';"

可以看到結果如下

+----------------------------+--------------------------------------------------------------+
| wsrep_local_state_uuid     | b4e876e0-8c1e-11e2-0800-8da732edfe2a                         |
| wsrep_protocol_version     | 4                                                            |
| wsrep_last_committed       | 516                                                          |
| wsrep_replicated           | 0                                                            |
| wsrep_replicated_bytes     | 0                                                            |
| wsrep_received             | 3                                                            |
| wsrep_received_bytes       | 282                                                          |
| wsrep_local_commits        | 0                                                            |
| wsrep_local_cert_failures  | 0                                                            |
| wsrep_local_bf_aborts      | 0                                                            |
| wsrep_local_replays        | 0                                                            |
| wsrep_local_send_queue     | 0                                                            |
| wsrep_local_send_queue_avg | 0.000000                                                     |
| wsrep_local_recv_queue     | 0                                                            |
| wsrep_local_recv_queue_avg | 0.000000                                                     |
| wsrep_flow_control_paused  | 0.000000                                                     |
| wsrep_flow_control_sent    | 0                                                            |
| wsrep_flow_control_recv    | 0                                                            |
| wsrep_cert_deps_distance   | 0.000000                                                     |
| wsrep_apply_oooe           | 0.000000                                                     |
| wsrep_apply_oool           | 0.000000                                                     |
| wsrep_apply_window         | 0.000000                                                     |
| wsrep_commit_oooe          | 0.000000                                                     |
| wsrep_commit_oool          | 0.000000                                                     |
| wsrep_commit_window        | 0.000000                                                     |
| wsrep_local_state          | 4                                                            |
| wsrep_local_state_comment  | Synced                                                       |
| wsrep_cert_index_size      | 0                                                            |
| wsrep_causal_reads         | 0                                                            |
| wsrep_incoming_addresses   | xxx.xxx.xxx.xxx:3306,xxx.xxx.xx.xxx:3306,xxx.xxx.xxx.xx:3306 |
| wsrep_cluster_conf_id      | 45                                                           |
| wsrep_cluster_size         | 3                                                            |
| wsrep_cluster_state_uuid   | b4e876e0-8c1e-11e2-0800-8da732edfe2a                         |
| wsrep_cluster_status       | Primary                                                      |
| wsrep_connected            | ON                                                           |
| wsrep_local_index          | 0                                                            |
| wsrep_provider_name        | Galera                                                       |
| wsrep_provider_vendor      | Codership Oy <info@codership.com>                            |
| wsrep_provider_version     | 23.2.4(r147)                                                 |
| wsrep_ready                | ON                                                           |
+----------------------------+--------------------------------------------------------------+

看到上述結果,有一個非常重要的數值,那就是 wsrep_ready,正確值是 ON,另外看看 wsrep_cluster_size 是否跟您設置 Node 的數量相同,這兩個如果都正確,那就表示設定成功了,由於上面 192.168.1.100 是主 Cluster Server,現在我們必須互相設定雙方 Address 也就是設定如下

node 01: gcomm://192.168.1.101
node 02: gcomm://192.168.1.100

設定如上述的好處就是,當 Node 01 關機時,資料還是在 Node 2 繼續運作,等到 Node 01 恢復上線後,資料又會從 Node 02 同步複製過來。

增加新 Node

我們可以任意新增多台 Node 到 Cluster 叢集系統裡,設置過程非常簡易

1. 安裝 MariaDB Server
2. 安裝 Galera Library
3. 設定 wsrep_cluster_address="gcomm://192.168.1.100:4567"

設定完成,就可以看到資料庫已經同步複製資料到新 Node 上面。如果遇到任何一台 Node 突然關機,不用緊張,系統會保持目前的資料,等到機器上線時,又會從 gcomm://another_node_ipaddress 同步後續的資料。

動態設定 gcomm://

如果新增一台新的 Node,我們就必須改動其它 Node 的 gcomm:// 設定,並且重新啟動 mysqld 服務,這樣會有些微時間影響,我們可以透過直接修改 GLOBAL wsrep_cluster_address 的值

$ mysql -e "SHOW VARIABLES LIKE 'wsrep_cluster_address';"                                                            
+-----------------------+-------------------------------------------------+                                          
| Variable_name         | Value                                           |                                          
+-----------------------+-------------------------------------------------+                                          
| wsrep_cluster_address | gcomm://xxx.xxx.xxx.xx:4567,xxx.xxx.xx.xxx:4567 |                                          
+-----------------------+-------------------------------------------------+

mysql> SET GLOBAL wsrep_cluster_address='gcomm://192.168.1.100:4567';
Query OK, 0 ROWS affected (3.51 sec)

mysql> SHOW VARIABLES LIKE 'wsrep_cluster_address';
+-----------------------+---------------------------+
| Variable_name         | VALUE                     |
+-----------------------+---------------------------+
| wsrep_cluster_address | gcomm://192.168.1.100:4567|
+-----------------------+---------------------------+

最後需要注意的地方是,由於我們每一台機器都互相設定,如果要關閉全部 Node 機器,請務必將第一台重新設定 gcomm:// 為空值,讓後續重新啟動的機器可以先連上此機器進行同步,

這次把 MySQL Replication 安裝設定完成,也就是完成架構圖的最下面部份

Server-load-balancersServer-load-balancers

之後會介紹如何透過 HAproxy 來處理 MySQL Load Balancer。

三月 28, 2013

小惡魔AppleBOY
AppleBOY
小惡魔 - 電腦技術 - 工作筆記 - AppleBOY is about »

tag cloud

» 統一開發者編輯器 Coding Style

在多人開發專案時候,一定會遇到大家使用的編輯器大不相同 TextMate, Vim, Sublime Text 2, Geany, Notepad++…等,該如何統一程式碼的一致性呢?這邊要講得不是各種語言的 Coding Style,而是編輯器的設定,例如大家一定會遇到有的開發者使用 Tab 另外一群人使用 Space,在同一專案裡面就會發現有的 tab 有的 space,這樣看起來非常的亂,該如何統一大家的預設 indent style,就是要使用 EditorConfig 啦。使用方式很簡單,可以在專案目錄內加入 .editorconfig 內容設定如下

; EditorConfig is awesome: http://EditorConfig.org

root = true ; top-most EditorConfig file

; Unix-style newlines with a newline ending every file
[*]
end_of_line = lf
insert_final_newline = true

; 4 space indentation
[*.py]
indent_style = space
indent_size = 4

; Tab indentation (no size specified)
[*.js]
indent_style = tab

; Indentation override for all JS under lib directory
[lib/**.js]
indent_style = space
indent_size = 2

設定方式真的很簡單,如果是 Makefile 可以加入底下

[Makefile]
indent_style = tab

設定完成,最後只要裝上編輯器的 Plugin 即可,可以參考這裡,目前支援編輯器如下

如果開發者沒有使用上面的編輯器,那可能需要請他更換了,或者是設定該編輯器設定了。

三月 26, 2013

小惡魔AppleBOY
AppleBOY
小惡魔 - 電腦技術 - 工作筆記 - AppleBOY is about »

tag cloud

» Javascript command line tool GruntJS 介紹

Update: 補上一張執行後的截圖 2013.03.27

gruntlogogruntlogo

GruntJS 是一套 JavaScript Task Runner,為什麼官網會這樣寫呢?網站上線之前,是不是需要經過測試,壓縮,及品質控管,這些 Task 該如何實現,在 GruntJS 還沒出現之前,大家可以透過 Linux command 的方式來達成,但是對於前端工程師而言,多學習 command line 真的是要他們的命,所以 GruntJS 解決了此問題,將所有的 Task 用 Javascript 方式設定就可以自動佈署或測試。GruntJS 的 Plugin 也非常多且完整,像是大家常用的 CoffeeScriptHandlebarsJadeJsHintLessSassCompassStylus…等都有支援。更多好用的 Plugin 可以在官網搜尋頁面上找到。

安裝方式

Grunt 可以透過 Node.js 的管理工具 npm 方式來安裝,Windows 只要到 Node.js 官網下載安裝包,直接按下一步即可安裝完畢,Linux 可以透過 NVM 方式來管理 Node.js 版本,可以參考作者之前寫的 Node Version Manager 版本管理 NVM。需要注意的是 Grunt 0.4.x 需要 Node.js >= 0.8.0 版本才可以。

如果之前已經安裝 Grunt 請先移除安裝

$ npm uninstall -g grunt

Linux 請切換到 root 使用者來安裝

$ npm install -g grunt-cli

準備新專案

在使用 Grunt 指令前,請在專案目錄內新增 package.jsonGruntfile.js 檔案

package.json: 此檔案紀錄專案 metadata 以便將來做成 npm module,另外也會記載專案內所用到 Grunt plugins 版本資訊,像是 devDependencies 設定。
Gruntfile.js: 此檔案可以用 Coffscript.coffee 撰寫,用來紀錄工作內容及相關 Plugins 載入.

PS. 如果是用 Grunt 0.3.x 版本,請命名為 grunt.js

package.json

此檔案記載專案相關資訊,也包含了 GruntJS 所需要用到的 Plugins,範例如下(官網提供)

{
  "name": "my-project-name",
  "version": "0.1.0",
  "devDependencies": {
    "grunt": "~0.4.1",
    "grunt-contrib-jshint": "~0.1.1",
    "grunt-contrib-nodeunit": "~0.1.2"
  }
}

建立此檔案後,在專案目錄內,執行 npm install,會發現專案內多了 node_modules 目錄。可以將此目錄名稱加入到 .gitignore,免的不小心 commit 到伺服器。如果不想手動更改 devDependencies 資訊,其實可以透過 npm install grunt –save-dev 方式加入到 devDependencies 裡。

Gruntfile.js

可以透過 Gruntfile.coffee 或 Gruntfile.js 來產生檔案,此命名適用於 0.4.x 版本,如果是 0.3.x 版本請命名為 grunt.js。此檔案會包含底下部份

* wrapper 寫法
* 專案及任務設定
* 載入 Grunt Plugins 和任務內容
* 定義特定任務

拿官網的例子來介紹:

module.exports = function(grunt) {

  // Project configuration.
  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    uglify: {
      options: {
        banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n'
      },
      build: {
        src: 'src/<%= pkg.name %>.js',
        dest: 'build/<%= pkg.name %>.min.js'
      }
    }
  });

  // Load the plugin that provides the "uglify" task.
  grunt.loadNpmTasks('grunt-contrib-uglify');

  // Default task(s).
  grunt.registerTask('default', ['uglify']);

};

在 package.json 裡面設定安裝 grunt-contrib-uglify 套件,uglify 任務就是將 Javascript 檔案壓縮,當我們執行 grunt 指令時,Grunt 會執行預設的任務 uglify。上面有提到四點 Grunt 檔案會包含的項目,其中第一點是 wrapper 寫法,也就是上面例子內的

module.exports = function(grunt) {
  // Do grunt-related things in here
};

接著注意專案的設定,也就是底下內容

// Project configuration.
grunt.initConfig({
  pkg: grunt.file.readJSON('package.json'),
  uglify: {
    options: {
      banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n'
    },
    build: {
      src: 'src/<%= pkg.name %>.js',
      dest: 'build/<%= pkg.name %>.min.js'
    }
  }
});

所有的工作項目設定都會寫在 grunt.initConfig 裡面,看到第一行 grunt.file.readJSON("package.json"),將 package.json 內容讀到 pkg 變數,接著參數設定就可以使 <% %> 方式讀取。uglify 工作項目內的 options 設定可以直接參考 grunt-contrib-uglify,我們可以定義多個 target 來區分多個工作內容,範例如下

// Project configuration.
grunt.initConfig({
  pkg: grunt.file.readJSON('package.json'),
  uglify: {
    options: {
      banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n'
    },
    build: {
      src: 'src/<%= pkg.name %>.js',
      dest: 'build/<%= pkg.name %>.min.js'
    },
    my_target_1: {
      options: {
        sourceMap: 'path/to/source-map.js'
      },
      files: {
        'dest/output.min.js': ['src/input.js']
      }
    },
    my_target_2: {
      options: {
        sourceMap: 'path/to/source-map.js',
        sourceMapRoot: 'http://example.com/path/to/src/',
        sourceMapIn: 'example/coffeescript-sourcemap.js'
      },
      files: {
        'dest/output.min.js': ['src/input.js']
      }
    }
  }
});

完成基本 Grunt Plugin 設定,接著將此 Plugin 載入

// Load the plugin that provides the "uglify" task.
grunt.loadNpmTasks('grunt-contrib-uglify');

最後定義預設的任務

// Default task(s).
grunt.registerTask('default', ['uglify']);

Grunt 設定檔就完成了,可以來進行測試,我們可以直接下 grunt 指令,系統會自動跑預設任務,也就是 uglify,也或者如果有多個任務時,你只想執行 uglify 任務,請將指令改成 grunt uglify,如果是想要執行 uglify 任務內的 my_target_2 項目呢?請直接下 grunt uglify:my_target_2

基本介紹到這裡,大家對於 Grunt.js 應該都有基本的瞭解。最後補張執行後的圖

GruntJSGruntJS

三月 21, 2013

小惡魔AppleBOY
AppleBOY
小惡魔 - 電腦技術 - 工作筆記 - AppleBOY is about »

tag cloud

» Linode VPS 升級網路及硬體設備

Linode VPSLinode VPS

Linode 是我最喜歡的國外 VPS 廠商,重點是速度跟穩定度都還不錯,不過今年不知道是不是被 DigitalOcean 刺激到?所以這個月將網路設備全面升級,不僅降低 latency 和 redundancy,出口端網路設備全部換成 Cisco Nexus 7000 series 等級,此系列提供了足夠的 Mac Address 及處理大量 Request,另外 access layer switches 則換成 Cisco Nexus 5000 series switches 跟 Nexus 2000 series Fabric Extenders,這些都不是重點,重點是每台 VPS 現在對外流量都變成原先的十倍,當然對內流量是無限制的,底下是 Linode 最新網路架構圖

Linode-NextGen-NetworkLinode-NextGen-Network

對外流量都增加十倍如下表,真是太超過了。

Linode 512 upgraded from 200GB to 2000GB (2TB)
Linode 1G upgraded from 400GB to 4000GB (4TB)
Linode 2G upgraded from 800GB to 8000GB (8TB)
Linode 4G upgraded from 1600GB to 16000GB (16TB)
Linode 8G upgraded from 2000GB to 20000GB (20TB)

這樣就算了,接著升級 VPS 硬體,每個 Linode 全升級成 8 Core CPU Instances,這簡直是太瘋狂了,已經讓作者忍不住來玩看看了,官方直接提供了重新編譯系統核心的速度,使用機器為 Linode 1024 with 8 cores,編譯完成時間大概為 100 秒,這速度……

apt-get update && apt-get -y install build-essential
wget https://www.kernel.org/pub/linux/kernel/v3.x/linux-3.8.tar.xz
tar xf linux-3.8.tar.xz
cd linux-3.8/
make distclean && make defconfig && time make -j8

real 1m41.861s
user 10m37.423s
sys 1m41.298s

最後文章提到,那硬碟呢?人家 DigitalOcean 全面採用 SSD,那 Linode 呢?沒關係,官方說這是未來的計畫,要全面換成 SSD 需要一大筆資金阿,所以讓大家期待一下吧。不過 CPU 已經這麼快了,那 Ram 呢?大家其實希望增加的是 Ram 吧 XD

最後補一張圖來證明真的是 8 Core CPU:

linodelinode

Ref 兩篇官方說明:

Linode NextGen: The Hardware
Linode Nextgen: The Network

三月 14, 2013

小惡魔AppleBOY
AppleBOY
小惡魔 - 電腦技術 - 工作筆記 - AppleBOY is about »

tag cloud

» Git denying non-fast forward 問題

最近幫別公司處理 denying non-fast forward 的 git server 問題,沒事就別動檔案權限,不管是不是修改內容,只要用 chmod 指令,Git 還是會判別檔案變動。處理 git push 直接給我噴

$ git push --force origin master
Total 0 (delta 0), reused 0 (delta 0)  
error: denying non-fast forward refs/heads/master (you should pull first)  
To git@git.example.com:myrepo.git  
! [remote rejected] master -> master (non-fast forward)  
error: failed to push some refs to 'git@git.example.com:myrepo.git'

會遇到這問題的原因是使用者將不該 commit 的程式碼都 push 到伺服器上面,例如資料庫帳號密碼,個人帳蜜等等,這真的是不應該,解決方式也沒有很難,只要用 git reset –hard 到您需要的 commit hash 值,並且 git push –force 方式蓋掉 Server 上面的程式碼,但是如果遇到 git push –force origingit push –force origin master 都無作用,那就請加上底下設定

$ git config --system receive.denyNonFastForwards false

在 Github 上面怎麼用 force 都可以直接覆蓋,私人自己架設的,請加入此設定,但是這設定基本上蠻危險的,如果用 git reset –hard xxxx,xxx 為很久以前的版本,並且 force 到 Server 上面,那就等於沒救了 XD,所以用 –force push 到 server 上面時,請小心阿,基本上可以搭配 git cherry-pick 來撿還需要的 commit 內容。

Ref:
git cherry-pick 處理專案 pull request
Git reset –hard and a remote repository
7.1 Customizing Git – Git Configuration

三月 7, 2013

小惡魔AppleBOY
AppleBOY
小惡魔 - 電腦技術 - 工作筆記 - AppleBOY is about »

tag cloud

» Remove Google CDN reference for jQuery?

jquery logojquery logo

html5-boilerplate 看到有人發 Remove Google CDN reference for jQuery 的 pull request,發現國外鄉民其實蠻有趣的,也很會表達自己的想法,根據 Steve Webster 在 2011/11/21 寫了一篇 Caching and the Google AJAX Libraries 裡面的結論是: 使用 Google CDN Library 對於第一次訪問網站並沒有很大的幫助,其實這句話非常有疑問,如果網站不想 host 一些 static file 又想要用 CDN 的話,Google 絕對是最好的選擇,底下就有人反駁 Google CDN 還是比自己 host 檔案快很多,所以此 pull request 好像沒有啥意義。

最好的解法,還是把全部的 script 檔案統一包成一個檔案,減少 http request (bundling jQuery up with the rest of your site’s JavaScript),那官方期望的解決方式就是用 Bower + AMD + r.js,對於一個上線網站,假如沒有做到這些事情,我想也不用考慮到 Google CDN 的速度了。

三月 1, 2013

小惡魔AppleBOY
AppleBOY
小惡魔 - 電腦技術 - 工作筆記 - AppleBOY is about »

tag cloud

» Backbone.js rewrite into CoffeeScript?

backbonebackbone

看到 @gsamokovarov 提出將 Backbone.js 改寫成 CoffeeScript 架構的 Pull request,結果官方團隊其中一位開發作者回應了一張圖,代表他的心情 XD,各位有興趣可以點上面連結看看,後來有其他人回應說,為什麼官方不用 CoffeeScript 來寫了,發此 Pull Request 的作者也有說,他只是將架構改成 CoffeeScript 讓大家參考看看而已,沒有真的希望可以納入整個 Backbone.js 專案,如果有其他開發者需要的話,一樣可以 fork 此專案,說明文件也用 docco 產生好了,可以參考此連結,官方作者也提到,大部份的第3方 Library 還是不會使用 CoffeeScript 來當作基底開發,畢竟並非所有人都知道 CoffeeScript,如果官方想這麼開發的話,早就再 2010 年丟釋出 Backbone.js 的時候就直接採用了,不會拖到現在還沒出來,當然最後官方也希望將此 pull request 寫到 wiki 裡面給大家參考,等待原作者補開發動機及細節。

A Feedjack powered Planet
A Django site.