2011年8月27日 星期六

Recovery unbuntu from rsync

If you counter this " /proc/devices: fopen failed: No such file or directory".
mount the proc file system by:
mount -t proc proc /proc
And repaire the Grub2:
mount /dev/sda1/mnt/root
sudo chroot /mnt/root
mount -t proc proc /proc
grub-update
grub-install /dev/sda

2011年8月26日 星期五

養嬰兒紀錄

晚上哭鬧---肚子痛---要按摩、注意水壺
吃一下就睡著---奶嘴太小---如果喝奶量一直不多要注意奶嘴

2011年8月5日 星期五

git到底好在哪裡

我一開始使用git的時候,其實是反彈的。因為比起SVN,git實在有夠雞肋。也不能說git無用,但我真的分辨不出從SVN換到git的理由是什麼。直到有一個較有慧根的同事敎了我一些基本操作,讓git的學習曲線比較上升了以後,才漸漸發覺到git的可貴,有點覺得Linux真的造福了寫程式的人們。

git可貴在哪哩? 他是免費的..bala bala....。很多git的優點,一堆blog都有在說明,因此我用一些例子引述我覺得git好在哪裡。

狀況一:過去常使用tar的方式來切換不同版本,搞得硬碟裡一堆類似名稱的檔案,還要常用比對軟體來確認版本差異,這反而徒增錯誤的發生。

所以如果你有很多版本需要切換,直接就使用git checkout吧!很多人不懂得使用這個,是因為不常去使用git branch,以及不習慣常git commit。只要是可以打出log的改動,我都會直接commit,哪怕是只改一行。如果目前有改了一堆東西但都還沒commit,但是又要切到其他版本。可以用git stash把所有東西都先放給git管,當你作完後,再使用git stash pop把東西拿出來。這樣子,無論做什麼操作,都是在git控制範圍內,不會需要一直比對,一直確認某包src是在哪個版本,當事情一忙,錯誤就會產生。

狀況二:現在公司內,因為職務輪調,轉到其他部門。但是我過去開發的模組,如果使用SVN管理,而部門間的server又不同,怎麼辦?我的過去開發的歷史就要從此終止嗎?哭哭!


別怕,git可幫你!svn2git這個工具可以幫你把SVN管理的任一URL路徑,轉為單一的git repository。
svn2git http://path/to/svn/dir --rootistrunk
如果是想要同步SVN上面的版本到git上。就是再使用svn2git,然後在舊版本的git repository上利用git remote add 來加入新版本的remote路徑。再使用git fetch,將新版本與舊版放在一起,git會自動找尋到SVN上相同的版本然後產生一個branch。由於git不需架server,而且是分散式。無論你調職到哪裡,svn2git後都可以繼續使用你過去辛苦建立起來的東西。


狀況三:公司內部可能因為平台差異,或是客戶差異,導致分部門來處理同一份來源的code。但是常常遇到A部門與B部門出現相同問題,變成花了原本未分出部門前的2倍以上的人力在解相同的問題,讓人事成本成倍數增加同時也讓加班時數與怨念指數增加。不好好管控版本簡直就是公司衰敗的開始。


不同部門可能使用的server是不同的,甚至沒使用任何VCS。但如果都使用git,可以幫助持續的紀錄兩邊版本差異,也許有一天,兩個部門需要合併?或是project需要合併?這時後可以使用git remote add,把分出去多年的src,利用git fetch把兩條線放進同一個git repository。這樣就可以針對某個問題,使用git cherry-pick,把其他部門以解過的問題,直接利用版本層面來解決,而不需再花費更多人力進去看src來解。這樣節省的時間會非常驚人。


狀況四:我的研發團隊分工很細,介面都訂得很清楚,所以通常部門間不會有source code的開放。SVN可以用export propetise的方式連結。git該怎麼做?


git本身帶有git submodule的方式,可以把其他的repository放進來。所以可以把各部門產出的東西使用git管理,然後建置的時候可以用submodule取得各部門產出的東西。這樣子從開發到建置測試,都可以用git做管理,明確知道哪些版本是這次測試的版本。


或是也可以採用Android在使用的repo這個用python寫的工具,他利用git原本就有的hooks與一些巧妙的機制,達成可以管理很多個git,而且比submodule好用許多,我目前是使用repo來管理所有git repository的。






所以我認為git能帶來最大的優點,就是無論發生什麼事(調職、離職、畢業、server掛掉...),版本都不會再中斷了。直到很久很久以後,你都能看到自己過去開發的一切,甚至還可以繼續的開發你很久很久都沒再碰的東西。只要你採用了git,你現在開始寫的code都開始有了歷史,你就在寫自己的歷史。

2011年8月4日 星期四

2011年7月30日 星期六

寫韌體,就不需要懂軟體嗎?

軟體、韌體傻傻分不清,這個討論我相信已經討論1x年了,小弟不才,也許更久。相信時代變遷得如此快速,1x多年的老前輩應該有深深的感觸吧。但如果想知道實際上的分別,還是到wiki上詳細閱讀吧。


我想分享的是:寫韌體,就不需要懂軟體嗎?


如果問多數人,韌體工程師的工作。我籠統點說,絕大多數人會認為:"看spec操作IO的工作"、"寫MCU"、"寫一台機器的軟體,但機器看起來不像電腦",就是韌體工程師的工作,所以公司與個人也是以軔體工程師去求才或求職。所以韌體工程師的確是此類工作的代名詞。這種工作有很多的竅門與專業知識,比如說:使用示波器、邏輯分析、電表、甚至頻譜分析儀來協助工作,也要看懂電路圖,以及電子電路的常識。但是這僅止於driver的部份,也就是你的產品想要賣錢,不是只要把driver做好就可以,一定還要有軟體才能完成一個產品。

天不從人願,哪有韌體工程師只要寫driver這個好康的事?當然要繼續往上開發出功能才行阿!不然你都會C語言了,老闆當然覺得你應該可以勝任。這時你應該知道如果推辭或擺爛,那你就被打入永遠寫driver的冷宮,老闆就會再找軟體的人來取代你,或是跟你合作,你就賺不到更多錢。我奉勸此類的朋友,持續的向上學習才是王道。所以這文章也是寫給努力向上的人看的。OK,既然要合作或是學習,韌體工程師就不能置身事外。韌體工程師最終還是要關心軟體領域會發生的問題,縱使你寫的軟體是放在flash或eeprom,而變成自詡為韌體工程師,但你卻因此不繼續探索軟體領域的解決方法,這想必是緣木求魚。

韌體要coding,軟體要coding。只要是一群人合作一起coding,不管他是coding來控制硬體,還是coding來UI的,還是coding來網頁的,甚至是用嘴巴coding的,都一定會遭遇到一些問題:

  1. 版本管理
  2. debug,而且具有非常不平衡的性質。就是可能改錯1個字,或是一行,都有可能造成嚴重錯誤。
  3. 不可預測性,常常計畫趕不上老闆一句話,韌體有時也是會牽連修改。只要修改,就可能有bug。
這些問題,如果不知道方法處理的team,就是以吵架收場。不知道該怎麼去處理,一而再再而三的prj延宕,讓老闆失去耐心後,你不解決問題,就是等著被老闆解決。

這些問題只是軟體開發的冰山一角,韌體開發的coding,還可以再寫一堆落落長的注意事項...。看,不可否認,即使你原本是韌體工程師,可能只寫driver或MCU的程式,最後還是會遇到這些問題。所以我只講版本管理就好,就像是使用svn、git這類工具,即使你是寫8051或寫driver或者是寫 " 放在rom裡的軟體 " ,你都必須管理版本。當然軟體的領域不只有版本管理這個項目,Bug tracking system、Jenkins CI、Agile、UML...這些也只是團隊合作上的工具,在整個軟體系統建構的過程中,還有好多好多東西要學的。先前分享的書裡面就有提到很多像是coding、design pattern、testing..etc.:



無論你是用什麼程式語言,無論你寫完的程式是放在哪裡跑,這些知識都有助於你解決問題。韌體這名詞對我來說,可說是寫完的軟體放到比較不容易修改的ROM裡面的Release方式罷了。所以我認為,絕不要因為自稱為韌體工程師就不去使用自認為"純軟體"在用的工具知識,或者認為自己不吃軟體工程這一套。只要是對解決問題有幫助的知識,就應該持續向上學習與虛心的跟別人合作,才是工程師的生存之道。


我結論是:原本寫韌體,想要更上層樓,就要朝向軟體發展。因為簡單來說沒有韌体工程這門學科。




2011年7月21日 星期四

當一個很大包的程式(之後稱”母體”),逐漸變成一個怪物時,會有很多人抱怨寫的太亂,寫得太難看懂。或是你的專案賺錢後,請了越來越多的人,發現到一直在重覆處理相同的問題。這時候要進行分解的動作,好讓你下面的人可以繼續專業分工。但是怎麼分解才不會影響到程式的穩定,與保持版本追蹤。我有一套流程。我分為幾個面向:

I. Source Code

為新模組寫一個新的makefile。makefile裡面重新加上要編在library裡面相關的.o與.a。



當然make以後會發現到有很多未定義的symbol。因為已經從母體分出,當然會有很多與母體連結的symbol。現在要將之拆散,勢必要重新實作出這些東西。所以事先規畫非常重要,你要先找出一個耦合度最低的部分來分解。



這些東西要實作在哪邊呢。我是新增一個.c檔,通常稱作xxx_Interface.c,將所有未定義的symbol,先定在這個.c中,使library通過編譯,讓自己對這library有個概觀,也形成一個骨架。未來再回來把內容補滿 。



II. Git版本操作

A. git branch xxxlibrary,加上#define的同時,也加上一個branch。從這個branch加入library。

B. 如要移動檔案,先改make裡面的路徑,而不要先移動檔案。因為移動了檔案,檔案如果需要修改,將來變得很難比對。先改makefile裡的檔案路徑,完成commit之後,再進行移動檔案。

C. 改完後commit。



III. Release

當library建立完成後,跟主線merge,並且在母體的Makefile裡面加上類似-Dxxxlib的定義。好讓source code裡面能選擇要不要link到新的library。這樣子就能夠在git中,追蹤新library以及原本未切出的部分了。

Jenkins notes

wget -q -O - http://pkg.jenkins-ci.org/debian/jenkins-ci.org.key

sudo apt-key add -

sudo sh -c 'echo deb http://pkg.jenkins-ci.org/debian binary/ > /etc/apt/sources.list.d/jenkins.list'

sudo aptitude update

sudo aptitude install jenkins





sudo aptitude install apache2

sudo a2enmod proxy

sudo a2enmod proxy_http

sudo a2enmod vhost_alias







************************改Port************************



Change /etc/default/hudson and add this to passed in arguments:

HUDSON_ARGS="--httpPort=8081 --webroot=/var/run/hudson/war"





************************為jenkins加上gitosis的ssh key************************



參考http://shreevatsa.wordpress.com/2005/11/17/ssh-keygen-as-another-user/



主要是在自己的帳戶路徑內,產生一個key pair,然後將.pub這個publish key,cp到你要登入目標的.ssh/authorized_keys裡面。

這等於連去對方的時候,對方的ssh會對照.ssh/authorized_keys是否與你擁有的private key是一對的。



然後就可以登入

sudo ssh -i id_rda_jenkins jenkins@10.1.5.203







************************設定目標專案的sudo免打密碼************************



在最後一行加上,sudo的權限是從上到下,任何最下面的設定都會蓋過上面的

hawk ALL=(ALL) NOPASSWD: ALL





************************設定某個repository被git push後,觸發jenkins************************



在server上bare git repository裡面的hooks 裡面加上一個名為post-update的可執行檔,內容是:

curl http://${JENKINS_SERVER}:${PORT}/job/${PROJECT_NAME}/build?delay=0sec

就會在有人作了push動作以後,執行jenkins裡設定的build script。

Build Script裡面就可以寫個repo sync去同步所有的git。





************************安裝jenkins衝到其他網頁************************



將http://10.1.5.203/jenkins 引導到8081

在default的最尾巴加上proxy的設定



#sudo vi /etc/apache2/sites-available/default







...



ServerName ci.company.com

ServerAlias ci

ProxyRequests Off



Order deny,allow

Allow from all



ProxyPreserveHost on

ProxyPass /jenkins http://localhost:8081/jenkins







#sudo a2ensite default



參考http://www.zzorn.net/2009/11/setting-up-hudson-on-port-80-on-debian.html