My code works, I don’t know why.

國王的耳朵是驢耳朵

在X86 Linux下透過Qemu安裝ARM的Debian系統

| Comments

安裝順序如下

測試環境

1
2
3
4
5
6
$ lsb_release -a
No LSB modules are available.
Distributor ID:   Ubuntu
Description:  Ubuntu 14.04.1 LTS
Release:  14.04
Codename: trusty

安裝Qemu

1
$ sudo apt-get install qemu-system-arm

拉ARM安裝相關檔案

  • 首先先來看Qemu有支援那些ARM平台
1
2
3
4
5
6
$ qemu-system-arm -machine help
Supported machines are:
versatileab          ARM Versatile/AB (ARM926EJ-S)
versatilepb          ARM Versatile/PB (ARM926EJ-S)
lm3s811evb           Stellaris LM3S811EVB
...

安裝ARM版本Debian需要

  • kernel
  • initrd
  • ISO 首先到提供Debian下載的網站中的debian/dists找一個你想安裝的版本,我選了7.8 (Wheezy)。 假設Debain下載網站叫host

先抓平台相關的kernel和initrd,路徑如下

http://host/debian/dists/Debian7.8/main/installer-armel/20130430/images/

下面有不同的ARM平台,還記得上面qemu-system-arm -machine help,請和這邊目錄下的比對,挑一個順眼的。我使用 versatile,所以就切到下面的目錄

http://host/debian/dists/Debian7.8/main/installer-armel/20130430/images/versatile/netboot/

把下面的兩個檔案拉下來

  • initrd.gz
  • vmlinuz-3.2.0-4-versatile

接下來在同樣的主機上,下載ISO檔。

http://host/debian-cd/7.8.0/armel

開始安裝

透過下面的指令安裝虛擬磁碟,請自行決定大小

1
$ qemu-img create debian.img 8G

然後叫qemu載入ARM kernel,initrd,以及ISO

1
$ qemu-system-arm -M versatileab -kernel ./vmlinuz-3.2.0-4-versatile -initrd ./initrd.gz -cdrom ./debian-7.8.0-armel-DVD-1.iso -hda debian.img -m 1024

這邊可以看到versatileab又出現了,請往上找一下這個字串吧。

抽出虛擬磁碟的kernel和initrd

最tricky的地方在這邊,理論上你要透過loopback裝置mount 虛擬磁碟,複製/boot就可以了。但是現實就是,因為磁碟機/root的partition有offset,所以直接mount程式無法辨認Filesystem所以無法mount。正確方式如下

1
2
3
4
5
6
7
8
9
10
11
12
13
$ sudo fdisk -l -u debian.img 

Disk debian.img: 8589 MB, 8589934592 bytes
255 heads, 63 sectors/track, 1044 cylinders, total 16777216 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x000823a0

     Device Boot      Start         End      Blocks   Id  System
debian.img1            2048    15988735     7993344   83  Linux
debian.img2        15990782    16775167      392193    5  Extended
debian.img5        15990784    16775167      392192   82  Linux swap / Solaris

有兩個東西要注意

  • unit為512 bytes
  • root partition offset為2048個unit

所以正確的mount方式如下

1
$ sudo mount -o loop,offset=$((2048 * 512)) debian.img /mnt

接下來抽出就簡單了,請在剛才安裝的虛擬磁碟檔案同一個目錄操作。

1
2
$ mkdir boot
$ cp /mnt/boot/* boot/ -rv

載入安裝的系統

這邊就照表操課,我有指定localhost將port 2222 forward到Qemu的port 22,以便將來ssh進去

1
$ qemu-system-arm -M versatileab -kernel ./boot/vmlinuz-3.2.0-4-versatile -initrd ./boot/initrd.img-3.2.0-4-versatile -hda debian.img -m 1024 -append "root=/dev/sda1" -redir tcp:2222::22

驗收看看是不是真的可以連進去,並且裏面真的是ARM的binary?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ ssh -p 2222 user@localhost
user@localhost's password: 
Linux debian 3.2.0-4-versatile #1 Debian 3.2.65-1+deb7u1 armv5tejl

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
You have mail.
Last login: Fri Feb  6 09:35:07 2015
user@debian:~$ file /bin/ls
/bin/ls: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.26, BuildID[sha1]=0x5bc97dbca9ac168932d898a5e2eaf68e8fde5e16, stripped

參考資料

談談autotools 的 Build, Target, 和host

| Comments

先來個小故事,某天組裝工趁放假跑去看老房子。發現只有一間上面有動物的造型。因為年代久遠,只看得出來有四肢腳而已,而不知道是那種動物。好奇之餘問了店家,店家說他們承租,不知道那是什麼東西。後來一位長者經過,就順便請教他同一個問題,長者說他住這邊好幾年都不知道上面有這東西。最後遇到當地文史工作室的人,問了才知道是當時主人的商標,一隻獅子。

我們常常用的東西,因為太習以為常,以至於發生視而不見的狀況屢見不鮮。但是惡魔就在細節裏面,而長時間地視而不見就會把自己對於這樣的事物感受性變低。

回到主體。組裝的時候,常常缺東缺西的。這時候就需要cross-compile一些套件頂一下,所以如果有人組裝過的話,應該會對下面的命令倍感親切。

1
$ ./configure --host=mipsel

如果組裝夠次數夠多,也會看到--target--build的參數似乎和這個有關。找時間稍微了解一下

對於–target目前手上的資料無法讓我完全理解,請注意!

根據Autoconf手冊說明,這些參數的預設值如下:

  • --build
    • 從config.guess中猜的
  • --host
    • 設成和--build相同
  • --target
    • 設成和--host相同

因為這樣的連動性,如果你要cross-compile,那麼下了--host後麻煩不要省掉--build,不然autotool會把build設成和host一樣。

Automake手冊裏面的定義

  • --build
    • 你build code,下xxx-gcc那台機器平台
  • --host
    • 產生的binary可以執行的平台
  • --target
    • 告訴gcc要產生什麼平台的機械碼
      • 一般來說會和--host一樣同樣的平台,根據上面的連動,你設了--host就可以省略這個選項
      • 特例是compile cross-compiler或是binutils,toolchain。這時候是指定build在host上,但是處理的對象是cross platform的機械碼

Autotool選擇gcc的方式如下

  • --host--build相同
    • 用你電腦上的gcc,來編譯autotool的套件。
  • --host--build不同
    • 你要自備cross-compiler
    • 如果有指定--target的為gcc的prefix
    • --host=xxx, --target=zzz,會使用zzz-gcc產生xxx平台的機械碼
    • 用該cross-compiler來編譯autotool的套件
    • 這時候要保證cross compiler可以吃的library也存在,常常會為了編一個套件cross compile一堆套件

看的有點混亂嘛?沒關係,autoconf 2.69手冊有提到,要cross-compile的話,唯一(if and only if)的條件就是指令--host指定和你現在的平台不同就好。

參考資料

如何trace Bash Script中的function

| Comments

在組裝的過程中,常常會遇到用source去載入一個shell script,裏面通常是一組的環境變數。然而如果專案大到某個程度,這個script就會塞入很多複雜的function,例如某專案的build/envsetup.sh。這時候要去trace用肉眼去看實在是太過殘酷,最近為了這個問題想到了一招很簡單的方式,那就是:

1
$ bash -x

沒錯就這麼簡單,直接來看例子吧。首先我們有一個script裏面有function。

demo.sh
1
2
3
4
5
#!/bin/bash
function whatsoever()
{
    echo "My code works, I don't know why."
}

接下來就是剛才講的操作

demo.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
$ bash -x
+ '[' -z '\s-\v\$ ' ']'
+ shopt -s checkwinsize
... # 中間發生超多事,有興趣自行研究。發現好玩的再跟我說。

$ cd /tmp
+ cd /tmp
$ . demo.sh
+ . demo.sh
$ whatsoever
+ whatsoever
+ echo 'My code works, I don'\''t know why.'
My code works, I don't know why.

打完收工,謝謝收看。

更新

網友Scott Tasi大大說這個方式和下面的方式相同:

demo.sh
1
set -x

我就學天線寶寶再重複一下實驗

demo.sh
1
2
3
4
5
6
7
8
9
10
11
$ set -x
$ . demo.sh
+ . demo.sh
$ whatsoever
+ whatsoever
+ echo 'My code works, I don'\''t know why.'
My code works, I don't know why.
$ set +x
+ set +x
$ whatsoever 
My code works, I don't know why.

結論就是,用set -xset +x就可以了。不過bash -x跑出來的訊息還真的嚇了我一跳,原來載入一個bash有那麼東的東西要做。這就是所謂的微言大意嗎?

使用debootstrap 在本機中操作其他Ubuntu 版本 (命令列)

| Comments

好吧,這個標題我也不滿意,不過就將就一下吧。

簡單來說在Ubuntu內只要可以找得到的distribution,你就有辦法讓它在你的Ubuntu使用。使用順序如下:

下載你想要執行的套件

命令:

1
debootstrap --arch=你要跑的target平台 --variant=minbase 你要跑的版本代號 自己PC的版本代號 [mirror site]

要怎麼知道arch有哪些呢,你可以連到任意一個Ubuntu archive中的ubuntu/dists/[版本代號]/main中就可以看到了。可以看範例網頁,這邊可以看到有i386amd64兩種架構。

而版本代號可以在任意一個Ubuntu archive中的ubuntu/dists/看到。範例網頁可以看到10.04 (lucid), 12.04 (precise)等。

另外–variant問男人可以看到有

  • minbase
    • 最少安裝
  • buildd
    • 多安裝build code需要的套件
  • fakechroot
    • 只安裝不需要root的套件 (怪怪的??)
  • scratchbox
    • 看不懂,跳過

我使用的範例如下:我要在x86-64位元的Ubuntu 14.04 (trusty) 下面安裝32位元(i386)的10.04 (lucid)最少套件的話,就會使用下面的指令。

1
2
3
4
5
6
7
8
9
10
$ sudo debootstrap --arch=i386 --variant=minbase lucid trusty ftp://ftp.tku.edu.tw/ubuntu/
I: Retrieving Release 
I: Retrieving Release.gpg 
I: Checking Release signature
...
I: Unpacking apt...
I: Configuring the base system...
I: Configuring apt...
I: Configuring libc-bin...
I: Base system installed successfully.

debootstrap會把下載並解開的套件放在你的指定的target名稱目錄中,這次範例使用trusty,所以我們看看trusty目錄有什麼東西?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
$ cd trusty
$ tree -L 1 -d
.
├── bin
├── boot
├── dev
├── etc
├── home
├── lib
├── media
├── mnt
├── opt
├── proc
├── root
├── sbin
├── selinux
├── srv
├── sys
├── tmp
├── usr
└── var

可以看到他就是一個root file system。接下來要做的就是。

使用chroot切換到用debootstrap安裝的root file system

先確認我電腦上的Ubuntu版本

1
2
3
4
5
6
7
8
9
$ lsb_release -a
No LSB modules are available.
Distributor ID:   Ubuntu
Description:  Ubuntu 14.04.1 LTS
Release:  14.04
Codename: trusty

$ file /bin/ls
/bin/ls: ELF 64-bit LSB  executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=64d095bc6589dd4bfbf1c6d62ae985385965461b, stripped

切換指令如下

1
2
3
4
5
6
$ cd trusty # 假設你還沒切換過去
$ sudo mount --bind /dev ./dev
$ sudo mount --bind /dev/pts ./dev/pts
$ sudo mount --bind /proc ./proc
$ sudo mount --bind /sys ./sys
$ sudo chroot .

好啦,口說無憑,我們先來看看是不是真的換到lucid,32位元版本吧

1
2
3
4
5
6
7
8
9
10
11
12
13
14
## apt-get install lsb-release # 因為最少安裝所以沒有lsb_release
Reading package lists... Done
Building dependency tree... Done
...

## lsb_release -a
No LSB modules are available.
Distributor ID:   Ubuntu
Description:  Ubuntu 10.04 LTS
Release:  10.04
Codename: lucid

## file /bin/ls
/bin/ls: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.15, stripped

這東西能做什麼呢?有時候開發套件需要在不同的Ubuntu版本測試,這時候後這招頂著先應該會比用VM再來得有效率一些。

另外要注意的是,我測試的時候自己的電腦應該有裝過很多東西了。這表示你要按表操課可能會因為缺乏套件所以不會成功,例如debootstrap可能就要自行安裝了我猜。

嘛,這就是人參,出現這種狀況就當作磨練吧。

參考資料

  • man debootstrap

Talking About Information Technology Presentions in Taiwan

| Comments

OK. This should be the first English article in my blog. I do hope this will also be the last one. English is not my mother tongue, so please bear with that. It should be clear to address my point of view although there should be some glitches throughout my article.

The purpose of my technical articles and slides is to provide useful information for the people who uses Chinese. Since I went to college to learn computer engineering, what I saw in the class and laboratory meetings, the slides always wrote in English. Even after I graduated, it still mostly true in the events or presentations I attended locally. However, most professors and speakers uses mandarin to describe their ideas and thoughts. It is rare to have a completed English presentation in those scenarios, never to say discuss in English. If that so, why people uses English in their slides?

Don’t get me wrong. I totally agree English is extremely important in information technology area. Most of the first hand information writes in English. If you need to cooperate with people overseas, you use English. However, the scenario I call into question is that if your audiences uses mandarin, you speak in mandarin, why bother to write slides in English? Can you make sure what you wrote are 100% grammar corrected? Will this exclude the newbie who does not familiar in English yet if they search keyword in the Internet? A ideal article in the Internet should be useful for the people who need it. If you write your article and slide in Chinese, you will benefit the people who uses Chinese. There are already plenty of useful information in English. Why don’t you just use your mother tongue to describe your thought and what you found?

Linux: 用Live CD跑硬碟裏面的Linux

| Comments

我用這個救過過兩次grub GG的狀況,每次都要上網回想一下,趁著還記得的情況紀錄一下。

  • 用Live CD開機。你的Live CD要和你硬碟的Linux distribution相同。
  • 想辦法開終端機
  • 輸入以下的咒語指令,假設你的硬碟root filesystem partition放在/dev/sda2
1
2
3
4
5
6
sudo mount /dev/sda2 /mnt
sudo mount --bind /dev /mnt/dev
sudo mount --bind /dev/pts /mnt/dev/pts
sudo mount --bind /proc /mnt/proc
sudo mount --bind /sys /mnt/sys
sudo chroot /mnt

剩下就是處理grub問題了,請自己估狗。

注意!grub是bootloader,沒弄好有可能會讓你的硬碟資料GG。操作有風險,操作前應詳閱相關文件資料。如果你不知道boot loader,grub,root file system,mount,chroot是什麼的話,請找熟悉的碰友幫你處理。

閒聊:忍耐力

| Comments

三四年前我聽過關於Linux下面中文輸入法的技術演講。技術內容忘得一乾二淨,然而印象最深刻的事講者說台灣人忍耐力太強,所以台灣中文輸入法就變成堪用,進度速度不夠快。   私自推論忍耐力太強的習性是造成問題長時間存在、把人類當成猴子用的悲劇原因之一。而且忍耐力強的話,到後面會把察覺到問題的能力降低或是消滅掉。我會這樣比喻:肚子痛想說忍耐一下。過幾天又在痛,想說大概最近吃到不乾淨的東西,接下來都這樣認為。直到幾個月後有天昏倒送醫才發現這是重病的症狀,而到那時候已經很難處理了。

雖然後來後來還是沒去幫忙看程式碼(組裝工程度太差又沒耐性,大大對不起)。但是至少我會比較願意看到問題讓開發者或是負責人知道,而不是單純地認為在找別人麻煩。雖然有沒有改善並不是我該關心的,但是也許作者或是負責人他們真的沒注意到這塊,這樣來說,你是幫作者或是負責人和自己的忙。

私密景點

| Comments

以前出遊和當地居民聊天聽到兩個故事。

第一個是在南部,一位年輕人帶我去私密景點。這個景點是個天然池塘,生態豐富,但是水草叢生,所以蚊子也不少。他說以前他們曾經有整理場地,把水草清掉,變得十分美麗。雖然沒有宣傳,但是過了中秋節以後,這地方就出現一大堆垃圾,經過清理後過一陣子水面還可以看到油光。所以他們後來就不去整理,讓雜草長回來。

另外一個在北部靠近山區,一位大哥跟我說剛解嚴時期,他跑去以前封鎖的海邊逛,發現到處都有毛蟹,他帶了幾個回去料理,後來他再回去海岸,除了垃圾,什麼都不剩了。

聽完這兩個故事,我決定把私密景點留在我的腦海中就好。希望那天國民水準可以提升到尊重土地,尊重生態,尊重自然。