上傳 debian package 到 PPA

去年就試著想放東西到 PPA 上,可是受限於公司網路環境與個人鬼混的因素,導致今天才真正把東西放上去。這部份中文的資訊很少,可能大家看PPA說明就都搞定了吧。
你比較會遇到的幾個問題:一個是 PGP、一個是如何打包 debian package,這邊假設你都會了。(PGP 可以去 Jedi 那邊找介紹文)
以下,就開始。你必須要先有 PGP key,然後到 launchpad 註冊,成為會員。
這篇:Personal Package Archives來做,我整理重點如下:

  1. profile頁,把 ppa 打開。
  2. 填 OpenPGP public key。
  3. Sign conduct:其實就下載文字檔,然後打指令,用gpg sign過(文章裡有指令),產生 .asc 檔案,再把檔案內容貼上去,送出即可。

上傳可參考這篇:Uploading a package to a PPA,package 有些要注意的事項,例如 changelog,在上面那一篇有說明,就是一般 debian changelog 裡是寫 unstable、experiment,在這裡要改為 lucid、hardy 等。
大致摘要如下:

  1. 準備好你要上傳的 package,用 dpkg-buildpage -S -k<your_gpg_private_key>,做出 source package。
  2. 到上一層目錄,找到 P_V-0_source.changes (P 表示你的 project name,V 表示版本)
  3. 上傳:輸入 dput ppa:your_ip-id/ppa P_V-0_source.changes
  4. 上傳順利的話,接下來就等回信了~

dput 預設是用 ftp 上傳,如果不行,可以試試 sftp:

  1. profile 填 ssh key
  2. 新增 ~/.dput.cf ,裏面放:
    [my-ppa-lucid]
    fqdn = ppa.launchpad.net
    method = sftp
    incoming = ~<your_launchpad_id>/<ppa_name>/ubuntu/<ubuntu_code_name>
    login = <your_launchpad_id>
    allow_unsigned_uploads = 0
    

    ,your_launchpad_id、ppa_name、ubuntu_code_name 不要忘了替換掉,ubuntu_code_name 就看你裝的 ubuntu 版本,填 lucid、hardy…等等的

  3. 上傳指令改用 dput my-ppa-lucid P_V-0_source.changes

回信不會那麼快,要稍微等一下,如果有問題,裏面會有錯誤訊息,不知道怎麼辦的話,很簡單,到 Questions for Soyuz 找答案。
最後成功的話,會有回信說 Accept,這時候再到你的 ppa 頁面,就會看到 package 了,不過這時候還在 building,需要等一陣子。
到這裡,應該就大功告成了。之後就可以很方便的用 add-apt-repository 來把自己 ppa 加進去,然後安裝、升級 package 啦~

busybox 的 mdev

mdev 實際上算是 udev 的替代品,代碼看起來很簡單。
下 mdev -s 會 enumerate /sys/class 下的檔案,並據此去建立 /dev 下的 device 檔案。如果 /etc 下有 mdev.conf,它會先參考這裡的設定,來決定 device 的 permission 與 user/group owner。
雖然說是 /sys/class,但是 /sys/class 下的檔案實際上都是 symbolic link,指向 /sys/device 下的檔案。
也可以下這行

echo /sbin/mdev > /proc/sys/kernel/hotplug

,直接讓 kernel detect 到新裝置時,就請 /sbin/mdev 去 /dev 建立新的 device 檔案。
kernel 是怎麼傳遞資訊給 mdev 的呢?答案是透過環境變數,kernel 在執行 /sbin/mdev 之前,會先填好 ACTION、DEVPATH跟SUBSYSTEM 這3個環境變數之後,再去呼叫,所以 mdev 才會知道要做些什麼。這也就是在 shell 下輸入 /sbin/mdev 會印出使用說明的原因,因為沒有這3個環境變數,mdev 就只印出說明了。
kernel mode 下的呼叫,還牽涉到 FIRMWARE 的部份,不過這邊目前沒用到,只有大致看一下。大底來說,就是如果有 FIRMWARE 環境變數時,他會試著去讀取 /lib/firmware/xxx 的 firmware 檔案內容,然後檢查 /sys/$dev/loading 這檔案,有了這檔案以後,再寫入 1,接著再把讀到的內容寫到 /sys/$dev/data 這個檔案裡去,完成載入外部 firmware 的動作。
程式相當的精簡,有空再來看看 udev。

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,這樣就能正常使用掃描器了。