2015年8月1日 星期六

cython workshop 150801 上課內容整理(一) - 環境架設

這天在摩茲工寮有一個一天的 cython workshop,最近因為開發 SOLVCON 所以開始需要寫一些 cython ,加上講師陣容看起來很堅強,所以毫不猶豫就報名了。

環境架設


這次 workshop 使用 vagrant 來準備測試用的環境。這算是我第一次用 vagrant。對於 vagrant 架設測試環境的快速與簡易,感到有一點小小驚喜。大致來說,vagrant 提供一個方便操作的前端,用 virtual box 來做實際的虛擬環境;網路上已經有很多介紹 vagrant 的文章,我在這裡就不多加描述。

我自己的筆電是 Ubuntu 14.04,接下來所有的操作與描述都是基於這個環境。

在 host machine 裝 virtual box 和 vagrant


安裝 virtual box


使用 Ubuntu 的軟體中心搜尋 virtual box 或是使用指令

sudo apt-get install virtualbox

如果在 virtualbox 的執行不太正常,請確定系統中在安裝完 virtualbox 之後,有 virtualbox-dkms 這個套件。確保 virtualbox 和你當下的 kernel 版本能夠很好地合作。

安裝 vagrant

sudo apt-get install vagrant

(這麼好裝,是時候喊一下「我愛 debian-based 的套件管理!」)

取得上課用的 source code


git clone https://github.com/yungyuc/cythonup.git

如果上面的 branch 失效,可以改用我對這個 git branch 的 fork

git clone https://github.com/tai271828/cythonup.git

取得上課用的測試環境 image


課堂上已經有提供包好的 image ,使用 debian jesse 64 bit。
把這個 image 和相關設定檔 copy 到同一個目錄,
然後匯入 vagrant 就好。
匯入 vagrant 的指令:
vagrant box add debian/jessie64 ./package.box
package.box 是講師事先準備好的 image 名字。debian/jessie64 是稍早從上面 github 取得的 vagrant 設定檔 Vagrantfile 裡面寫死的名稱。

因為我沒有附上上課的 image,這裡提供一個另外的方法取得 image。我沒試過這些方法,大概會遇到一些問題。只是打算提供讀者一些可能可以用的資源。這個連結裡面有一些別人事先準備好的 image (請注意我沒有驗證過這個網站和 image 的安全可靠性),使用下面這個指令去取得 image,注意請盡量也是選擇和課堂一樣的 jesse 作為 image,盡量讓差異少一些。使用下面的語法把 image 匯入 vagrant:
vagrant box add {你想要的Box名稱} {下載網址,請見上面連結}
我大概可以預期至少會遇到某些套件缺少或是相依的問題,應該少什麼裝什麼大概就可以解決掉大部分的問題。vagant 似乎也有提供官方下載的站台,我試了一下覺得要從台灣下載實在太慢了,沒耐心等他跑完。

啟動 vagrant


到有 Vagrantfile 的同一個目錄下,執行
vagrant up

啟動 ipython notebook server

因為講師打算使用 ipython notebook 作為講義,所以我們來開啟一個這樣的 server 來閱讀講師提供的講義。

透過 ssh 進去 vagrant 準備好的虛擬環境

vagrant ssh

在此虛擬環境中啟動 ipython notebook server

vagrant@debian-jessie:~$ ipython notebook --ip "*" --no-browser

這個指令的意思就是啟動 ipython notebook server,並且不要主動打開瀏覽器(因為我們不要在虛擬環境中打開瀏覽器)。啟動後,在 hostmachine 裡面打開你的瀏覽器,開始瀏覽

http://localhost:8888/

2015年7月16日 星期四

Debug C program on Ubuntu

很多 GNU 工具都是用 C 寫的,用這些工具用久了偶爾難免會踩到 bug ,在 Ubuntu 上有很完整的生態系可以協助開發者很快架設好除錯環境。

今天好像踩到一個 isoinfo 的 bug ,加上很久沒有這樣玩了(都在寫 python ,哈!),所以又重新走了一遍整個準備除錯環境的步驟,趁著記憶猶新趕快整理下來。isoinfo 這個指令來自 genisoimage 這個 debian package,下面我就直接用這個當範例。

取得 source code

apt-get source genisoimage

一步就完成了,真是貼心的服務。[1]


取得 debug symbol

Ubuntu 使用的 debian package 中,名稱帶有 -dbg 或是 -dbgsym 後綴者,都是對應 package 的 debug symbol。-dbg 通常在預設的 repository 就可以找到,-dbgsym 則是要從另外的 repository 取得,方法如下[2]:

加上新的 repository、取得公鑰[4]、更新 apt list、安裝:

echo "deb http://ddebs.ubuntu.com $(lsb_release -cs) main restricted universe multiverse" | sudo tee -a /etc/apt/sources.list.d/ddebs.list
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 428D7C01
sudo apt-get update
sudo apt-get install genisoimage-dbgsym[3]

準備 gdb

至此為止其實已經準備好除錯環境了,不過為了更輕鬆一點,我們可以把待會自己想要用的 gdb 指令寫成 script。

set substitute-path /build/buildd/cdrkit-1.1.11 /tmp/asdf/cdrkit-1.1.11
b 681
run

/tmp/asdf 是稍早我使用 apt-get source 時取得的 source code 路徑,set substitue-path 是告訴 gdb 不要使用 dbgsym 中提示的舊路徑(/build/buildd)而去用新的(/tmp/asdf);所謂的舊路徑是在某人的電腦上編譯 dbgsym 的時候對應到的放 source code 的路徑,他的環境當然跟自己的會不一樣,所以要稍微調整。

最後開始享受除錯的樂趣吧!

gdb --args isoinfo -R -i ./my-customized-image.iso -x /casper/filesystem.squashfs


[1] 嚴格來說應該要注意自己想要除錯的 binary 版本和 source code。這可以用 dpkg -l package 來查詢版號。
[2] https://wiki.ubuntu.com/DebuggingProgramCrash
[3] 當然也是有版號問題,不過範例中我知道我這樣拿下來會是我系統中對應的版號,所以我就省略了。
[4] 只是為了確定下載下來的 package 不是來路不明的東西。

2015年6月11日 星期四

解決 git 顯示中文檔名的問題

我的 daily system 使用 git 的時候,會有中文檔名顯示的問題,看起來像是:

$ git diff

diff --git "a/\346\210\221" "b/\346\210\221"
index f13588b..75050e9 100644
--- "a/\346\210\221"
+++ "b/\346\210\221"
@@ -1 +1,4 @@
 asdfasdf
+22222222

可以用下面的指令解決這個問題[2]:

git config core.quotepath false

原本上面的亂碼看起來就會是:

$ git diff
diff --git a/我 b/我
index f13588b..75050e9 100644
--- a/我
+++ b/我
@@ -1 +1,4 @@
 asdfasdf
+22222222
也就是說中文檔名「我」現在被正確顯示了。










[1] 不太確定有沒有關聯,但先記下我當時的系統語言環境變數是

$echo $LANG
en_US.UTF-8

[2] 查詢 git-config 使用手冊

man 1 git-config

core.quotePath
The commands that output paths (e.g. ls-files, diff), when not given the -z option, will quote "unusual" characters in the pathname by enclosing the pathname in a double-quote pair and with backslashes the same way strings in C source code are quoted. If this variable is set to false, the bytes higher than 0x80 are not quoted but output as verbatim. Note that double quote, backslash and control characters are always quoted without -z regardless of the setting of this variable.

Blogger 方便快速套用貼程式碼的方法:覆寫 Blogger 的 Quote 樣式

之前在使用 Blogger 貼程式碼的時候,都會手動切換到 HTML 編輯模式,然後插入下面語法:

<pre class="codeblock">
</pre>

這段標記會搭配我事先在 Blogger 準備好的 CSS 樣式:

.post .codeblock {
background-color: #eeeeee;
border: 1px dashed #999999;
color: black;
font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace;
font-size: 12px;
line-height: 14px;
overflow: auto;
padding: 5px;
width: 100%;
}

就成了之前大家看到的樣子。

但這種「手動切換到HTML 編輯模式,再手動找到程式碼,然後插入對應語法」的方式實在嚴重違反程式設計師的三大美德[1]之一的懶惰原則。本來想說看有沒有辦法在 Blogger 編輯模式下新增自己的小工具,後來乾脆心一橫直接覆寫原本 Quote 按鍵的樣式(反正我很少用到 Blogger 提供給我的樣式)。作法其實很簡單,也是事先準備好 CSS 範本就好,只要注意有使用到關鍵字 blockquote 即可[2]:

blockquote {
background-color: #eeeeee;
border: 1px dashed #999999;
color: black;
font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace;
font-size: 12px;
line-height: 14px;
overflow: auto;
padding: 5px;
width: 100%;
}
之後每次貼上程式碼後,只要用滑鼠選好區域,按下 Blogger 提供的 Quote 按鍵,就會套用我原本慣用貼程式碼的樣式了。

方便多了;寫文章就是要行雲流水才爽啊!Bravo!

[1] 設計師美德:懶惰、不耐煩、驕傲 - Programming Perl, Larry Wall
[2] 可參考:https://www.nosegraze.com/how-to-style-blockquotes/

chrome 異常:外觀變成大分頁(低解析度)workaround


昨天自己的 XPS 上的 Ubuntu trusty 系統更新後,一早開機發現 chrome 外觀整個大亂,即使是清掉系統快取、重新安裝之後也還是一樣,心想說天啊該不會跟什麼圖形渲染的函式庫衝突或是有臭蟲吧!!?? 幸好在網路上有找到一個適用於我的 workaround:

用終端機執行 chrome ,並且搭配下面的參數

google-chrome --force-device-scale-factor



使用 Chrome 一陣子之後變慢而且常顯示沒有正確關閉的 workaround


Ubuntu 14.04 上面使用 Chrome 一陣子之後,
會變很慢,或是有一些不太穩定的感覺。
而且在剛開機完後,
瀏覽器會顯示沒有「上次沒有正常關閉」。

解決變慢、變不穩定的 workaround

其實就是放大絕重裝。但是 chrome 提供的 debian rule 似乎沒有足夠完整,所以即使使用 apt-get purge 還是沒辦法清乾淨[1]。下面是我自己試出來、認為有效的方式,提供給大家參考。

首先使用下面指令把程式清除:

apt-get purge google-chrome

接著清除下面這些設定檔和快取[2]

$HOME/.cache/google-chrome
$HOME/.config/google-chrome
$HOME/.local/share/applications/chrome-*

之後再重新安裝 chrome 就會取得清爽多了的 chrome 了!!(雖然還是很吃記憶體)

常常顯示上一次沒有正確關閉

這是因為 chrome 預設會在背景持續跑, 可以透過 Unity 桌面右上角 chrome applet 選擇, 把背景跑 chrome 的功能關閉。 或是進到 chrome 的設定選項, 取消裡面類似的 checkbox 。 如果你的 Unity 桌面右上角沒有看到 chrome applet , 就可能表示你的 chrome 已經被你搞到很髒了[3], 可以考慮使用上面的方法清掉一堆系統上的快取、重新安裝 chrome 。 [1] 只用 apt-get purge 清除之後,立刻去 google 下載 chrome debian package 重新安裝的話,我們可以注意到很多設定、外掛等等其實都還在。 [2] 如果擔心造成系統不穩,記得先把這些檔案移到 [3] 自己曾經按照這個方法把快取位置改來改去,最後好像就把自己的系統搞髒了 XD

2015年5月31日 星期日

初探 Ubuntu Snappy


最近 Canonical 公司在 IoT 的浪潮下,也開始力推自己的系統,稱為 Snappy ;例如這個 Canonical 的創辦人在 youtube 的介紹影片。喜歡湊熱鬧的我,也跳進來攪和了一下,瞧瞧 Snappy 究竟是什麼。

這次湊熱鬧所選用的硬體為 Raspberry Pi 2 (RP2)。下面的 demo 主要是參考 Snappy 官方文件,加上一些個人心得。



事前準備

Snappy 在 RP2 上面目前(2015五月)還沒有官方釋出,不過已經有開發者準備好了移植到 RP2 的映像檔案,可以從這裡下載,取得映像檔 pi2.img.gz 。解壓縮後取得檔案 pi2.img ,將 pi2.img 透過指令 dd 寫入 micro SD 裝置 /dev/sdX (根據你的系統狀況,請自行用適當字串代換 sdX ) [1][2]

sudo dd if=pi2.img of=/dev/sdX

映像檔接近 4G ,讀寫要花上一點時間。如果想知道 dd 的進度,可以用這個技巧偷看一下寫入進度。讀寫完畢後,將 micro SD 插到 RP2 上面、開啟電源。預設帳號、密碼都是 ubuntu ,登入後就可以開始玩了。

因為設計上是給物連網 client 端產品使用,基於效能考量,當然不會有圖形介面。操作上可以選擇使用 RP2 的 HDMI 輸出,或是像我所採取的作法:第一次使用 HDMI 登入,登入後使用 ifconfig 取得 RP2 Snappy 的 IP ,之後都透過自己慣用的作業系統,透過 ssh 登入 RP2 Snappy 。RP2 Snappy image 已經將 ssh server 服務事先準備好,因此直接從慣用的作業連過去就好。[3] 例如使用這個指令(IP 位置視您的環境而定):

ssh ubuntu@<您的 RP2 Snappy IP>
ex.
ssh ubuntu@192.168.1.23



Let's party!!

接下來就是今天的重頭戲了。下達指令 snappy info

(RaspberryPi2)ubuntu@localhost:~$ snappy info
release: ubuntu-core/devel
architecture: armhf
frameworks: 
apps: 

release 和 architecture 分別就是 image release 版本和適用的平台類型,RP2 使用 ARM ,所以是 armhf 版本。frameworks 和 apps 分別是什麼意思呢? 望文生義, apps 很明顯就是 applications ,那 frameworks 呢?

簡而言之,根據官方文件,framework 在這邊指的是一個獨立的、因目的導向而事先配置好所需軟硬體資源存取管道的「環境」。

「獨立的」,意指各個 framework (與該 framework 下的 apps) 彼此之間不互相影響,所以可以顧及安全問題(檔案權限不會被亂改、存放密碼的檔案別人讀不到等)。

一般 IoT client side device,通常為了滿足某種目的,都會依照該目的,去設計、製造、配置所需的對應資源。例如,假設有個瓦斯洩漏偵測器,可以在偵測到一氧化碳時,將警告與一氧化碳濃度值送到我們的手機裡面。所以這個裝置,起碼必須要有一氧化碳偵測器、網路連線(此處假設我們選用乙太網路)。而一個這樣的瓦斯洩漏偵測器 framework ,就會保證所有在這個偵測器下的 applications ,可以取用到一氧化碳偵測器的讀數、和取用系統乙太網路資料。

說得落落長又很抽象,直接舉例,docker 就可以是一個提供 framework 服務的工具。

接著我們看一下這個 snappy 系統中,裝了什麼 snappy 套件

(RaspberryPi2)ubuntu@localhost:~$ snappy list
Name        Date       Version Developer 
ubuntu-core 2015-04-10 4                 
pi2         2015-04-15 0.11    lool

系統還很乾淨,就只有 ubuntu-core (官方文件稱這是一種 system-layer)和 pi2 (官方文件稱這個叫做 OEM snappy package or device) 而已。[4]

好吧!我們來裝 framework 和 app 吧!

framework 我們選擇使用 docker ;可以看出來裝了 docker 之後, snappy list 就多了這個 snappy package 。

(RaspberryPi2)ubuntu@localhost:~$ sudo snappy install docker
Installing docker
Starting download of docker.canonical
8.36 MB / 8.36 MB [====================================] 100.00 % 41.93 KB/s 
Done
Name        Date       Version   Developer 
ubuntu-core 2015-04-10 4                   
docker      2015-05-31 1.6.1.002           
pi2         2015-04-15 0.11      lool  
    
(RaspberryPi2)ubuntu@localhost:~$ snappy list
Name        Date       Version   Developer 
ubuntu-core 2015-04-10 4                   
docker      2015-05-31 1.6.1.002           
pi2         2015-04-15 0.11      lool      

請注意這時候已經有 framework docker 了[5]

(RaspberryPi2)ubuntu@localhost:~$ snappy info
release: ubuntu-core/devel
architecture: armhf
frameworks: docker
apps: 

app 我們選用 go-example-webserver

(RaspberryPi2)ubuntu@localhost:~$ sudo snappy install go-example-webserver
Installing go-example-webserver
Starting download of go-example-webserver.canonical
3.06 MB / 3.06 MB [================================] 100.00 % 44.75 KB/s
Done
Name                 Date       Version   Developer 
ubuntu-core          2015-04-10 4                   
docker               2015-05-31 1.6.1.002           
go-example-webserver 2015-05-31 1.0.7               
pi2                  2015-04-15 0.11      lool  
(RaspberryPi2)ubuntu@localhost:~$ snappy list
Name                 Date       Version   Developer 
ubuntu-core          2015-04-10 4                   
docker               2015-05-31 1.6.1.002           
go-example-webserver 2015-05-31 1.0.7               
pi2                  2015-04-15 0.11      lool    

這時候 apps 果然也補上了 go-example-webserver

(RaspberryPi2)ubuntu@localhost:~$ snappy info
release: ubuntu-core/devel
architecture: armhf
frameworks: docker
apps: go-example-webserver

go-example-webserver 是一個用 go 寫成、用來做 snappy 打包教學的 snappy 套件,原始碼可以在 Launchpad 上面找到。

當初以為裝了 go-example-webserver 以後,web server 的服務會自己啟動,搞了半天發現根本沒有自己啟動,不曉得這是 by-design 還是一個 bug 。最後我直接參考原始碼(裡面有 README),手動尋找執行 web 服務的指令、並且啟用服務:

尋找可能可以用的指令

root@localhost:/# find ./ -name go-example-webserver
./var/lib/apps/go-example-webserver
./writable/system-data/var/lib/apps/go-example-webserver
./writable/system-data/apps/go-example-webserver
./writable/system-data/apps/go-example-webserver/1.0.7/magic-bin/go-example-webserver
./writable/system-data/apps/go-example-webserver/1.0.7/magic-bin/arm-linux-gnueabihf/go-example-webserver
./writable/system-data/apps/go-example-webserver/1.0.7/magic-bin/x86_64-linux-gnu/go-example-webserver
./apps/go-example-webserver
./apps/go-example-webserver/1.0.7/magic-bin/go-example-webserver
./apps/go-example-webserver/1.0.7/magic-bin/arm-linux-gnueabihf/go-example-webserver
./apps/go-example-webserver/1.0.7/magic-bin/x86_64-linux-gnu/go-example-webserver

這裡有兩點滿有意思,第一是 /var/lib/apps/go-example-webserver 是空的,不曉得在其他 Snappy package 中,實際上會放入什麼樣類型的檔案。第二是整個 app 程式似乎就是集中在 /apps 這個資料夾裡。

找到疑似可以用的可執行檔後,直接給他執行下去啦!

(RaspberryPi2)ubuntu@localhost:/apps/go-example-webserver/1.0.7$ ./magic-bin/go-example-webserver 
snapp_name: go-example-webserver
snapp_bin: go-example-webserver
snapp_dir: /apps/go-example-webserver/1.0.7
snapp_org_bin: go-example-webserver
plat_abi: arm-linux-gnueabihf
2015/05/31 10:06:53 Starting webserver on :8081

最後開啟本地端(不是 RP2 ,而是,例如說,你慣用的作業系統)的瀏覽器,瀏覽器 url 填入 RP2 的 IP ,port 8081 (這是上面執行時,程式告訴我的)。一切順利的話,應該就可以看到下面的畫面。另外,在 RP2 中可以使用 ctrl+c 以中斷程式伺服器服務的運行。





[1] 注意!!這個指令在使用之前務必確定知道自己在做什麼。這個指令操作錯誤的話有可能抹除您系統裡面的資料。

[2] 如果使用上有問題,例如 Snappy 操作起來怪怪的,像我遇到的問題就是明明已經把 docker 裝上去了,但是 snappy list 卻看不到這個訊息。遇到這種情況的話,可以試試 dd 前先把 micro SD 上面的 partition 全部清掉之後,再用 dd 寫入。寫入完畢後,下達兩三次 sync 指令,確認所有必要的訊息都寫進 micro SD ,再將 micro SD 退出、插到 RP2 上面。

[3] 在這之前,當然要先確定慣用的作業系統和 RP2 在同一個、彼此可以看見彼此、允許 ssh 通訊 port 的網域。

[4] 根據官方文件,在未來 system-layer 和 device package 會整合成一個 snappy package 。

[5] Snappy for RP2 似乎不太穩定;有時候我明明已經裝了 docker ,但是把系統放在那邊一陣子,大約二十分鐘, snappy info 卻看不到 docker 了。reboot 之後再安裝一次 docker 還會報錯。不太確定是不是自己有哪裡不清楚,或是真的是一個 bug ;需要更多測試與資訊。