2010年11月14日 星期日

馬雲演講

記得是碩一上時,熱情的同學常邀請我去他寢室聽聽不錯的商業演講或影片,但之後我反而比較常專注在程式或是實作一些小品,很久沒聽聽或看看了。


馬雲是阿里巴巴的創辦人,在 Youtube 上看了幾則他的演講。從他的言論上,讓我有很深的體會,剛好可以驗證目前待過了兩間公司,一間是研究所這間公司,一間是財團法人非營利為主的公司。兩間很微妙的角色,恰恰好呼應很多談話內容,想起來這樣的機會還真不容易。


在碩班時,的的確確享受到「競爭是最大的快樂」,所謂的競爭不是多偉大多美好的議題,而是很簡單得問題,用最細密的思緒來處理,我喜歡這種簡單的小生活,而不是因為競爭把彼此的情緒搞得很難看;在財團法人的公司時,反而常常為了避免競爭,需要搞一個沒人想過的題目,除了搶有錢的計畫吧!這是兩者最大的不同,前者是想把事情做得更好,後者則是為了當個贏家,只想挑別人沒做過的事來搞。很不一樣的生活環境吧!


馬雲的演講很生活化,但我很喜歡這樣的論點,用平凡的人做非凡的事!我喜歡這種說法。我看的書很少,但也因此會很深刻,記得國中看過的一本書,諸葛亮的人生哲學,裡頭正是談論到用人的問題,人都有缺點,用其長避其短,但真正能做到的微乎其微。每次看到應徵的相關議題,要嘛看不上別人的學歷,要嘛就是要考倒對方才甘願,而每位老闆都想要最強的人,卻沒想過最強的人是不是合於公司的環境,但我知道目前公司壓住強者的方式,第一是無限的上班時間,第二是薪資,讓你忙到沒時間抱怨,又讓你領錢領到遺忘自己。相較之下,平凡人是美好的。


有空看看馬雲2008年來台灣的演講吧~


完整版



































比較好的畫質:到 Youtube 上 avp48 頻道裡搜尋"馬雲"。


其他演講:























一些語錄:



  • 競爭是最大的快樂

    • 要在競爭的環境上享受快樂



  • 投資者是舅舅,孩子的父親是你

    • 給錢的是舅舅,但真正要執行的卻是你自己,用來說明創投跟公司執行者的關係



  • 大象是搞不死螞蟻的

    • 大公司與小公司的差別,總會有生路的




2010年11月10日 星期三

安裝 Hadoop 0.20.2 Multi-Node Cluster @ 異質環境

關於安裝的細部流程,請參考



大概瀏覽一下這兩篇,應該可以稍稍了解架設 Hadoop 的過程。


在這邊要玩的是將 Hadoop 架設在異質環境中,手邊有以下的機器:



  • 64-Bit, FreeBSD 8 x 2

  • 32-Bit, FreeBSD 7 x 1

  • 64-Bit, Linux x 2


共五台機器,並使用 Hadoop-0.20.2 ,理由純粹是擔心 0.21.0 設定檔有更新,自己還沒追到 :P


以上台機器有一個共同點:



  • 使用 NFS 掛載使用者家目錄


加上 Hadoop 是跑在 User Mode 的環境,因此我不需要太多的管理權限(軟體不存在?那就用 tarball 安裝),只需留意使用的 port number 是否已被使用,最多則是 /tmp 目錄是否可以使用吧!


緊接著,我開始嘗試在 FreeBSD 環境上安裝!第一個碰到的問題是 jdk 的部份!幸運地發現有人在維護 jdk ,而機器上面也有安裝 jdk,但為了求 Hadoop 的設定檔可以一致性,我下載了適用於 FreeBSD jdk,可以在這邊下載:



另外 Linux 部份則是直接到 Sun 下載:



如此一來,我在我的家目錄建立一個 hadoop 目錄並擺上上述的目錄結構,並把一些 jdk 目錄多了 32bit 和 64bit 的字樣


# ls -l ~/hadoop
diablo-jdk1.6.0_07_32bit/
diablo-jdk1.6.0_07_64bit/
hadoop-0.20.2/
jdk1.6.0_22_32bit/
jdk1.6.0_22_64bit/


接著才是進入環境的設定:



  1. 建立 SSH 登入免帳號

    • # ssh-keygen -t rsa -P ''
      # cat ~/.ssh/id_rsa.pub > ~/.ssh/authorized_keys 

    • 由於上述幾台機器都透過 NFS 彼此相連,因此只需在一台機器上操作,其餘的就沒問題,可以用 ssh 登入 locahost 和各台機器試試,應該不用輸入密碼即可登入。請務必先用 ssh 登入各台機器,讓機器記錄相關初始化的資訊。



  2. 設定各台 /ets/hosts 資訊

    • 通常有提供 NFS 服務的機器都算已經有加好了,例如:
      192.168.56.168  bsd1
      192.168.56.169  bsd2
      192.168.56.170  bsd3
      192.168.56.171  linux1
      192.168.56.172  linux2

    • 如果要加的話,就變成要有管理者權限,不加應該可以純用 IP 試試。請記得描述不要用到 '_' 唷,如 bsd_32bit,已經有兩人跟我分享過這樣會連不到機器



  3. 設定 Hadoop 相關檔案

    • 由於我將 hadoop 安裝在 ~/hadoop/hadoop-0.20.2 裡頭,因此我的設定檔是在 ~/hadoop/hadoop-0.20.2/conf 中

    • 設定 conf/hadoop-env.sh


      • 由於是異質環境,因此我要多判斷環境來挑選 jdk 使用。加在第 10 列左右

        • FLAG_AMD64=`uname -a | grep -i -c 'amd64'`
          FLAG_X86_64=`uname -a | grep -i -c 'x86_64'`
          FLAG_FREEBSD=`uname -a | grep -i -c 'FreeBSD'`
          FLAG_LINUX=`uname -a | grep -i -c 'Linux'`

          if [ $FLAG_AMD64 = 1 ] || [ $FLAG_X86_64 = 1 ]; then
              if [ $FLAG_FREEBSD = 1 ]; then
                  export JAVA_HOME=/home/user/hadoop/diablo-jdk1.6.0_07_64bit                
              elif [ $FLAG_LINUX = 1 ]; then
                  export JAVA_HOME=/home/user/hadoop/jdk1.6.0_22_64bit                
              fi
          else
              if [ $FLAG_FREEBSD = 1 ]; then
                  export JAVA_HOME=/home/user/hadoop/diablo-jdk1.6.0_07_32bit                
              elif [ $FLAG_LINUX = 1 ]; then
                  export JAVA_HOME=/home/user/hadoop/jdk1.6.0_22_32bit                
              fi
          fi



      • 設定停用 IPv6,過去經驗因為沒有加這個設定而導致機器彼此連不到,可以依自己的環境多測試,或許已經可以不用加了。加在第 50 列左右


        • HADOOP_OPTS=-Djava.net.preferIPv4Stack=true





    • 設定 conf/core-site.xm

      • 設定 NameNode 擺在哪一台機器,挑強一點的吧!在此挑 bsd1 和使用 9000 port,請自行確認 9000 可否使用

      • <?xml version="1.0"?>
        <?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
        <!-- Put site-specific property overrides in this file. -->
        <configuration>      
                <property>   
                        <name>fs.default.name</name>
                        <value>hdfs://bsd1:9000</value>
                        <description>The name of the default file system. A URI whose
                        scheme and authority determine the FileSystem implementation. The
                        uri's scheme determines the config property (fs.SCHEME.impl) naming
                        the FileSystem implementation class.  The uri's authority is used to
                        determine the host, port, etc. for a filesystem.</description>
                </property>  
        </configuration>



    • 設定 conf/mapred-site.xml

      • 設定 job tracker,在此挑 bsd1 和 9001 port,請自行確認 9001 可否使用

      • <?xml version="1.0"?>
        <?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
        <!-- Put site-specific property overrides in this file. -->
        <configuration>
                <property>
                        <name>mapred.job.tracker</name>
                        <value>bsd1:9001</value>
                        <description>The host and port that the MapReduce job tracker runs
                        at.  If "local", then jobs are run in-process as a single map
                        and reduce task.
                        </description>
                </property>
        </configuration>



    • 設定 conf/masters

      • 這是 secondary namenode,預設是 locahost,可以改成指定成另一台機器,例如 bsd2 等,由於我目前不想要 secondary namenode,因此把這個檔案清空



    • 設定 conf/slaves

      • 設定 datanode 的機器,以原先的架構,就 bsd1 當 namenode,其他當 datanode,因此可以依序填入 bsd2, bsd3, linux 等機器,但由於我想要讓 bsd1 也加入運算的環境,因此最後我的設定是有四台機器,建議先一台台機器加上去,例如一開始只加 bsd2 這台機器

      • bsd1
        bsd2
        bsd3
        linux1
        linux2





  4. 啟動與測試

    • 對 NameNode 進行資料的格式化,目前以 bsd1 當作 NameNode,在 bsd1 執行以下指令


      • # ~/hadoop/hadoop-0.20.2/bin/hadoop namenode -format



    • 經同事提醒,只要在某一台機器上執行 ~/hadoop/hadoop-0.20.2/bin/start-all.sh,該台機器就會是 NameNode,因此我就選擇在 bsd1 上執行( 嘗試在 bsd2 執行結果有問題?細節還沒去追)

    • 執行完後,可以使用 jps 指令查看狀態

      • 依照目前的設定,bsd1 會是 NameNode、DataNode、TaskTracker和JobTracker,其他機器則是會有 DataNode 和 TaskTracker 的資訊

      • 請依照各機器 jdk 位置執行

        • bsd1, FreeBSD 8 64-bit

          • # ~/hadoop/diablo-jdk1.6.0_07_64bit/bin/jps





        • bsd3, FreeBsd 7 32-bit


          • # ~/hadoop/diablo-jdk1.6.0_07_32bit/bin/jps





        • linux 64-bit

          • $ ~/hadoop/jdk1.6.0_22_64bit/bin/jps







    • 另一種查看方式

      • # ~/hadoop/hadoop-0.20.2/bin/hadoop dfsadmin -report

      • 將會成列出目前的 DataNode 狀態,以上述的設定將會有 5 個 DataNode (conf/slaves中所呈列的)



    • 如果執行上有問題,例如某台機器沒跑起來,可以試著用 stop-all.sh 和 start-all.sh 來重跑看看,機器並不是每次跑都成功的 XD

    • 測試 wordcount

      • # ~/hadoop/hadoop-0.20.2/bin/hadoop fs -mkdir input
        # ~/hadoop/hadoop-0.20.2/bin/hadoop fs -put ~/hadoop/hadoop-0.20.2/README.txt input/
        # ~/hadoop/hadoop-0.20.2/bin/hadoop jar hadoop-0.20.2-examples.jar wordcount input output

      • 印出結果
        # ~/hadoop/hadoop-0.20.2/bin/hadoop fs -ls output/
        # ~/hadoop/hadoop-0.20.2/bin/hadoop fs -cat output/part-r-00000






經過上述的設定,輕鬆地整合異質環境!其中 FreeBSD 跑 Java 的部份,可能因為各台機器已經有作過 Java 相關環境的設定,因此並沒碰到啥大問題!除此之外,由於 Hadoop 算是只要 user mode 的權限就可以執行,再加上許多學校的機器都是使用 NFS 掛載家目錄進來的,看來,這樣惡搞下去,學校的 SA 要 QQ 了(附帶一提,光 ~/hadoop 目錄就已經 927MB 了!此方式僅適用於沒有設 quota 的機器啊啊)。至於加減機器的方式,多虧 NFS 的關係,只須修改 conf/slaves 的資料,多一台就加一筆,少一台就減一筆,然後在從 NameNode 透過 start-all.sh 和  stop-all.sh 就可以啟動囉!以前都在 VirtaulBox 上架機器,第一次覺得加減機器的設定是如此的方便有爽感,這大概算是自己架過最多台實體機器的一次吧!


2010年11月2日 星期二

驗證 MSN 使用明文傳遞聊天內容

msnms


記得幾年前大學專題也在玩 MSN ,當時只大概了解有幾種 M$ Server 負責一些事情,也久聞 MSN 是傳送明碼,但一直沒有仔細確認,剛好想到就使用 Wireshark 測試一下。


測試環境:


Ubuntu 10.10 x86_64 + Pidgin 2.7.3 + Wireshark 1.2.11


使用上就只要把 filter 設成 msnms 就可以看到一連串的資訊,上例挑選一則從 MSN Server 傳來的訊息,代表某人丟訊息給我,而後面幾個 bytes 就是聊天內容:


訊息


e4 bd a0 e6 83 b3 e9 81 b8 e4 bb 80 e9 ba bc ef bc 9f


使用 Python 驗證:


#!/usr/bin/python
if __name__ == "__main__":
        print "\xe4\xbd\xa0\xe6\x83\xb3\xe9\x81\xb8\xe4\xbb\x80\xe9\xba\xbc\xef\xbc\x9f"


結果:


你想選什麼?


我想應該不用解釋吧?轉出來的文字是可讀的,因此的確沒有加密處理。所以,人在外頭,一些敏感字眼還是少用 MSN 傳遞吧!


2010年11月1日 星期一

免費軟體 - 使用 GIMP 和 XnView 去背景顏色(透明背景)

一時之間找不到去背景的免費工具,試過了 XnView 但效果不好,最後想起安裝過 GIMP,翻了一下終於找到了!


我是要把一張 PNG 檔案的圖,把白色的背景去掉,但由於圖中間又有用到白色,導致使用 XnView 去背景時,想要留下的部分會被清掉,解法就是把真正要去背景的部分,先用另一種顏色填補,再挑該顏色去背景。


XnView


xnview



  • 影像(i) -> 編輯色彩圖(Ctrl+M) -> 挑選你要的顏色 ->啟用透明效果 -> 確定

  • 好像僅適用於 GIF 檔案


GIMP


gimp



  • 圖層(L) -> 透明度(A) -> 色彩轉成透明(A) -> 挑選你要的顏色 -> 確定

  • 可先先把想要轉成透明的部分,使用某個不在該圖顏色填滿,如黑色,再使用上述的步驟挑選黑色來轉換


[Javascript] 模仿 Monocle 分頁效果之簡單的 HTML 閱讀器

Monocle 是一套 Javascript 電子書閱讀器,以 EPUB 格式結構作為設計,使用方式不是餵給他一個 EPUB 檔案,而是依照 Monocle 所定義的資料進行實做,例如某個 function 要回傳書目,這類似於 EPUB 裡的 OPF content file 或 Spine file 等,另外還要實做一個回傳指定章節的內容,如問你第一章時,要回傳第一章整個 XHTML 內容等,以此做出豐富的閱讀效果。


關於翻頁效果,可以參考這篇 [Javascript] EPUB Reader 翻頁效果的原理,在此就仿照 Monocle 的分頁效果,使用 jQueryCSS Multi-column Layout Module (W3C Candidate Recommendation 17 December 2009) 實作簡單的 HTML 閱讀器,順便筆記一下。


程式碼 - index.html:


<!DOCTYPE html>
<html xml:lang="utf-8" lang="utf-8" xmlns="http://www.w3.org/1999/xhtml">
        <head>
                <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
                <meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;"/>
                <script type="text/javascript" src="http://code.jquery.com/jquery-1.4.3.min.js"></script>
                <LINK REL="StyleSheet" HREF="style.css" TYPE="text/css"/>
                <script type="text/javascript">
                        try{
                                console.log( '' );
                        }catch(err){
                                console = {}
                                console.log = function(){}
                        }
                        var page = 1;
                        $( document ).ready( function() {
                                $( '#info' ).hide();
                                $( '#tools' ).hide();
                                $( '#touch_menu' ).click( function(){
                                        var obj;
                                        obj = $( '#info' );
                                        if( obj.is( ':visible' ) )
                                                obj.hide();
                                        else
                                                obj.show();

                                        obj = $( '#tools' );
                                        if( obj.is( ':visible' ) )
                                                obj.hide();
                                        else
                                                obj.show();
                                } );
                                var window_width = $(window).width();
                                $( '#show' ).width( window_width);
                                $( '#content' ).css( '-moz-column-width' , window_width );
                                $( '#content' ).css( '-webkit-column-width' , window_width );
                                $( '#touch_next' ).click( function(){
                                        var obj = document.getElementById( 'show' );
                                        var tmp = obj.scrollLeft;
                                        obj.scrollLeft += $( '#show' ).width();
                                        if( tmp == obj.scrollLeft )
                                                getPage( ++page );
                                } );
                                $( '#touch_prev' ).click( function(){
                                        var obj = document.getElementById( 'show' );
                                        if( obj.scrollLeft > 0 )
                                        {
                                                obj.scrollLeft -= $( '#show' ).width();
                                        }
                                        else if( page > 1 )
                                                getPage( --page , true );
                                        else
                                                obj.scrollLeft = 0;
                                } );
                                getPage( page );
                        } );


                        function getPage( page , be_last )
                        {
                                $.ajax({
                                        //
                                        // url 為 EPUB 檔案解壓縮後,章節檔案的位置
                                        // 此例剛好章節檔名是 chapter1.html ~ chapter100.html
                                        // 因此翻頁就只是類似從 chapter1.html 換到 chapter2.html 而已
                                        //
                                        url:'epub/OPS/chapter'+page+'.html', 
                                        type:'GET',
                                        async: false,
                                        success:function(data){
                                                $( '#content' ).empty();
                                                xmlDoc = new DOMParser().parseFromString( data , "text/xml" );
                                                while( xmlDoc.hasChildNodes() )
                                                {
                                                        var node = xmlDoc.removeChild(xmlDoc.firstChild);
                                                        console.log( node.nodeType );
                                                        if (node.nodeType == 1)
                                                        {
                                                                $( '#content' ).append( node );
                                                        }
                                                        else if (node.nodeType == 3 && !node.nodeValue.match(/^\s+$/))
                                                        {
                                                                var elem = document.createElement('div');
                                                                elem.appendChild(node);
                                                                $( '#content' ).append( elem );
                                                        }
                                                }
                                        }
                                });
                                var obj = document.getElementById( 'show' );
                                if( !obj )
                                        return;
                                if( be_last == undefined )
                                {
                                        obj.scrollLeft = 0;
                                }
                                else
                                {
                                        obj.scrollLeft += 999999;
                                }
                        }
                </script>
        </head>
        <body>
                <div id="container"><div id="show"><div id="content"></div></div></div>
                <div id="info"></div>
                <div id="tools"></div>
                <div id="touch_menu"></div>
                <div id="touch_next"></div>
                <div id="touch_prev"></div>
        </body>
</html>


程式碼 - style.css:


html, body {
        margin: 0;
}
#container , #show , #content , #info , #tools , #touch_menu , #touch_prev , #touch_next {
        position:absolute;
        width:100%;
        height:100%;
}
#container {
        background-color:rgba(75%, 75%,75%,0.5);
        z-index: 0;
}
#touch_menu , #touch_prev , #touch_next {
        z-index: 10;
}
#touch_menu {
        background-color:rgba(70%,70%,70%,0.5);
        width:40%;
        top:0;
        left:30%;
}
#touch_prev , #touch_next {
        width:30%;
}
#touch_prev {
        top:0;
        left:0;
        background-color:rgba(90%,90%,90%,0.4);
}
#touch_next {
        top:0;
        left:70%;
        background-color:rgba(90%,90%,90%,0.4);
}

#info , #tools {
        height:10%;
        z-index: 100;
}
#info {
        top:0px;
        background-color:rgba(0%,10%,20%,0.5);
}
#tools {
        top:90%;
        background-color:rgba(0%,10%,20%,0.5);
}
#show {
        z-index:100;
        width:1000px;
        overflow: hidden;
}
#content {
        font-size:20px;
        -moz-column-gap: 0pt; -moz-column-width: 1000px;
        -webkit-column-gap: 0pt; -webkit-column-width: 1000px;
        z-index:100;
}


使用上需要更新 ajax 那一塊,把 url 的規則修改,不然就自己擺個幾個網頁,如 chapter1.html, chapter2.html 就可以試試效果囉。


成果:


ereader
分成三塊,中間點了顯示上下兩個圖層外,可以拿來規劃成其他服務,另外,左右兩邊就只是翻頁而已。


上述程式碼大概只有 ajax 裡的 sucess function 裡的部分動作,是從 Monocle 參考修改而來的,除此之外都非常簡單,只是翻頁計算的事情。此次僅為了熟習 CSS Multi-column Layout Module 翻頁,大家要多支持 Monocle 這套閱讀器,他可還是 MIT License 的 open source!另外,還可以看到 Monocle 網站的最新消息,推出了 BOOKish 網站服務,感覺未來走向跟 ibis reader 差不多吧。