initrd+busybox

kernel source 的 Documentation/initrd.txt 裡,把 initrd 、開機順序跟必要的程序講的很清楚,依法施為,大致就沒問題了。

雖然如此,我還是花了快一天的時間。這邊紀錄一下我的作法,我是用文件裡提到的 loop device 方法,也就是先用 dd if=/dev/zero of=initrd bs=4M count=1 製作出 initrd,再用 mke2fs 格式化,接著用 mount -o loop 把這檔案掛為檔案系統。

然後我 build BusyBox,參考 BusyBox 原始碼的 examples/bootfloppy/mkdevs.sh 裡的 code,把我要的 device 都建起來,然後把 BusyBox 的相關檔案放進去,再把 examples/boot/floopy/etc 放進去。接著修改 etc/init.d/rcS, etc/fstab, etc/inittab,調整成我要的樣子以後,就差不多了。

因為這份 initrd 在開機後,我就拋棄了,所以 etc/init.d/rcS 最後得掛上真正的 device,並且切換過去:

# mount your device to /newroot.
mkdir /newroot
mount -t ext3 /dev/your_device /newroot
cd /newroot
mkdir /initrd
/sbin/pivot_root . initrd
exec /usr/sbin/chroot . /init </dev/console >/dev/console 2>&1

最後,umount,再用 gzip -9 壓縮得到 initrd.gz 之後,大致上就是這樣子。

xargs

以前就看過 xargs 這指令了,不過那時只有看人家的範例,沒有理解為什麼要這樣用。等到想試著用的時候,才發現原來是這樣子。
因為我之前完全誤解了。
舉例來說,這樣的命令:

ls | xargs echo

假設我目前目錄有 file0, file1, file2 這3個檔案,我以為 xargs 會根據 stdin,執行 echo 三次,這當然是錯誤的。
xargs 會讀取 stdin 的內容,然後轉成以空白分格的字串,再將結果作為指定命令的參數。所以上面最後會執行的指令其實是:

echo file0 file1 file2

用 bash source 時,出現 “file not found”

今天遇到很鳥的問題。
情境是這樣的:目前的目錄下有 .config,而 scripts 目錄下有個 shell script ,名稱是 Configure。Configure 的內容很簡單,就是 source .config。接著,在目前的目錄下輸入 sh scripts/Configure,你就會遇到 “.config: file not found” 的訊息。
試了好久,雖然知道可以用 bash 執行來解決,但是就是覺得奇怪,因為 9.04 的 bash 3.2 是沒問題的,但到了 9.10 的 bash 4.0 就不行了。
最後在這裡:Re: source command differs if in bash or sh mode 找到答案:

This is a property of bash posix mode when you don’t have `.’ in $PATH:
28. The `.’ and `source’ builtins do not search the current directory
for the filename argument if it is not found by searching `PATH’.
> This behavior is new in version 4, old version 3.2 works fine.
The bash-3.2 behavior was a bug. Its fix is listed in CHANGES:
ggg. Fixed a bug that caused a shell running in Posix mode to search $PWD for
a file specified as an argument to source/. when the file was not found
in $PATH.

對,這是 bug,bash 3.2 沒問題,是因為他是 bug,4.0 的時候修正了,所以就有問題了,你必須要在 PATH 裡加入 . 才行。
好鳥。

gwibber 的 spell 問題

如果你用 gwibber 時,碰到下面錯誤的話,這是因為沒有中文的 aspell 資料檔的關係:

File "/usr/lib/python2.6/dist-packages/gwibber/gwui.py", line 455, in __init__
self.spell = gtkspell.Spell(self, None)
glib.GError: enchant error for language: zh_TW.UTF-8

解法很簡單,修改 /usr/lib/python2.6/dist-packages/gwibber/gwui.py 把 455 行的前後加上 exception handling 即可:

try:
self.spell = gtkspell.Spell( self, None )
except:
pass

修改時要注意縮排問題,python 對這點可是很講究的!

解決 opera 10 不能用 ibus 問題

環境:
Ubuntu 9.10
Opera 10
輸入法:ibus
解決方法:
編輯 /usr/bin/opera,在 OPERA_BINARYDIR 之下加上

export QT_IM_MODULE=XIM

,然後重新啟動就行了。

grub 從不是第1個硬碟開機

我承認,這標題下的很爛,但一時也想不到更好的。

情況是這樣的,我第一個硬碟已經裝了 Linux,這時候我卻想裝 Windows,是故,我只能裝在第二個硬碟上。Windows 非常機車,如果第一個硬碟沒有 NTFS 的 partition 是不給你裝的。這時候只能先拔第一個硬碟的電源,把 Windows 裝到第二個硬碟上之後,再重新把第一個硬碟的電源裝回去。

接下來,因為不想老是在 BIOS 裡切換開機順序,所以把腦筋動到 grub 上。根據 grub 的 manual,只要利用 map 就行了,但我還是試了好一陣子,後來才發現是順序的問題,我試的時候把 map 放到最前面去了。正確的順序是這樣的:

title		Windows XP
root		(hd1,0)
makeactive
map (hd0) (hd1)
map (hd1) (hd0)
chainloader	+1

這樣就可以不用在 BIOS 裡切換開機順序了。如果你不是用第二個硬碟,而是第3個或第四個硬碟,只要類推為 hd2、hd3 即可。

wine 的選單

我用的是 Ubuntu。
用 wine 安裝程式以後,Wine 選單裡會多出該程式的項目,但移除程式以後,這些項目還存在,即便你之前有備份 .wine,將備份檔案回存了,也不會有用。關鍵在於 wine 其實是把這些選單項目放在 $HOME/.config/menus/applications-merged 下,所以只要把該刪除的項目從這個資料夾下刪除即可。
2009/10/14 補充:$HOME/.local/share/applications/wine/Programs 下的也要記得刪掉,否則會出現在”其他”選單裡…

Mustek Bearpaw 1200TA in Ubuntu

如果你正好用的掃描器跟我一樣是 Mustek BearPaw 1200TA 或者是開啟 xsane 遇到 gt68xx:libusb 錯誤時,你可以試著到這裡:SANE GT68xx Backend Homepage 去下載適當的 .usb 檔案。下載以後,把它複製到 /usr/share/sane/gt68xx 目錄下,變更權限為 a+r,然後重新開啟 xsane,這樣就能正常使用掃描器了。

在 Ubuntu 9.04 使用 svk 出現 Can’t locate Time/Progress.pm

在公司正想用 svk 把 monodevelop source code 拉回來時,發現有 Can’t locate Time/Progress.pm 訊息,然後就停止運行了。
Launchpad 找了一下,發現已經有人回報了:Bug #317487 in svk (Ubuntu): “2.2.1 needs Time::Progress”,後續的回覆裡,也提供了好幾個 workaround,我選擇直接修改 Notify.pm,因為以後 apt-get upgrade 時,新檔案會把舊檔案覆蓋掉。

kernel 怎麼執行 hotplug?

因為只知道 hotplug 這關鍵字,直接以 hotplug 找,從 lib/kobject_uevent.c 裡可以看到放 “/sbin/hotplug” 的變數:uevent_helper。再往後找,可以看到 call_usermodehelper 使用了此變數。
call_usermodehelper 定義在 kmod.h 裡,是一個 static inline function。裡面則呼叫了 call_usermodehelper_setup 去設置環境,末了再呼叫 call_usermodehelper_exec 去執行。
p.s. 似乎不能在 IRQ 中斷處理常式裡去呼叫,會造成 kernel crash 掉,仔細想想,這樣有合理,因為 IRQ 中斷處理常式應該要盡早處理結束。如果是這樣,處理就比較麻煩了,可能就要利用 thread 跟 queue 來作。現階段,先不要作這個好了,雖然主動通知的功能很酷…