Wednesday, March 25, 2015

jQuery Change Image src with Fade Effect

I think instead of using FadeIn and fadeOut, its better to use fadeTo functionality as fadeIn and fadeOut created a time gap between them for few micro-seconds.

I have used above code from Sylvain : thanks to him

Use fadeTo():

$("#link").click(function() {

  $("#image").fadeTo(1000,0.30, function() {
  return false;

Use fadeIn and fadeOut:

$(".thumbs a").click(function(e) {
    $imgURL = $(this).attr("href");
    $(".boat_listing .mainGallery")
        .fadeOut(400, function() {
            $(".boat_listing .mainGallery").attr('src',$imgURL);


Coolors 是一個免費的自動配色工具,可以讓您在線上快速產生各種適宜的色票,省去自己配色的煩惱。

Monday, March 23, 2015

Pass a object by value - assigning / copying object

JSON method:

var myObjDefault = JSON.stringify({
  price: {min: 0, max: 999},
  weight: {min: 0, max: 999},

var myObj = JSON.parse(myObjDefault);

Jquery Method:

// Shaw Copy
var oShallowCopy = jQuery.extend({}, o);

// Deep Copy
var oDeepCopy    = jQuery.extend(true, {}, o); 


Sunday, March 22, 2015

Magento programatically refresh reindexing indexes

I have written a script to update the product description information programatically. However, after I run the script, the URL is reset to a empty blank value. Refresh the indexes will re-generate the URL keys.

### Magento programatically refresh reindexing indexes

function refreshAllIndexes() {
  /* @var $indexCollection Mage_Index_Model_Resource_Process_Collection */
  $indexCollection = Mage::getModel('index/process')->getCollection();

  foreach ($indexCollection as $index) {
    /* @var $index Mage_Index_Model_Process */

    #echo '<pre>' . print_r($index->debug(), TRUE) . '</pre>';

 * catalog_product_attribute     Product Attributes
 * catalog_product_price         Product Prices
 * catalog_url                   Catalog URL Rewrites
 * catalog_product_flat          Product Flat Data
 * catalog_category_flat         Category Flat Data
 * catalog_category_product      Category Products
 * catalogsearch_fulltext        Catalog Search Index
 * cataloginventory_stock        Stock Status
 * tag_summary                   Tag Aggregation Data
 * targetrule                    Target Rules
function refreshIndex($indexName) {
  $process = Mage::getModel('index/indexer')->getProcessByCode($indexName);


Tuesday, March 17, 2015

Get Product Information Query

Attribute Code SQL Equivalent Example
eq = $collections->addAttributeToFilter('price', array('eq' => 10.00));
neq != $collections->addAttributeToFilter('price', array('neq' => 10.00));
like LIKE $collections->addAttributeToFilter('name', array('like' => '%VJTemplates%'));
nlike NOT LIKE $collections->addAttributeToFilter('name', array('nlike' => '%VJTemplates%'));
in IN () $collections->addAttributeToFilter('id', array('in' => array(1,2,3,4)));
nin NOT IN () $collections->addAttributeToFilter('id', array('nin' => array(1,2,3,4)));
is IS
notnull IS NOT NULL
$collections->addAttributeToFilter('description', 'notnull');
null IS NULL $collections->addAttributeToFilter('description', 'null');
moreq >= $collections->addAttributeToFilter('price', array('moreq' => 10.00));
gt > $collections->addAttributeToFilter('price', array('gt' => 10.00));
lt < $collections->addAttributeToFilter('price', array('lt' => 10.00));
gteq >= $collections->addAttributeToFilter('price', array('gteq' => 10.00));
lteq <= $collections->addAttributeToFilter('price', array('lteq' => 10.00));
finset FIND_IN_SET() $collections->addAttributeToFilter('custom', array('finset' => '1'));
from >= $collection->addAttributeToFilter('created_at', array(
'from' => '10 July 2013',
'to' => '11 July 2013',
to <= 'date' => true
date ));
datetime $collection->addAttributeToFilter('created_at', array(
'from' => '2013-01-01 00:00:00',
'to' => '2013-12-31 00:00:00',
'datetime' => true

Get a list of attributes of a product:

$attributes = Mage::getSingleton('catalog/config')->getProductAttributes();
echo '<pre>' . print_r($attributes, TRUE) . '</pre>';

AND Operation:

$collections = Mage::getModel('catalog/product')
       ->addAttributeToSelect(array('id', 'sku', 'name', 'price'))
       ->addAttributeToFilter('name', array('eq' => 'test car'))
       ->addAttributeToFilter('price', array('eq' => 10.00))

OR Operation:

$collections = Mage::getModel('catalog/product')
       ->addAttributeToSelect(array('id', 'sku', 'name', 'price'))
           array('attribute' => 'name', 'eq' => 'test car'),
           array('attribute' => 'sku', 'regexp' => '^ABC'),

Looping through the collection:

foreach ($collection as $prodObj) {
  echo $prodObj->getId() . ' ';
  echo $prodObj->getSku() . ' ';
  echo $prodObj->getName() . ' ';
  echo $prodObj->getPrice() . ' ';


Monday, March 16, 2015

To redirect to a page from a template in Magento


Wednesday, March 11, 2015

Set JQuery UI modal dialog overlay background color

To remove the strip and use a custom background color you can do like this on the open event :

open : function(event, ui){
        overflow: 'hidden'
        background:"rgb(0, 0, 0)",
        opacity: ".50 !important",
        filter: "Alpha(Opacity=50)",
beforeClose: function(event, ui) {
    $("body").css({ overflow: 'inherit' })


CSS Sprites - offset the background

Method 1 (preferred):

.myul {
  position: relative;

.myli {
  position: absolute;
  list-style: none;
  width: 52px;
  height: 52px;
  background: url('mysprite2.gif') no-repeat;
  display: block;
  top: 0px;

.myli:hover {
  background-position-y: -51px;

#myli1 {
  background-position-x: 0px;
  left: 0px;

#myli2 {
  background-position-x: -51px;
  left: 54px;

#myli3 {
  background-position-x: -102px;
  left: 108px;

#myli4 {
  background-position-x: -153px;
  left: 162px;

<ul class="myul">
  <li id="myli1" class="myli"></li>
  <li id="myli2" class="myli"></li>
  <li id="myli3" class="myli"></li>
  <li id="myli4" class="myli"></li>


Method 2:

.myul {
  position: relative;
  width: 400px;
  height: 200px;
  background: transparent url('mysprite.jpg') no-repeat;
  padding: 0px;

.myli {
  position: absolute;
  list-style: none;
  width: 100px;
  height: 200px;
  top: 0px;
  display: block;

#myli1 {
  left: 0px;

#myli2 {
  left: 100px;

#myli3 {
  left: 200px;

#myli4 {
  left: 300px;

#myli1:hover {
  background: transparent url('mysprite.jpg') 0px -200px no-repeat;
  opacity: 0.8;

#myli2:hover {
  background: transparent url('mysprite.jpg') -100px -200px no-repeat;
  opacity: 0.8;

#myli3:hover {
  background: transparent url('mysprite.jpg') -200px -200px no-repeat;
  opacity: 0.8;

#myli4:hover {
  background: transparent url('mysprite.jpg') -200px -200px no-repeat;
  opacity: 0.8;


<ul class="myul">
  <li id="myli1" class="myli"></li>
  <li id="myli2" class="myli"></li>
  <li id="myli3" class="myli"></li>
  <li id="myli4" class="myli"></li>

<img src="mysprite.jpg" />


hide the title bar and close button in jQuery UI

  create: function(event, ui) {
    $j('.ui-dialog-titlebar').hide(); // hide the title bar.
    $j('.ui-dialog-titlebar-close').hide(); // hide the close button.

css complex attribute selector

/* Attribute Present Selector */
#checkoutSteps a[target] {
  color: #fff;

/* Attribute Equals Selector */
#checkoutSteps label[for="billing:firstname"] {
  color: #fff;

/* Attribute Begins With Selector */
#checkoutSteps label[for^="billing:"] {
  color: #fff;

/* Attribute Contains Selector */
#checkoutSteps label[for*="billing:"] {
  color: #fff;

/* Attribute Ends With Selector */
#checkoutSteps a[href$=".pdf"] {
  color: #fff;

/* Attribute Spaced Selector - attribute is within space separated list */

a[rel~="tag"] {...}

<a href="#" rel="tag nofollow">...</a>

/* Attribute Hyphenated Selector - attribute is within dash separated list */

a[lang|="en"] {...}

<a href="#" lang="en-US">...</a>


Tuesday, March 10, 2015

How can I restrict IP addresses in .htaccess with the reverse proxy in front?

Since requests to your site are usually first handled by the Varnish reverse proxy, you can't use the sender IP address to block certain IP addresses in your .htaccess configuration file. The following will not work because all requests the web server receives will originate from the proxy address, and in consequence, no access will ever be allowed:

Order deny,allow
Deny from All

Allow from
Allow from

There is a way of checking the real sender address, though, because Varnish puts it in the HTTP header X-Forwarded-For.

A few additional lines make Apache check this HTTP header, too:

Order deny,allow
Deny from All

SetEnvIF X-Forwarded-For "" AllowIP
SetEnvIF X-Forwarded-For "" AllowIP

Allow from env=AllowIP
Allow from
Allow from

This ruleset will work both for requests handled by Varnish (Port 80) and directly handled by Apache (Port 81).

Check the bash shell script is being run by root or not


# Make sure only root can run this script
if [[ $EUID -ne 0 ]]; then
   echo "This script must be run as root" 1>&2
   exit 1

To ignore files in subversion

To ignore files in subversion:

# svn propedit svn:ignore /www/magento1.9.1/media/catalog/product


To remove svn:ignore property:

// For current directory

# svn propdel svn:ignore .

// For recursive

# svn prodel svn:ignore -R

Failed opening 'SoapClient.php' for inclusion

2015-03-10T17:43:18+00:00 ERR (3): Warning: include(): Failed opening 'SoapClient.php' for inclusion (include_path='/var/www/html/magento1.9.1/app/code/local:/var/www/html/magento1.9.1/app/code/community:/var/www/html/magento1.9.1/app/code/core:/var/www/html/magento1.9.1/lib:.:/usr/share/pear:/usr/share/php')  in /var/www/html/magento1.9.1/lib/Varien/Autoload.php on line 94

Double check if Soap is installed:

# yum list installed | grep php-soap

php-soap.x86_64                       5.4.16-23.el7_0.3                @updates

Install php-soap:

# yum install php-soap

Make sure the components have the same versions:

# yum list installed | grep php

Update PHP:

# yum update php

Make sure SOAP is loaded:

# systemctl restart httpd
# systemctl restart php-fpm
# php -m | grep soap

Monday, March 9, 2015

the download attribute on a link

when the user clicks the link, the download attribute appears in the save dialog instead of the garbled mess that was there before. In this case, the file will be downloaded as expenses.pdf. The download attribute also triggers a force download.

<!-- will download as "test.pdf" -->
<a href="/files/test.pdf" download="test.pdf">Download test.pdf</a>


Saturday, March 7, 2015

Announcing .NET Native Preview

We’re thrilled to announce the first release of .NET Native. Windows Store apps start up to 60% faster with .NET Native and have a much smaller memory footprint. Our first release is a Developer Preview that allows you to develop and test apps with this new compiler. This preview release of .NET Native offers you the performance of C++ with the productivity of C#. .NET Native enables the best of both worlds!




















我學 Machine Learning 的方法


讀 Data mining 的書

一開始我讀 data mining 之類的課本、講義,發現內容講得滿概念的。但若只是想拿 ML 來用,那看這類文件會比較容易上手。比方 Introduction to Data Mining 寫得挺不錯的,可謂深入淺出!官網附的投影片挺棒的,可以先「快速」 (相對於看書來說……) 看一遍,再挑有興趣的部份閱讀課本。若有耐性慢慢讀完課本,會較有系統性地認識相關內容。由於碩論做 clustering 的緣故,我有好好地讀書本 clustering 部份。不過 clustering 論文種類多到爆炸,看完這本的內容也只是苦痛的開始而已……。


若想進一步了解 model 的原理,那就需要讀 ML 課程用的課本和講義。這類文件滿多的,其中我強力推薦 Andrew Ng 教的 Stanford CS229 Machine Learning。大部份教材在講解 model 最關鍵的數學時,只會從天空掉下來一句「套用 gradient ascending 求最大值」、「運用 EM 求最佳值」之類的話,接著結果就神奇地飛出來。這份講義卻從最基礎的數學開始講,包含需要用到的微分、線性代數、機率等,讓讀者有能力自己從頭推導數學算式,算是 ML 文件裡最親切的教材。當然,讀者也要有興趣慢慢地啃才行。我大概啃了一半多一點內容,收獲良多。可惜久一沒用也只記得概念了。有機會想再從頭自己推導一次。我覺得 Andrew Ng 數學寫得相當漂亮,這是我第一次察覺寫數學式和寫程式一樣,也有美醜、易懂難懂之分。附帶一提,當初會看這份教材是看 Mr. Saturday 推薦才讀的,感謝 Mr. Saturday 推薦。
後來我陸續看了一些不同國外大學的 ML 課程講義,發覺大家的切入點差很多,各有不同考量。像 MIT OCR 6.867 Machine Learning 有教 HMM,Stanford CS229 沒教。A Fundamentalist Organization of Machine Learning 提到由 Learning theory 的方式切入 ML,而不要走馬看花講一堆 model (作者稱為 “zoo approach”,挺傳神的譬喻)。我只有從 Andrew Ng 的講義裡讀了一點 learning theory,懂些基本觀念 (bias 和 variance),感覺挺有用的。若對 learning to theory 有興趣,印象中該文作者有推薦 15-859(B) Machine Learning Theory,Spring 2009。我看了一晚講義,內容是從簡單的假設環境中推導出明確的性質,還挺有趣的。但看到後來就看不懂了,也不明白能做什麼,就沒繼續看了。

讀 Wikipedia

此外,我發覺 Wikipedia 是學東西的好地方。有代表性的方法早已有系統地記錄下來,又提供詳細的參考資料可以一路讀下去。比方說想學 Linear classifier ,比起查書,查 Wikipedia 更有效率。我常拿 Wikipedia 內容和其它文件交叉對照,弄明白看不懂的部份。讀這些東西需要的是耐心以及不傷眼的 Wikipedia CSS 樣版


後來又看到 Mr. Saturday 提到 Elements of Statistical Learning: data mining,inference,and prediction. 2nd Edition.,而且官網還有附完整電子書,就載來看看。不得不說這本書數學超硬,但內容超級紮實,相當值得一讀。我挑有興趣且讀得下去的部份加減看,學到 bagging、random forest 等東西,讓我擴展眼界,明白許多原理。除數學太硬之外,這本書另一問題是實驗資料太小了,令人懷疑實驗結果是否適用於真實世界的情況。只好先暫時相信大師,之後再從實驗中確認。
有興趣的話可以在 Amazon 查一下其它書,或以這本書為底看相關書籍。ML 有不少經典書籍,也有針對影像處理或文字處理的。


O’Reilly 出的 Programming Collective Intelligence - O’Reilly Media 也是不錯的書,適合初學者閱讀。配合使用情境,作者簡單地解釋 model 的概念並用 Python 說明如何實作。最令人讚賞的是,作者還有比較各個模型的優缺點。雖然分析的內容不見得正確,對初學者來說挺受用的。


讀這些理論時,我發覺有許多文件提供不同的講解方式,可以多比較一番,找自己看得懂的。不用刻意從某個地方學會某種 model。文中提的是我學習的歷程,每個人的需求不同,數學底也不同,我的經驗不見得適用於其他人。寫在這裡供大家做個參考,有錯還請告知,感謝。


學習和開發 Python 的好幫手

慣用 IDE 的人會推 Eclipse + PyDev, 網路上有不少教學文章。我則是慣用 VIM IPython

這裡有我針對 Python 設的 vim 設定檔, 有興趣用的人可以撿需要的部份用, 或是直接複制整個 .vim 和 .vimrc 也行 (若你原本沒設 .vim 和 .vimrc):

$ git clone git://
$ cp -r configs/.vim ~
$ cp configs/.vimrc ~

推薦讀 IPython Tip Sheet 學習使用 IPython, 花個十分鐘將可獲得兩倍以上的學習速度。我常最用的指令是 ? 和 ??, 分別會秀出物件 (函式) 說明和原始碼。它的運作原理很簡單, 因為在 Python 的世界裡, 所有東西都是物件, 而物件的 __doc__ 欄位存有文件, __file__ 欄位則存有載入的檔案路徑。因此 IPython 可以輕易地讀入文件和原始碼。

如此一來, 在 screen 裡開兩個 terminal, 一個開 IPython; 一個開 VIM。想試什麼簡單程式就在 IPython 裡試, 有疑問就用 ? 和 ?? 查。在 VIM 裡可按 F10 執行內容, 方便試較長一些的程式。實際開發時則在 VIM 裡切兩個視窗, 一個寫 unit test, 一個寫 software-under-test。在 unit test 的視窗裡按 F10 執行程式, 有錯就切到 software-under-test 的視窗改。若有錯不知錯在那想了解物件內容, 則在 unit test 裡呼叫 IPython [1], 進入 IPython 內了解詳情, 寫起來很有效率。


學 Python 的入門書

我在學 Python 前已學過別的程式語言,所以想找針對已學過程式的人的書。一開始翻許多人推薦的《Learning Python》,發現它是針對沒學過程式的人,有太多篇幅在介紹基本觀念 (如 if 是什麼 ),翻沒幾頁就沒耐性看下去。而《Programming Python》又太厚了,於是找別本書。
後來 Scott 推薦我看《Python Essential Reference》 (目前出到第四版,包含 Python 2.6 的新功能),我一看就驚為天人,「if、elif、else」只有一頁!內容包含完整語法,以及特殊情況 ( 若 if 之後想放空的 statement ,要用 pass )。沒錯,這就是我要的書,去蕪存菁地讓讀者立即掌握 Python 的語法。附帶一提,Scott 明明已學會了,竟然還買了一本用來傳教,真是面惡心善的好學長。
看完這本後,有時查些 Python 觀念或函式名稱,發現常連到《Dive into Python》,才發覺這本也滿有名的,而且還有完整免費的網頁版。於是又找時間看了《Dive into Python 3》,順便了解 Python 3 有啥有趣的東西。發覺這本書超合我胃口,直接用完整的例子說明語法,在學到語法的同時,也明白怎麼實際使用這些語法。有些書就像辭典一般,提了很正式的語法,讀起來很累,讀完卻不知能怎麼用它們。《Dive into Python 3》不但用生動的實例避免這個問題,並進一步深入淺出地介紹運作細節。而且還提到如重構、單元測試等寫軟體的重要觀念,又有詳細的 Python 2 和 3 的比較。若只對 Python 2 有興趣也沒關係,大部份語法仍適用於 Python 2.6 (2.6 是承接 Python 2 和 3 的橋樑)。
總結來說,若你沒學過程式語言,我不知道能推薦什麼書藉。或許可以參考《Python Programming: An Introduction to Computer Science》,這是 MIT 6.00: Introduction to Computer Science and Programming 的參考書,該課程用 Python 教沒寫過程式的學生學會電腦科學家的思考方式。若有學過程式語言,《Python Essential Reference》或《Dive into Python 3》都值得一看。除了學會 Python 之外,兩者提供不同的額外內容,都看也不會浪費時間。


學會 Python 基本語法後,可以先看這幾篇了解如何寫出更道地的 Python。道地的 Python 程式不但易讀、易維護,通常也表示更有效率:
再來,可以到《Python Essential Reference》作者 David Beazley 的網站挖寶,像是:
另外若對 design patterns 有興趣,可以看 Google 員工 Joe Gregorio 寫的(The Lack of) Design Patterns in Python
《Python Cookbook》也有不少經典寫法,不過該書有點舊了 (到 Python 2.4),有些方法已用不到,看的時候要挑一下。
原以為延伸閱讀應該沒多少東西,沒想到我拉拉雜雜也看了不少文件,整理到後來就累了。不知何時 Python 才會像 Java 有本《Effective Python》,一本搞定大部份的注意事項和經典寫法。



Python 的特別之處 (1)

從新手的眼中來看 Python,比較能看出 Python 和其它語言不同之處。最近有機會幫別人快速上手 Python,就順便整理一下我從中發覺 Python 較為突出的優點。

list、dictionary and string

平時 coding 最常用到的 container 就是 list 和 dictionary,另外也會常用到字串操作,Python 提供方便的方法來操作它們。string 可看成一個有實作 list 介面的類別,一些常用操作像是 slice:"abcd"[1:3] 回傳 "bc";負數的索引: "abcd"[-1] 回傳 "d";直接和 for-loop 整合在一起:
In [1]: for ch in "abcd":
  ....:         print ch


使用 iterator 比傳統的 for (i=0; i 來得清楚,Python 針對 iterator 下了不少工夫,提供好用的輔助函式,像是 enumerate 補足需要用到 index 的情況:
In [2]: for i, n in enumerate([1, 3, 5]):
  ....:     print i, n
0 1
1 3
2 5
使用 zip 整合多個 list:
In [3]: names = ["John", "Marry", "Tom"]
In [4]: sexes = ["Male", "Female", "Male"]
In [5]: for name, sex in zip(names, sexes):
  ....:     print name, sex
John Male
Marry Female
Tom Male

map, filter and reduce

任何使用過 map 的人,都會喜歡 map 輕巧的用法,來看幾個例子:
In [1]: map(int, ["12", "37", "999"])
Out[1]: [12, 37, 999]
In [2]: map(str, [12, 37, 999])
Out[2]: ['12', '37', '999']
int 是一個函式,將傳入的物件轉成整數;str 則是轉成字串。使用 map 可以將一個 iterator 轉為另一種 list。
另一個常見的情境是,從一個 list 裡篩選出需要的物件,比方說只留下偶數:
In [1]: numbers = [1, 2, 3, 4, 5]
In [2]: filter(lambda x: x % 2 == 0, numbers)
Out[2]: [2, 4]
或像 filter(lambda s: s.endswith('.py'), file_names) 只留下結尾為 ".py" 的字串。
除 map 和 filter 的重心放在轉換 list 之外,reduce 則是將 list 匯整成一個物件。有了這些函式,就能任意的操作 list,用以匯整或擴散資料容器。
In [1]: numbers = [1, 2, 3, 4, 5]
In [2]: reduce(lambda x, y: x + y, numbers, 0)
Out[2]: 15
上面這個例子可以用內建的 sum 取代,來看另一個複雜點的例子,將一串 0、1 值合成一個整數:
In [1]: bits = [0, 1, 0, 0, 1]  # bits[i] 的值表示 2^i 的系數

In [2]: reduce(lambda x, (i, b): x | (b << i), enumerate(bits), 0)
Out[2]: 18

list comprehension

map 和 filter 雖然方便,要用到 lambda 或是混合使用時就沒那麼好讀了。Python 提供一個重量級的武器 list comprehension 來解決這問題。比方說留下偶數並乘以三再加一:
In [1]: numbers = [1, 2, 3, 4, 5]

In [2]: [n * 3 + 1 for n in numbers if n % 2 == 0]
Out[2]: [7, 13]
綜合以上的語法,可以輕鬆地寫出易懂的 quick sort
def qsort(numbers):
    if len(numbers) <= 1:
        return numbers                                                                                     
    pivot = numbers[0]
    rest = numbers[1:]
    smaller = [n for n in rest if n <= pivot]
    larger = [n for n in rest if n > pivot]
    return qsort(smaller) + [pivot] + qsort(larger)
對於習慣 C、C++、Java 世界的人來說,應該不曾看過這麼直覺易懂的quick sort 吧。


tuple 是一個很妙的資料結構,它和 list 的主要差別是它是唯讀的,Python 裡鮮少有這種唯讀物件。不過它較易發覺的好處是被用在 Python 的parallel assignment 和函式傳回值。
於是在 Python 裡可以這麼寫:
a, b = b, a # swap
Python 在看到 b, a 時會產生一個 tuple 表示 (b, a),再透過 tuple 達到parallel assignment
In [1]: def divide_and_mode(a, b):
   ...:     if b == 0:
   ...:         return None, None
   ...:     return a / b, a % b

In [2]: divide_and_mode(7, 3)
Out[2]: (2, 1)

In [3]: a, b = divide_and_mode(7, 3)

In [4]: a
Out[4]: 2

In [5]: b
Out[5]: 1
原理一樣是先轉成 tuple 再傳回,再視等號左側放什麼,決定要存成 tuple 或做 parallel assignment

2012-01-25 更新



在 Python 2.6 後,支援用 with 管理資源。像讀檔案可以用 with 的方式寫:
# 印出所有使用者的 id
with open('/etc/passwd') as fr:
    for line in fr:
        print line.split(':')[0]  
在進入 with 的 block 前,會呼叫 file object 的 __enter__ 以獲得 file descriptor;在離開 block 前會呼叫 __exit__ 關掉 file descriptor。即使中間呼叫了 sys.exit() 或丟出 exception,仍會執行到 __exit__,不用擔心會漏關。方便用在許多情境 (比方說 lock / unlock、自動 flush output buffer),易讀易用。


除上述的基本資料結構和 string 外,還有 sqlitejson等。


舉幾個寫 C 可能發生的問題,但在 Python 的語法下則不會發生:
if (condition);
    // BUG!! 這裡的程式一定會被執行
if (x < 60)
    total_fail_score += x; // BUG!! 這行每次都會執行
另外,由於 Python 的 condition 只能是 expression,不能是 assignment。不會有 if (x -= 3 < 0) 這種 bug。


了解 C/C++ 程式行為的技巧

下面以了解 C/C++ 程式為主,列出自己一些零散心得。


加入程式 log function call 是直接有效的作法,而且做起來不如想像的麻煩,詳見 《trace C/C++ function call 的方法》
或是找看看前人是否有了下除錯的 flag。有經驗的程式設計師在開發時必定有一套除錯方式,只是在正式使用時關掉了這些除錯功能,詳見《C/C++ 檢查和打開 debug 功能的小技巧》
附帶一提,自己開發程式時,除了留下除錯程式之外,記得要考慮使用 gdb 的影響,讓除錯程式更易於使用,詳見 《除錯小技巧: 在程式中直接中斷及偵測是否被 gdb 監控中》
程式碼通常會用到第三方函式庫,有時我們可以從中得知一些線索,《python BaseHTTPServer 速度緩慢的原因》是一個簡短的例子,說明如何使用 ltrace 找出關鍵的第三方函式,繼而找出效率瓶頸。使用 ltrace 無須重編程式或加入 debug symbol。不過有可能讓程式變得不穩定,這時可使用 -l filename 只觀察部份函式庫,執行的時候會比較穩定一些。
其它兩則和 ltrace 相關的例子:
觀察使用的 system call
system call 是程式和 kernel 溝通的途徑,介面數量相對少,容易集中觀察。有時藉由觀察 system call 夾帶的參數,可以提供一些線索。比方說,不論上層函式如何包裝,開啟檔案最後會用到 open(),可以從 open() 的參數 找出程式目前使用的設定檔或 log 檔位置。或是像《用 strace 找出 Ubuntu 如何提示未安裝的指令》,使用 strace 觀察 system call 直接解答疑惑。
和 ltrace 一樣,無須重編程式也不用 debug symbol。更棒的是,使用 strace() 執行程式還滿穩定的。
其它 strace 相關的例子:
使用 gdb
debugger 的重要性無須多言,《gdb 初步心得》條列我常用到的指令。另外值得一提的是,有 core dump 的時候,core dump 裡一定會記錄產生 segmentation fault 的 thread,不用擔心找錯 thread,原因見《linux thread 與 signal》
編譯上線的程式時,多數會加上 -O2 最佳化效能,讓程式實際執行的狀況和程式碼有些出入。雖然如此,仍然可以加上 -g 觀察程式的 core dump,但要留意觀察的結果不見得是對的,詳見《debug info 和 optimization》。平時觀察程式行為還是用 -O0 -g 編譯較適當。
以下是其它和 gdb 相關的小技巧:
從 kernel 切入
有些情況下我們沒辦法從程式內部或 gdb 取得資訊,比方說程式莫明奇妙地收到 SIGKILL 而結束。由於程式無法攔截 SIGKILL,不方便查出凶手是誰。雖然可以在相關程式內直接對 system call kill() 設中斷點,但若凶手是外部程式,就沒輒了。
這種時候可用 SystemTap 直接從 kernel 內觀察是什麼程式請求使用 kill 送出 SIGKILL。我自己還沒有第一手經驗,這個例子是從同事那邊學來的,在這裡備忘觀察程式時,還可以用 SystemTap 觀察更底層的行為。


《配合 c++filt 讀程式》說明如何從執行檔中找關鍵字,可藉此找出 UI 相關字串或是可能的函式名稱,有時比直接從程式碼下手容易。
找出 symbol 的定義或使用到 symbol 的程式碼
C 的情況比較單純,相關工具比較正確,也有工具可以產生精美的 call graph。但 C++ 的情況複雜許多,最後我決定無視 C++ 語法,直接找出所有和目標 symbol 有關的程式。《閱讀 C/C++ 原始碼的好幫手》有整理相關工具, 《查 C/C++ symbol 定義的方法》有一點關於我使用 gj 的方法。
使用 doxygen 產生 class 階層關係圖
大型專案會依功能切成數個模組,模組本身亦有一套自己使用 class 的方法。直接看程式碼容易陷入見樹不見林的困境。這時可用 class 階層關係圖協助了解整體架構。產生階層圖的方式見《用 doxygen 產生 class hierarchy diagram》。再輔以 gdb 產生 backtrace 觀察類別、模組之間的使用關係,比較容易明白整體架構。
善用編輯器或 IDE
目前是逐步學習如何強化用編輯器或 IDE 讀程式,加快在相關程式碼中探索的時間,還沒整理出一套完整的流程。
比方說用 gj 跳到某個使用函式 foo() 的檔案後,再來我會想知道目前在那個函式裡,《vim 顯示目前函式的名稱》就是針對此情境在 vim 內加了快速鍵做這這件事。或是像《使用 vim script 自動開啟 C/C++ 程式的標頭檔或程式碼》說明如何在 .h 檔裡按 F4 快速開啟 .c 或 .cpp 檔,或是反過來在 .c 或 .cpp 裡開啟 .h。
理解到了解程式是如此不容易後,行有餘力時,別忘了加強測試碼,讓日後使用相關程式的人更快進入狀況。良好的 unit tests 也是不錯的使用範例,有助於了解模組的行為。


2014-01-05 更新。


What is SGID and how to set SGID in Linux?

This is next to SUID in our ongoing Linux file and folder permissions series. We already discussed about CHMOD, UMASK, CHOWN, CHGRP, SUID, StickyBit and SUDO concepts in our previous posts. In this post we will see

What is SGID?

Why we require SGID?

Where we are going to implement SGID?

How to implement SGID in Linux?

What is SGID?

SGID (Set Group ID up on execution) is a special type of file permissions given to a file/folder. Normally in Linux/Unix when a program runs, it inherits access permissions from the logged in user. SGID is defined as giving temporary permissions to a user to run a program/file with the permissions of the file group permissions to become member of that group to execute the file. In simple words users will get file Group’s permissions when executing a Folder/file/program/command.

SGID is similar to SUID. The difference between both is that SUID assumes owner of the file permissions and SGID assumes group’s permissions when executing a file instead of logged in user inherit permissions.

Learn SGID with examples:

Example: Linux Group quota implementation

When implementing Linux Group quota for group of people SGID plays an important role in checking the quota timer. SGID bit set on folder is used to change their inherit permissions to group’s permissions to make it as single user who is dumping data. So that group members whoever dumps the data the data will be written with group permissions and in turn quota will be reduced centrally for all the users. For clear understanding of this you have to implement group quota from the above link. Without implementation of SGID the quota will not be effective.

How can I setup SGID for a file?

SGID can be set in two ways

1) Symbolic way (s)

2) Numerical/octal way (2, SGID bit as value 2)

Use chmod command to set SGID on file: file1.txt

Symbolic way:

chmod g+s file1.txt

Let me explain above command we are setting SGID(+s) to group who owns this file.

Numerical way:

chmod 2750 file1.txt

Here in 2750, 2 indicates SGID bitset, 7 for full permissions for owner, 5 for read and execute permissions for group, and no permissions for others.

How can I check if a file is set with SGID bit or not?

Use ls –l to check if the x in group permissions field is replaced by s or S

For example: file1.txt listing before and after SGID set

Before SGID set:

ls -l

total 8

-rwxr--r-- 1 xyz xyzgroup 148 Dec 22 03:46 file1.txt

After SGID set:

ls -l

total 8

-rwxr-sr-- 1 xyz xyzgroup 148 Dec 22 03:46 file1.txt

Some FAQ’s related to SGID:

Where is SUID used?

1) When implementing Linux group disk quota.

I am seeing “S” ie Capital s in the file permissions, what’s that?

After setting SUID or SGID to a file/folder if you see ‘S’ in the file permission area that indicates that the file/folder does not have executable permissions for that user or group on that particular file/folder.

chmod g+s file1.txt

-rwxrwSr-x 1 surendra surendra 0 Dec 27 11:24 file1.txt

so if you want executable permissions too, apply executable permissions to the file.

chmod g+x file1.txt

-rwxrwsr-x 1 surendra surendra 0 Dec 5 11:24 file1.txt

you should see a smaller 's' in the executable permission position.

How can I find all the SGID set files in Linux/Unix.

find / -perm +2000

The above find command will check all the files which is set with SGID bit(2000).

Can I set SGID for folders?

Yes, you can if it’s required (you should remember one thing, that Linux treats everything as a file)

How can I remove SGID bit on a file/folder?

chmod g-s file1.txt