2010年11月9日 星期二

玩flashgame訓練邏輯能力--lightbot2

真是久違了的好遊戲!!沒想到出了第二代!!趕快來玩玩吧~~~~
如果你沒有玩過第一代的話,請參考玩flashgame訓練邏輯能力--lightbot,喜歡寫程式的朋友一定會瘋狂的啦~~

2010年11月8日 星期一

LPIC-1 passed

9/27我趕在出國前趕快把LPIC考一考,11/2巨匠email通知我可以來領取我的LPIC-1證照了。從考上到領到證照,大約35天左右。不過我人在澳洲,所以請老婆代領。考過LPIC-1其實沒有想像中的興奮,因為RHCE跟NCLP這類實機考試都通過了,考LPIC只是把先前的考試卷在出國前趕緊用掉而已。不過話雖如此,我覺得LPIC的證照還蠻好看的。

9/24考101,才考700分...9/27考102,竟然630...更低


過了一天才收到信

這張卡片真的很漂亮唷!

2010年10月28日 星期四

Microsoft真的害怕OpenOffice.org!!

你有看過一間全世界最賺錢的公司花大錢設計廣告來打一個可能很多人都沒聽過的組織嗎?我想,這部影片用來描述欲蓋彌彰是在恰當不過了。

話說回來,我的碩士論文也是用OpenOffice.org 2.0來寫的,剛開始還叫OpenOffice.org,真的是世界難用;後來的2.0以後就好很多了,沒有遇到什麼大問題。真的要互相來質疑的話,用office2007來開office97來試試看會不會跑掉,然後在用OpenOffice.org3.0來開sxw版面是否正常,然後看看誰能直接的把office文件轉成pdf?

延伸閱讀:
中國網軍新攻擊,惡意程式竄改Word設定偷機密

2010年10月11日 星期一

Linux+MacOSX+Windows Triple Boot on Macbook Pro

keywords:Linux, Mac, XP, 多重開機, MacBook pro

我在2009年買了一台15吋的MacBook pro,一直到最近才開始比較有時間去玩他。MacOSX本身當然沒有什麼大問題,但是想到要在MacBook pro上面裝linux跟WinXP就感到很刺激,可以預期的是,因為是intel的cpu,所以os本身應該沒有大問題;但是週邊設備(例如解析度、亮度、觸控版、音效、視訊、有線/無線網路, etc.)就真的很難保證。本文僅作為一篇經驗分享文,沒有太多的技術在內,僅作為筆記分享給需要的看官。

EFI與BIOS

BIOS(Basic Input/Output System)幾乎是普羅大眾學習電腦都會碰到的東西,有著跟pc一樣古老的歷史。簡而言之,他掌控了開機時的自我檢測,包含電壓、記憶體、cpu、硬碟等週邊設備。雖然所有配備都日新月異的在進步,但是bios卻是依然停留在16位元的環境。由於bios自我檢測之後會自動尋找第一個開機的裝置,如果是硬碟,則會尋找他的MBR(master boot record)。而MBR又有非常多的限制,只能有四個主要分割區,如果要安裝多個系統則需要小心維護MBR。這麼多年下來,bios的缺點依然沒有被改進。目前支援GUID的作業系統可以參考wikipedia的資料
EFI(Extensible Firmware Interface)不但完全擁有BIOS的功能,而且他其實就是一個小型的os,扮演作業系統與韌體之間溝通的角色。能載入硬體的驅動程式,所以在EFI裡可以使用滑鼠、鍵盤。EFI使用的是GUID的分割表方式(或類型),有別於BIOS使用的是ms-dos的分割表模式,使得硬碟能有128個主要分割區,開機管理程式也不再放在MBR(當然,EFI也可以支援MBR),而是會放在GPT(GUID partition table),開機時由EFI去控制要開進哪一個含有作業系統flag的分割區。比起傳統的MBR,要安裝多個os,GPT確實方便且強大多了,只是他會佔用第一個主要分割區,而且不會自動隱藏。

行前準備

  1. MaxOSX Snow Leopard安裝光碟
  2. Windows XP安裝光碟
  3. MintLinux 9安裝光碟
  4. 決定讓三個os都能讀取的檔案系統:hfsplus
  5. 完全不使用bootcamp
  6. 決定安裝順序:MacOSX->Windows->Linux

MacOSX的安裝與硬碟配置

我是從頭重新安裝MacOSX的,為此我還買了一個1T的硬碟來取代裡面原本的250G小硬碟--對於重度使用virtual machine的我,使用固定大小的映像檔需要很大的空間。由於1T的硬碟比較厚,所以MacBook/MacBook Pro系列的才能裝,Air可就裝不下了!

如果你有安裝Leopard(10.5)的經驗--兩片DVD,總共安裝時間大約要兩個小時,非常辛苦;Snow Leopard(10.6)是大幅修改kernel(雖然Apple說是重新撰寫kernel),使得10.6有較好的效能、功能以及較短的安裝時間(約30分鐘左右)。

10.6是我額外去買的,NT 1090,比起windows,我覺得便宜又值得。
安裝MacOSX時,請先到磁碟工具裡,把該硬碟分割成四個分割區(事實上MacOSX會分成五個分割區,第一個就是GPT所佔的分割區啦,約200MB左右)。我對於這顆硬碟的劃分是:120G的hfs+(journalled)給MacOSX,40G的ext4給LinuxMint,100G的fat-32給windows,剩下所有的空間都切成hfs+(journalled),到時候可以在linux裡讀寫hfs+分割區。分割時,給定一個辨識度高的標籤非常重要。

(上圖是我安裝完MacOSX之後在額外安裝NTFS-3g才會有的結果,關於ntfs-3g,請詳閱後面內容。而MacOSX預設並不支援linux的檔案系統,因此就暫時格式化成fat-32或是hfs+都無所謂。)
不選擇其他檔案系統當成共用的分割區,有如下的原因:

  1. Windows僅拿來打電動用,並不拿來上網或是工作,甚至是聽音樂看影片也不會,因此可以讀取hfs+就可以。
  2. 在Linux跟MacOS下讀寫NTFS都必須透過fuse/macfuse,速度很慢;Linux目前對於hfs+讀寫支援得相當不錯,速度也很不賴(寫入稍慢,刪除非常快!!)
  3. hfs+是MacOSX預設的檔案系統格式。vfat非常容易造成磁區破碎分佈的情形,而且單一檔案大小又有4G的限制。
(當然如果你有其他的需求,自然要依據您的需求作調整。)
劃分安裝MacOSX的分割類型時,請選擇GUID,否則會無法順利安裝MacOS;另外我會建議安裝MacOSX的分割區最好是MacOS類型+日誌式+區分大小寫,這樣屆時在linux底下才會有比較高的相同感--畢竟linux下的檔案系統都是區分大小寫的。

在劃分時,我遇到無法重新格式化或是切分割區時,我不熟MacOSX底下的指令,我只好塞入linux的live CD去把所有分割區刪掉,再重新開進mac安裝光碟以進行安裝。由於linux的fdisk指令不支援GPT,你必須使用parted/gparted來製作一個可以安裝Mac的分割表。

由於需要跟linux共用資料,因此如果每個檔案都有不同的uid/gid是很麻煩的事情。你可以選擇讓Linux配合BSD的傳統配置(uid/gid=501/20),也可以讓Mac配合linux--我選擇後者。在Debian系列的linux裡,第一個使用者的uid/gid都會是1000,安裝完MacOSX之後,我們就把Mac裡的uid/gid改成1000吧!

sudo su -
dscl . -change /Users/maxsolar UniqueID 501 1000
dscl . -change /Users/maxsolar PrimaryGroupID 20 1000
chown -R 1000:1000 /Users/maxsolar
如果沒有錯誤訊息,表示變更已經完成。請不要作任何動作,直接重開機。
再次進入Mac--這個時候我的gid=1000並沒有相對應的群組名稱,但根本無關痛癢--unix世界是認uid/gid,而非名稱。由於我有使用終端機的需求,因此有兩行需要加入~/.profile:
export PS1="\[\033[01;32m\]\u@\h\[\033[01;34m\] \w \$\[\033[00m\] "
alias ls='ls -FG'
如果一切ok的話,請按左上角的蘋果,點選軟體更新,讓系統保持在安裝好patch的狀態。

ntfs-3g for Mac的安裝

NTFS檔案系統在linux下穩定的讀寫已經行之有年,透過fuse的技術,我們一樣可以在user space使用NTFS。mac上使用ntfs也是透過fuse,但是卻是跟linux世界不同的fuse;為了有所區別,Tuxera公司把它稱為MacFuse,總之是相同的原理,讓Mac可以認識ntfs並且在上面進行讀寫。速度不能跟原生的hfsplus相提並論就是了。

Windows的安裝

務必確定windows的分割區是最後一個(或是第四個)分割區。由於Windows只認得MBR,在MBR與GPT混雜(hybrid)的情況下,WindowsXP必須要在最後一個(但不能超過第四個)分割區才能成功安裝,否則會出現:

"下列檔案遺漏或損毀,無法啟動Windows:
system32\hal.dll
請重新安裝一份上列檔案的拷貝"
事實上你的windows裡是有這個檔案的,boot.ini的設定也完全沒錯,但如果不是把windows放在最後一個(最多不超過四)磁區,這個問題就會一直存在。
假設你的分割區已經配置完成,塞入xp光碟並重開機之後,按住c不放以進入光碟開機,並依照你的規劃選定windows要安裝的分割區。

(利用Mac的diskutil工具都會有128MB的間距,或許有他的意義吧!?只要注意GPT會佔去第一個分割區,我說的第四個是包含GPT分割區。)
安裝完成後,請update以安裝所有修補程式,並且塞入Snow Leopard光碟,裡面包含支援Macbook Pro的所有驅動程式。

安裝好bootcamp驅動程式之後,會發現可以看到MacOSX的hfsplus分割區了!但是第五個分割區卻讀不到,這就是windows XP只認得MBR的證據--只認得4個主要分割區,而GUID則全為主要分割區,所以我所標示的DATA分割區在windows裡是看不到的。不過即使裝了驅動程式,hfsplus檔案系統對windows來說還仍然是read only,需要安裝像MacDrive這類商用軟體才能在windows讀寫hfs檔案系統。

linux的安裝

筆者安裝的是LinuxMint 9,我想其他套linux也是大同小異,只需要額外安裝一些套件即可,只要注意鍵盤格式要選擇USA-Macintosh,以及開機管理程式安裝在自己的root分割區(本例而言是sda3)

LinuxMint是基於ubuntu的封裝版,因此就跟ubuntu一樣,安裝後會自動顯示偵測到廠商私有的驅動程式。我的這台MacBookPro是nvidia Geforce 9400M;當系統剛安裝好時,xorg是載入nouveau(opensource的nvidia晶片驅動程式)可以使用F1/F2調節亮度,但是安裝完nvidia私有驅動程式之後,螢幕亮度會到達100%,而且沒有任何控制鍵可以調低亮度。
為此,我們必須手動使亮度降低才能繼續工作:

smartdimmer -s 20
smartdimmer是nvidia控制亮度的一個小程式。當xorg載入的是nvidia的模組時,原本在gnome裡面所有控制亮度的小工具都失效了,也因此只好手動調整亮度。-s表示設定(set),20表示20%的意思。事實上我們還需要一些步驟來修改Macbook,務必執行上一步驟使亮度降低,否則眼睛一定受不了。

增加Mactel-PPA套件庫:

add-apt-repository ppa:mactel-support
aptitude會自動增加套件庫並且下載公開金鑰,一切都是自動化。當然,請務必更新套件庫:
aptitude update
我們來安裝一些必要的套件:
aptitude install applesmc-dkms bcm5974-dkms gnome-power-manager isight-firmware-tools macfanctld mbp-nvidia-bl-dkms nvidia-bl-dkms pommed xfree86-driver-synaptics xserver-xorg-input-synaptics xserver-xorg-video-intel pommed gnome-alsamixer
以上的套件除了安裝for macbook週邊的firmware之外,還需要pommed daemon幫助我們調整預設亮度。請修改/etc/pommed.conf
#
# Configuration file for pommed
#

# General configuration
general {
# fnmode: functions keys first (no need to use fn) or last
# Value is either 1 or 2, effect is hardware-dependent
fnmode = 2
}

# sysfs backlight control
# nVidia machines, will fall back to nv8600gmt if not supported by the kernel
lcd_sysfs {
# The sysfs backlight control is a generic interface provided
# by the Linux kernel for backlight control on most graphic cards.
# The brightness range can differ depending on the hardware.

# initial backlight level [12] (0 - 15, -1 to disable)
init = 10
# step value (1 - 2)
step = 2
# backlight level when on battery [6] (1 - 15, 0 to disable)
on_batt = 8
}

# ATI X1600 backlight control (MacBook Pro v1 & v2)
lcd_x1600 {
# initial backlight level [200] (0 - 255, -1 to disable)
init = -1
# step value (1 - 127)
step = 10
# backlight level when on battery [80] (1 - 255, 0 to disable)
on_batt = 80
}

# Intel 945GM, 965GM backlight control (MacBook v1-v4, MacBook Air v1)
lcd_gma950 {
# initial backlight level [0x6f] (0x1f - 0x94 usually, -1 to disable)
init = -1
# step value (0x01 - 0x20)
step = 0x0f
# backlight level when on battery [0x40] (0x1f - 0x94 usually, 0 to disable)
on_batt = 0x40
}

# nVidia GeForce 8600M GT/9400M/9600M GT backlight control
# (MacBook Pro v3-v5, MacBook v5, MacBook v2)
lcd_nv8600mgt {
# initial backlight level [12] (0 - 15, -1 to disable)
init = 10
# step value (1 - 2)
step = 2
# backlight level when on battery [6] (1 - 15, 0 to disable)
on_batt = 6
}

# Audio support
audio {
# Use amixer or alsamixer/alsamixergui to determine the sound card
# and the mixer elements to use here.

# sound card to use
card = "default"
# initial volume [80] (0 - 100%, -1 to disable)
init = -1
# step value (1 - 50%)
step = 10
# beep on volume change
beep = yes
# mixer element for volume adjustment
volume = "PCM"
# mixer element for muting the speakers
speakers = "Front"
# mixer element for muting the headphones
headphones = "Headphone"
}

# Keyboard backlight control
kbd {
# default value for automatic backlight (0 - 255)
default = 100
# step value (1 - 127)
step = 10
# ambient light thresholds for automatic backlight (0 - 255)
on_threshold = 20
off_threshold = 40
# enable/disable automatic backlight
auto = yes
# idle timer - switches off keyboard backlight automatically (timeout in seconds, -1 to disable)
idle_timer = 60
# idle tickms - timer tick rate in milliseconds
idle_tickms = 2000
}

# CD/DVD drive ejection
eject {
# enable/disable eject key
enabled = yes
# CD/DVD device
device = "/dev/dvd"
}

# Beeper
beep {
# enable/disable beeper
enabled = no
# WAV file to use (from pommed: goutte.wav or click.wav in /usr/share/pommed)
beepfile = "/usr/share/pommed/goutte.wav"
}

# Apple Remote - deprecated
# Note: the appleir driver is required for this to work; this driver has been
# obsoleted with Linux 2.6.22, so unless you are running a kernel < 2.6.22 or
# use the appleir driver on a newer kernel, this won't work.
# You should use LIRC instead.
appleir {
# enable/disable the appleir support
enabled = no
}
紅字的區域是我們要注意的地方--啟用fn鍵來控制最上面的快捷鍵,以及啟動時的預設亮度。設定完之後讓pommed重新啟動吧!
invoke-rc.d pommed restart
這個時候,你應該需要使用fn鍵來調整亮度了。

利用gnome-alsamixer關閉靜音狀態:
這個時候,我們的linux還是啞巴狀態,原因是預設輸出(front speaker)是mute狀態,文字介面的alsamixer並沒有辦法變更mute狀態,我們必須呼叫gnome-alsamixer才能關閉靜音:

確認mute沒有打勾,這樣linux就會有聲音了。當初為了找沒有發聲的原因,幾乎要翻遍了所有設定檔...

使linux可讀寫hfs檔案系統:
由於我們需要讀寫hfsplus,所以我安裝了以下的套件:

sudo aptitude install hfsplus hfsprogs hfsutils
安裝好之後,我們已經可以建立並掛載hfsplus檔案系統了。在linux下我們看看分割區長什麼樣子吧:
WARNING: GPT (GUID Partition Table) detected on '/dev/sda'! The util fdisk doesn't support GPT. Use GNU Parted.

Disk /dev/sda: 1000.2 GB, 1000204886016 bytes
255 heads, 63 sectors/track, 121601 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disk identifier: 0x00000000

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1               1          26      204819+  ee  GPT
Partition 1 does not start on physical sector boundary.
/dev/sda2   *          26       15691   125829120   af  HFS / HFS+
/dev/sda3           15707       20929    41943040   ef  EFI (FAT-12/16/32)
/dev/sda4           20945      121585   808392368   af  HFS / HFS+
我們在安裝時所切的三個分割區其實是sda{2,3,4},sda1則是GPT的所在。我不清楚MacOS為什麼要在每個分割區之間都隔了一個128MB大小的空間,好在我們只浪費三個128MB...
我希望在家目錄下新增兩個資料夾來放sad2與sda4,先改個/etc/fstab先:
LABEL=MacOSX   /home/maxsolar/MacOSX   hfsplus   defaults,user,users,force   0   0
LABEL=DATA   /home/maxsolar/DATA   hfsplus   defaults,user,users,force   0   0
由於linux並未正式支援hfs+的寫入,需注意參數必須加上force才能掛載為可讀寫模式。

Linux與MacOSX共用目錄架構:
在家目錄建立DATA與MacOSX兩個資料夾之後,可以用一般使用者身份掛載:

mkdir ~/{MacOSX,DATA}
mount ~/DATA
chown maxsolar:maxsolar ~/DATA
mount ~/MacOSX
chown maxsolar:maxsolar ~/MacOSX
chown能成功的關鍵在於你必須有在fstab加入force參數,否則永遠都會是read-only的檔案系統,即使你已經在Mac把你的uid/gid改掉了,也是枉然。

接著,我們希望家目錄下的一些目錄可以共享:

cd $HOME
rm -r Desktop && ln -s MacOSX/Users/maxsolar/Desktop .
rm -r Downloads && ln -s MacOSX/Users/maxsolar/Downloads .
rm -r Documents && ln -s MacOSX/Users/maxsolar/Documents .
rm -r Music && ln -s MacOSX/Users/maxsolar/Music .
rm -r Pictures && ln -s MacOSX/Users/maxsolar/Pictures .
rm -r Public && ln -s MacOSX/Users/maxsolar/Sites Public
ln -s MacOSX/Users/maxsolar/Movies .

啟用多點觸控:兩指翻頁而非側邊翻頁
到Preferences-->Mouse,到touchpad分頁啟動他!
到目前為止,兩套os檔案可以互通,無線網路、ethernet、視訊都可以使用了,要進入linux只需要按住option鍵,就可以選擇開機磁區;看起來十分美好不是嗎?

rEFIt的迷思

rEFIt是Mac機器上把EFI給視覺化的工具,簡而言之就是一個圖形介面的開機選單程式。我曾經下載了rEFIt來安裝,也成功的出現了三個作業系統的畫面,非常開心!

但是在後續開機進入MacOSX的時候,就無法成功開進MacOSX。在linux底下我用fsck檢查hfs+,發現有幾個block位置不正確,被修正之後才能順利開機;但是下次要進入MacOSX又是同樣的情形。所幸利用cmd+s進入單人模式,出現提示指令進行檔案系統的檢查,又發現有block位置異常,修復之後又可以開機了。我不知道這是什麼原因,但是在我移除rEFIt並且塞入Snow Leopard光碟修復MacOSX分割區之後,就在也沒有這種情形發生了;我不知道各位會不會有這種情形,但是我在也不會再去使用rEFIt了。進入MacOSX是預設值,要進入Linux/Windows只需要按住option鍵,會看到有另一個標示著『Windows』的硬碟,選擇他之後就會看見可愛的grub2選單了。

雖然硬碟裡有三個os,但是EFI的選單還是只會有兩個,且第二個一定是Windows(真鳥)。

一些未解的問題:

  • 鍵盤背光燈:
  • 鍵盤背光無法控制--你可以讓他暫時暗下來,但隨後又恢復亮度;只要鍵盤閒置他就會自動關閉,鍵盤一有動作,無論任何情況都會有50%的亮度顯現。
  • 在linux下的觸控版:
  • 在linux底下用觸控版移動視窗不能用兩點觸控,但可以使用雙擊+移動,也可以使用單點不放+移動。雖然不太方便,但習慣就好。
    無法支援MacOSX下的三指/四指觸控的功能,這點很可惜,即使在Windows底下也是如此。
  • 沒有print screen鍵、number以及insert鍵:
  • 沒有number跟insert鍵只是小問題,在windows打電動時需要trianer時,熱鍵不能用阿@__@|||,但是linux底下沒有printscreen鍵,每次都要點"Take Screenshots",很辛苦。
  • iSight會自動隨亮度變化,調整螢幕亮度:
  • 這應該算是好事,只是每次光線變化調整亮度都是調到100%,眼睛差點瞎掉,只好趕快用smartdimmer調低亮度,有點惱人。
  • 在linux環境下,耗電較兇:
  • 我自己的感覺是相同工作下,比MacOSX環境少了2小時左右。MacOSX在正常使用下幾乎可以到8小時的使用時間,linux大約只能撐6小時。
  • grub無法成功啟動MacOSX,無論是32或64bits
  • 如果我把linux的開機管理程式安裝在MBR,事實上是裝在GPT最前面128Kb的"Protective MBR"。然而這會導致Macbook一開機就進入了grub,而grub的預設值卻無法成功啟動MacOSX,我也不知道原因為何。但如果我安裝在sda3,那麼預設還是進入MacOS,如果要選擇進到XP或是Linux,就按個option鍵來切換。
    option鍵所能夠顯示的開機選單最多就三個:MacOS,非MacOS以及光碟機(或是firewire/USB),如果實體硬碟上有多個os,也只會顯示兩個而已,我覺得蠻不親切的,而且另一個系統的標籤預設是"Windows",我覺得蠻不好的,但找不到地方改。

參考文章:

2010年10月10日 星期日

在Linux上看數位電視

昨天被大通騙了之後,我決定今天再去店家換圓剛的電視棒。圓剛在網路上的評價一直都是很不錯的,這回我先做足了功課,想知道圓通科技有哪些電視棒是可以在linux下使用的,我在

這兩篇文章都提到了圓剛有支援linux的幾項產品,很令人振奮。於是我上圓剛的官方網站,確實有三款有支援linux:

我是在台中NOVA二樓的瑞爾鼎買大通HD-335的,我告知其中一個店員我要換貨,理由是大通的電視棒根本不支援linux,剛開始那店員還有點悻悻然的說,沒遇過linux的使者(沒辦法,台中linux方面的人才非常少);我告訴他,我就是因為他用斗大的面積標示他支援linux我才買的,如果不支援,沒有提供編譯driver的工具就不能說支援!
另一個比較資深的員工知道我要買圓剛的產品,剛好他店裡就剩下Volar這款,所以補了差額之後,我就把這隻電視棒帶回家測試,我還告訴那店員要跟公司反應,大通會騙人,linux客戶被騙一定會來反應的。

一間負責任的公司,就算不能提供驅動程式,起碼應該像nvidia一樣提供一個工具,讓使用者可以自動根據核心來編譯模組;圓剛清楚的提供了32/64位元的工具,也清楚的標註適用於OpenSuSE/mandriva/Fedora/Ubuntu。看到這裡我就放心許多,而且我相信大通可能沒有一個員工懂linux。

這個小工具其實是一個script,能自動偵測作業系統的Distribution,以root權限去執行他之後,他能夠呼叫該套linux的套件管理工具,自動安裝相依套件。

至此,電視棒的指示燈終於亮了起來,這個核心已經可以認得這個裝置了。但跟在windows不同的是,圓剛並沒有提供介面讓linux底下可以看電視,但是這完全沒有問題--Linux的世界多得是這類的軟體:

  • MythTV
  • 一個類似windows media center的東西,在ubuntu世界裡更有Mythubuntu,Fedora世界的MythDora以及Knoppix世界的LinHES。
  • FreeVo
  • FreeVo是一套開放原始碼的HTPC media center軟體,大部分的linux都有提供套件。
  • Me-TV
  • Me-TV是一套以gtk寫成的輕巧的電視軟體,支援DVB協定,筆者就是用這套來當作我的電視軟體。關於更多Me-TV的使用教學,可以參考用ubuntu看電視(三)--數位電視軟體Me-Tv之使用這篇好文。

很可惜我的位置收不到訊號,所以就沒有繼續嘗試;希望把這隻電視棒帶去澳洲,閒暇時可以聽聽那邊的新聞或節目...

圓剛也有三款電視棒支援MacOSX,很可惜的並沒有同時支援Linux。

電視棒別買大通(PX)!說linux適用是騙人的!

如果你正在選擇一項for linux的電視棒,很可能在訪間店家看到一個很醒目的標題:全球領先:99.5%系統支援度,Windows XP, vista, Linux

大通說支援linux是騙人的。

事實的真相是,無論你用哪一種型號,都無法支援目前現有的Linux。

首先,dmesg所顯示出來的型號是

[ 2607.447722] input: Afa Technologies Inc. AF9035A USB Device as /devices/pci0000:00/0000:00:06.1/usb2/2-2/2-2:1.1/input/input16
原來,晶片不是大通自己的,連驅動程式也是別家廠商的,這種商品的品質就令人大大地扣分,也意味這這是一間能力劣於其他廠商的公司。其次,你在afa的網頁上也完全無法找到關於linux驅動程式的任何訊息。第三,我所購買的HD-335雙頻數位棒所附的驅動程式光碟,裡面的LinuxDriver竟然還需要使用者自行編譯才能使用,這樣大通竟然敢光冕堂皇稱『支援Linux』? 第四,我是個看得懂Makefile的人。由於不同核心的標頭檔都有差異,而光碟片裡面的原始碼只能支援2.6.16~27;但問題是,現在所有的linux核心都不會只是這麼單純的版本號,況且現在主流都是2.6.32(所以大通認為新的linux使用者都該活該?!),我使用pae的核心更是完全不支援,google到AF9035的部份都是非常老舊且原始碼也已經失去連結,完全無法有任何參考幫助。

我太晚看到這篇文章,這位仁兄跟我一樣都是被大通騙的。如果你要選一款適合linux的電視棒,請千萬不要選擇騙人的大通,他的任何一款都無法讓你順利支援linux。

再拜託大家一次,不要在被這間公司欺騙。你不可能不修改Makefile而能編譯成功,使用者不會有時間去修改原始碼,除非你的核心版本就剛好吻合他的Makefile裡的範圍,否則你不可能成功編譯。

為了賣產品而無所不用其極的欺騙,是非常惡劣的一間公司。

2010年9月9日 星期四

Google Docs的有趣把戲

今天看到buzz上有一個好玩的新聞,就是google docs裡的document裡,只要你輸入Konami code(上上下下左右左右ba,相信玩過任天堂紅白機的朋友都會知道),google就會給你好玩的效果!據說不同瀏覽器有不同效果唷!


按完方向鍵跟BA之後,記得按下enter喔!上圖是javascript的效果,正在進行翻轉!


如圖所示,chrome的效果是左右相反,有些瀏覽器的效果則是上下顛倒。總之如果要翻轉回去的話,就在敲一次密碼囉!

2010年7月29日 星期四

RHCE PASSED

昨天痛苦而密集的複習了RHCE的部份,今天很幸運的通過了RHCE考試,加上檢查一次的時間約90分鐘可以好好做完題目。準備考試是痛苦的,但是成果卻是甜美的唷!

考試時間有三個半小時,但是實際上約一個小時內就可以做完,若加檢查一輪約一個半小時可完成。考試分成RHCT跟RHCE兩部份;如果第一部份有達70%分數但第二部份未達70%,則可以拿到RHCT;假設第二部份達到70%但第一部份卻未達70%,則是兩者都未通過。只有兩者都達70%以上才能拿到RHCE。

我把我的certificated number隱藏起來了。這就是RHCE的證照唷。希望有心想考RHCE的同好也能好好加油。

不過我大概不會想再考Redhat系列的認證了。因為考試的時候選擇國家,我們台灣的後面又被灌上a province of china,實在是非常落伍又泛政治化的一間公司。

2010年7月26日 星期一

Memory for crash kernel not within permissible range

這個問題會發生在所有Redhat-based Linux上,包含Scientific Linux,當然更包含了虛擬機器下的Redhat-based linux--在開機時出現:「Memory for crash kernel (0x0 to 0x0) notwithin permissible range」的訊息。


CentOS 的開機畫面。


RHEL5 的開機畫面。


ScientificLinux 的開機畫面。

這個警告寫得太像錯誤訊息,以至於雖然能夠成功開機,但是小心一點的管理員卻會擔憂這代表什麼意思。事實上,這是kdump(Kernel dump daemon)的訊息。這只是一個提示訊息(informational message),只要在init.d裡面拿掉kdump,或是安裝時選擇不安裝kdump即可。由於在開機時,系統不會知道你是否有為crash kernel保留一份記憶體位置,所以嚴格說來這是給kernel dump的服務所提供的訊息,是可以安心的忽略他的。如果你已經取消kdump開機時啟動,但仍然出現這個問題,那麼就當做沒看到吧!
雖然redhat的開發人員已經出面解釋這不是bug也可以從容的忽略他,但是許多人還是罵翻這個message,因為他讓太多網管人員花太多的時間在google這個近乎無用的訊息上。

論壇上許多網友建議的做memory test,更新或是手動編譯一個kernel都是於事無補的,請別浪費時間在這上面。

chroot初體驗

chroot是linux上一個可以讓你限制根目錄的有趣指令。在unix的世界裡,萬物的源頭就是/,就算是/的上一層目錄也還是根目錄本身。也就是說,任何使用者都無法離開/,就像是你永遠跨越不了宇宙的邊界,除非你已經不屬於該宇宙的一部分。

今天研究室學妹laptop上的opensuse遇到了一個有趣的問題。開機到stage2之後,無法掛載根目錄,其錯誤訊息是:『unknown "reiserfs" filesystem』。這在Redhat系列的linux並不意外,因為他們並不打算讓使用者不自訂kernel的情況下去使用reiserfs以及reiser4。反之,opensuse則是預設以reiserfs為檔案系統。很顯然是kernel不認識這個filesystem,但是是什麼原因使得kernel不認識filesystem呢?

我只是合理的猜測--更新kernel的過程中,或是在執行SuSEConfig之前更新的process被中斷。後來學妹也說因為太久沒更新,結果更新的清單一大疊,很可能是因為要回家前更新還沒有完成,所以就中斷這個process。跟Debian不同:Debian的更新是把所有的套件都抓下來之後再逐個安裝,Redhat/SuSE系列則是下載一個安裝一個,或許恰好是在安裝新的kernel時被終止,留下了一個沒有設定完成的kernel。

由於根檔案系統無法被掛載,我只剩下最基本的ls/mount等指令可用,連關機都不行@_@||| ...在Debian的liveCD裡,我無法利用rpm或是yast替opensuse安裝一個新的kernel上去;於是,我想到chroot。

mkdir /Virtual
mount /dev/sda1 /Virtual
mount --bind /proc /Virtual/proc
mount --bind /sys /Virtual/sys
mount --bind /dev /Virtual/dev
chroot /Virtual
這個時候,我就擁有了opensuse的環境,雖然此時此刻所使用的kernel是debian的。由於我急著希望有一個可以正常開機的kernel,因此就先更新kernel吧!
zypper update kernel-default
Debian重開機之後,原本的硬碟載入grub,到了stage2就可以成功掛載root檔案系統了!第一次使用chroot就有不錯的經驗,chroot真是好物!

延伸閱讀:
Tetralet大哥的好文:使用 debootstrap 來建立 CHROOT 環境

2010年6月24日 星期四

What did I see that?

最近為了趕WPGM的poster,幾乎每天都熬夜,加上RHCE考試在即,兩頭燒恐怕是凶多吉少。還好在上週末努力加班下,seismogram跟圖都出來了;加上老闆大力幫忙幫我修文字(其實是老闆全包啦),今天的poster還算順利,只是午後的一場暴雨,使得我回南港的路上淋得臭頭。

雖然考試在即,但我晚上還是去家樂福買了一箱黑麥汁來犒賞自己。結帳後,我聽到一個中年男子對手機大喊:

『What did I see that? What did I see that?』
我覺得這個句子很奇怪,應該是What did you see或是why did you say that,怎麼會是what did I see that呢?
後來那男子再喊一次,我才聽懂他說什麼...
『哇底地下室啦!哇底地下室啦!(台語)』

我一定是今天在WPGM被那些日本人的爛英文疲勞轟炸害的....

2010年5月5日 星期三

LVM2學習筆記

LVM2(Logical Volume Manager, version 2)的前身是LVM,他是由Heinz Mauelshagen於1998年在HP-UX上開發。他當初為了解決unix上分割區空間分配的問題而設計出這個管理程式。有了LVM,我們可以動態的調整空間的大小,大大縮短置換硬碟所需的downtime。這個鬼才現在任職於Redhat,目前正主持幾個跟software raid相關的計畫。目前我們所接觸到的教學文件大多是LVM2,但是因為已經全面取代了舊版的的LVM,因此還是以LVM稱之。

LVM的基本架構


上圖引用自鳥哥的私房菜,是一個相當有助理解的架構圖。本文僅適合非常熟悉LVM架構的讀者做為快速複習使用;如果談到PV/LV/VG等名詞您還得停頓一下,本文可能對您毫無幫助。下表則是我自己整理的指令列表,但僅列出一些常用的commands。

Function PV VG LV
新增 pvcreate vgcreate lvcreate
刪除 pvremove vgremove lvremove
擴大 vgextend lvextend lvresize
縮小 vgreduce lvreduce
變更屬性 pvchange vgchange lvchange
掃描 pvscan vgscan lvscan
詳列清單 pvdisplay vgdisplay lvdisplay
匯入/匯出 vgimport
vgexport
移動 pvmove
附註: 1. pvchangelvchange非常少用,本文也不會提及。
2. lvextend與lvreduce可以完全由lvresize來取代。
3. LVM不具備redundent的功能。如果想要有備援機制,請改用raid或是raid搭配LVM。
4. 目前的開機管理程式均無法辨識LVM,請獨立出/boot便於開機。

設計一個實驗

藉由實做是理解LVM最好的方式。本實驗的流程與目的如下:

  1. 利用虛擬機器產生一個2G大小的硬碟用來產生LVM類型分割區
  2. 練習建立與刪除PV
  3. 練習建立與刪除VG
  4. 練習建立與刪除LV
  5. 在LV上建立檔案系統,並且動態改變LV以及檔案系統大小
  6. 實做LVM的snapshot功能並還原
  7. 以新硬碟取代舊硬碟
  8. 系統重灌或是硬碟轉移,LVM的轉移方案


目標1:產生LVM類型分割區

我先前已經有一個2G的虛擬硬碟,我不想用fdisk慢慢組分割區,直接刪掉他的partiton table以利我們馬上就能使用:

dd if=/dev/zero of=/dev/hdb count=1
接著利用fdisk產生四個分割區,假設分別是hdb{1,2,5,6},各為200M, 300M, 300M以及1200M。

把partition ID改成8e(LVM format)。改完後,別忘記更新核心的partition資訊:

partprobe /dev/hdb
檢查一下核心是否已經更新partition table了:
cat /proc/partitions
major minor  #blocks  name

   3     0    8388608 hda
   3     1    8281476 hda1
   3     2     104422 hda2
   3    64    2097152 hdb
   3    65     196024 hdb1
   3    66     293328 hdb2
   3    67          1 hdb3
   3    69     293296 hdb5
   3    70    1314400 hdb6
如果能看到hdb的1,2,5,6號partition,那就表示可以進行下一步。

目標2:PV的建立與刪除

pv就是構成LVM最基本的元素,他可以是一整顆硬碟,也可以是一個partition。(實作上如果要把整顆硬碟加入LVM裡,還是建議至少做一個partition再加入)要把數個硬碟或是分割區加入PV裡,需要用pvcreate:

pvcreate /dev/hdb{1,5}
把某個分割區從pv裡移除,使用pvremove:
pvremove /dev/hdb5
查看現有的pv有哪些,可以用pvdisplay得知:
  "/dev/hdb1" is a new physical volume of "191.43 MB"
  --- NEW Physical volume ---
  PV Name               /dev/hdb1
  VG Name               
  PV Size               191.43 MB
  Allocatable           NO
  PE Size (KByte)       0
  Total PE              0
  Free PE               0
  Allocated PE          0
  PV UUID               OKTpgY-M2tF-KykI-xPB1-xJae-UMqI-XKvJ5U
可以得知我們現在只有一個分割區加入到pv裡。我們把hdb{2,5}也加到pv裡,讓實驗繼續進行。
pvcreate /dev/hdb{2,5}

目標3:VG的建立與刪除

對於作業系統來說,vg相當於傳統硬碟的地位;把許多個傳統分割區加入pv裡,然後建立一個vg組成一個大的虛擬硬碟。現在我們建立一個名為myVG的vg,由hdb1及hdb2組成:

vgcreate myVG /dev/hdb{1,2}
此時可以用vgdisplay以及vgscan觀察之:
  --- Volume group ---
  VG Name               myVG
  System ID             
  Format                lvm2
  Metadata Areas        2
  Metadata Sequence No  1
  VG Access             read/write
  VG Status             resizable
  MAX LV                0
  Cur LV                0
  Open LV               0
  Max PV                0
  Cur PV                2
  Act PV                2
  VG Size               472.00 MB
  PE Size               4.00 MB
  Total PE              118
  Alloc PE / Size       0 / 0   
  Free  PE / Size       118 / 472.00 MB
  VG UUID               VyMTQc-1Cuy-z2UG-jXyF-LFvx-vRY2-oQaJLd
由上面資訊可以得知,我們只有一個vg叫做myVG,大小為472MB,為118個PE的大小,目前完全沒有PE被使用。
再把hdb5加入到這個vg裡:
vgextend myVG /dev/hdb5
然後再使用vgdisplay/vgscan觀察變化。要把某個傳統分割區從vg裡開除,則使用vgreduce:
vgreduce myVG /dev/hdb1
要把整個vg砍掉重練,就使用vgremove:
vgremove myVG
為了後續的實驗,趕快恢復原狀吧:
vgcreate myVG /dev/hdb{1,2,5}

目標4:LV的建立與刪除

從一個vg裡建立一個lv,就好比從一顆硬碟建立分割區,你需要清楚的知道分割區從哪顆硬碟建立,以及分割區的大小。利用lvcreate建立lv:

lvcreate -L 500M -n myLV myVG
也可以特別指定vg裡的某個pv:
lvcreate -l 125 -n myLV myVG /dev/hdb1
上例表示使用myVG的其中一個pv的空間來建立lv,以-L指定大小,-l指定PE數量;預設1PE=4MB。需特別注意的是,lv一旦建立,想要使用lv則必須像是寫一個分割區一樣寫完整的路徑。以myLV而言,他的完整路徑將會是/dev/myVG/myLV或是/dev/mapper/myVG-myLV
現在擴大lv成為600M:
lvextend -l +25 /dev/myVG/myLV
上例會再從vg裡剩餘的空間去分配。同樣的,要縮減lv也很容易:
lvreduce -l -5 /dev/myVG/myLV
如果-l後面沒有接正負號,則表示改變大小成指定值。由於lvextend只能接正值,lvreduce後面只能接負值,這兩個指令可以完全被lvresize取代,例如上面兩個例子完全等於:
lvresize -l +25 /dev/myVG/myLV
lvresize -l -5 /dev/myVG/myLV
因此,往後的實作將只使用lvresize。為了使實驗繼續進行,我們把myLV的大小設定成600M吧:
lvresize -L 600M /dev/mapper/myVG-myLV

目標5:動態改變LV以及檔案系統大小

建立好lv(想像成建立好傳統的分割區)之後,就必須在上面搭載檔案系統以供使用。請把lv當成一個分割區一樣的來進行格式化吧!

mkfs.ext3 -L "myLV" /dev/mapper/myVG-myLV
mount -t ext3 LABEL=myLV /mnt
截至目前,這個lv已經正式上線使用了。不過我們可以藉由vgdisplay以及df得知,其實myLV並沒有用到全部的可用空間。LVM最強大的功能之一,就是允許線上擴大容量。由於lv是底層,檔案系統在上層,因此要擴大檔案系統必須lv先擴大,filesystem再擴大。
想要擴張lv到最大容量,你可以查看vg剩餘多少PE然後擴大,或是直接擴大到全部可用範圍:
lvresize -l +100%FREE /dev/myVG/myLV
或是指定完全使用某幾個pv:
lvresize -l +100%PVS /dev/myVG/myLV /dev/hdb{2,5}
由此可見,LVM的運用非常強大,且自訂性極高。
擴充lv的容量之後,接著就可以擴充檔案系統:
resize2fs /dev/myVG/myLV [700M]
如果不指定擴充大小,則resize2fs會自動擴充到全部可用範圍。

要縮減lv大小則與擴充相反--必須先縮小上層的filesystem,再縮小底層的lv。如果你不照此順序進行,lv上面的資料會全部付之一炬。縮減lv不支援線上進行,而且縮減到有寫入資料的部份也會造成檔案lost,必須小心為之:

umount /mnt
fsck.ext3 -f /dev/myVG/myLV
resize2fs /dev/myVG/myLV 500M
lvresize -l -25 /dev/myVG/myLV
mount LABEL=myLV /mnt
依序縮減filesystem以及lv大小後,就可以掛載後正式上線工作。

目標6:實做LVM的snapshot功能

Solaris的ZFS檔案系統擁有非常卓越的snapshot功能,雖然LVM的snapshot沒有Solaris那麼powerful,但是也是一樣功能強大且便於使用。snapshot目前僅支援lv,vg的snapshot功能還尚未實做出來。
快照檔其實就是一個lv,他會與檔案系統共用『未變更』的PE,因此snapshot必須與原本的lv在同一個vg裡面。

上圖引用自鳥哥的私房菜,說明了snapshot可以很小的原因就是與原本的lv共用未變更的PE。 他的大小約為想執行snapshot的lv的15%~20%的大小。檢查我們的lv大小:

lvdisplay | grep Size
以我們的例子而言,我們的lv約750MB,製作一個snapshot約需要150MB,恰好目標5的末段我們縮減了檔案系統,vg也還有約156M的空間可以用。我們讓snapshot就坐在這156MB上:
lvcreate -L 156M -s -n `date +"%Y-%m%d".snap` /dev/myVG/myLV
產生了具有日期為檔名的快照檔之後,可以以此作為系統還原備份之用。例如半年後想要回到snapshot的狀態,只要把該snapshot掛載上去就好。
umount /mnt
mkdir /mnt/{myLV,date}
mount /dev/myVG/2010-0505.snap /mnt/date
mount LABEL=myLV /mnt/myLV
雖然snapshot只佔有156MB的空間,但是對於核心而言,他就是一個lv的clone,因此你從df看到的大小是一樣的:
/dev/mapper/myVG-myLV
                      591M   17M  545M   3% /mnt/myLV
/dev/mapper/myVG-2010--0505.snap
                      591M   17M  545M   3% /mnt/date
把snapshot給umount之後,再來進行一些測試!
umount /mnt/date
for words in $(seq 1 1000000); do
      echo 'I love peace world!!' >> abc.txt
done
cp -r /etc/httpd /mnt/myLV
以上,我們做的所有更動都會紀錄在snapshot檔裡,可以用lvdisplay /dev/myVG/2010-0505.snap來觀察:
  --- Logical volume ---
  LV Name                /dev/myVG/2010-0505.snap
  VG Name                myVG
  LV UUID                JDGmIg-m0qW-M0VK-Gem1-4bqA-DEyS-83FtbL
  LV Write Access        read/write
  LV snapshot status     active destination for /dev/myVG/myLV
  LV Status              available
  # open                 0
  LV Size                600.00 MB
  Current LE             150
  COW-table size         156.00 MB
  COW-table LE           39
  Allocated to snapshot  13.32% 
  Snapshot chunk size    4.00 KB
  Segments               1
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     256
  Block device           253:1
請特別留意"Allocated to snapshot"已經佔了13.32%,由此可知LV的snapshot有個關鍵的要素:所容許的異動大小必須小於snapshot的大小。往後將此snapshot掛載,便可以取出製作快照前的檔案作為備援使用。snapshot被掛載的時候會停止紀錄變動,請非常留意。

刪除一個snapshot就是刪除一個lv:

lvremove /dev/myVG/2010-0505.snap

目標7:以新硬碟汰換舊硬碟

以上已經展示過LVM線上擴大檔案系統及lv的卓越能力,也展示過製作snapshot的功能,現在則是模擬淘汰一個快要壞掉的舊硬碟,換上一個又大又新的硬碟上去。我們假設舊硬碟是hdb1(200M),新硬碟是hdb6(1200M),首先必須把新硬碟加入:

pvcreate /dev/hdb6
vgextend myVG /dev/hdb6
pvmove -v -i 2 /dev/hdb1 /dev/hdb6
上述的指令顯示線上加入一個新硬碟到vg裡,然後把hdb1裡的PE都移動到hdb6裡,並且每隔2秒顯示詳細訊息:
    Finding volume group "myVG"
    Archiving volume group "myVG" metadata (seqno 4).
    Creating logical volume pvmove0
    Moving 47 extents of logical volume myVG/myLV
    Found volume group "myVG"
    Updating volume group metadata
    Suspending myVG-myLV (253:0) with device flush
    Creating myVG-pvmove0
    Loading myVG-pvmove0 table (253:1)
    Resuming myVG-pvmove0 (253:1)
    Creating volume group backup "/etc/lvm/backup/myVG" (seqno 5).
    Checking progress every 2 seconds
  /dev/hdb1: Moved: 14.9%
  /dev/hdb1: Moved: 34.0%
  /dev/hdb1: Moved: 46.8%
  /dev/hdb1: Moved: 57.4%
  /dev/hdb1: Moved: 66.0%
  /dev/hdb1: Moved: 76.6%
  /dev/hdb1: Moved: 89.4%
  /dev/hdb1: Moved: 100.0%
    Found volume group "myVG"
    Loading myVG-myLV table (253:0)
    Suspending myVG-myLV (253:0) with device flush
    Suspending myVG-pvmove0 (253:1) with device flush
    Resuming myVG-pvmove0 (253:1)
    Removing temporary pvmove LV
    Writing out final volume group after pvmove
    Creating volume group backup "/etc/lvm/backup/myVG" (seqno 7).
由於是每隔兩秒顯示一次訊息,因此訊息很長。
vgreduce myVG /dev/hdb1
pvremove /dev/hdb1
lvresize -l +100%FREE /dev/myVG/myLV
resize2fs /dev/myVG/myLV
最後的兩行指令,就是把hdb1完整的從LVM裡面拿掉,接著就是找個可以允許短暫downtime的時間,把舊硬碟抽走。別忘了新硬碟容量大多了,別忘了先把lv變大,在擴大filesystem!

目標8:LVM的轉移方案

假設今天想要換新的機器或是重灌系統,但是lvm裡面的資料還是要保留下來,我們該怎麼處理呢?大致的流程如下:

umount->vgchange(deactivate)->vgexport->系統重灌->vgimport->vgchange(activate)->mount

承續剛才的狀況:

umount /mnt/myLV
vgchange -a n myVG
vgexport myVG #可以藉由vgdisplay觀察是否有exported!

上述的指令便是停止vg的運作,因此所有在vg上的lv也都會全部終止運作,因此假設你在vg上切不只一個lv,則需要把所有掛載點都umount之後,vgchange才有可能終止活動。我終止這個vg並且匯出vg之後,關閉虛擬的os並開啟一個新的os,假設是SLES11好了;我們可以在SLES11上面利用vgdisplay找到這個vg:

vgimport myVG
vgchange -a y myVG
mkdir /export
mount /dev/myVG/myLV /export
如此一來便可以順利完成轉移。


參考文獻:

1. Redhat Enterprise Linux系統管理寶典 進階篇(陳永昇),第八章
2. Logical Volume Manager(一)(二)(林彥明)
3. RHEL3/4 之Logical Volume Manager(林彥明)
4. 鳥哥的私房菜:Logical Volume Manager

2010年5月3日 星期一

[轉載]Steve Jobs的公開信談Apple拒絕flash

全文轉載自:Steve Jobs談為何蘋果討厭吃Flash(完整公開信,中文版),ZDnet Taiwan


蘋果跟Adobe有很深的關係,我們還曾在他們草創的車庫裡跟Adobe創辦人見過面,蘋果是他們第一個大客戶,把他們的Postcript語言用在我們新的Laserwriter印表機中。蘋果曾經投資過Adobe,也曾一度擁有Adobe 20%股權多年。我們曾密切合作創新推出桌面出版,雙方都有過許多甜蜜時光,但過了那段蜜月期後,我們就漸行漸遠了,蘋果歷經瀕死經驗,Adobe則以Acrobat產品打入企業市場。今日,我們依然共同服務雙方共有的創意客戶群,Mac用戶大概買了半數Adobe的Creative Suite產品,但除此之外,雙方已經殊少交集了。

我之前很想寫出我對Adobe Flash產品的想法,好讓大家能更瞭解為何我們不想讓Flash進到iPhones、iPods與iPads。Adobe一直認為我們的決定是出於商業考量,他們說我們這麼做是要保護App Store,但其實這一切都只是出於技術考量而已。Adobe說我們是封閉系統,而Flash是開放的,但事實根本相反,我在此解釋一下。

首先是開放問題。

Adobe的Flash產品是100%專屬的,僅能由Adobe提供,未來怎麼發展、價格等也全看Adobe自己的決定。雖然Adobe的Flash產品廣為使用,但這不代表他們是開放的,因為這個技術由Adobe自家掌控,從任何角度來看,Flash都是封閉系統。

蘋果自己也有很多專屬產品,不過iPhone、iPod與iPad雖然是封閉的,但十分相信所有跟Web有關的標準都應該公開。蘋果捨棄Flash,改用HTML5、CSS與JavaScript,這些都是公開標準。蘋果的行動裝置要用最高性能、最低耗電的部署方式推出。HTML5(蘋果、Google等都已經採用此一新標準)可讓Web開發者建立更先進的繪圖、字型、動畫與轉換,完全不需仰賴第三方瀏覽器外掛(不像Flash那樣)。HTML5完全開放,由標準委員會控制,蘋果也在其中。

蘋果甚至也自創Web的開放標準,比如,蘋果弄了一個小的開放原始碼計畫稱為WebKit,這是一個完整開放原始碼HTML5呈現引擎,是Safari網頁瀏覽器的核心。WebKit目前已經廣為採用,Google在Android的瀏覽器也有採用,Palm也是,Nokia也有用,RIM(BlackBerry)則已經宣布未來會採用。現在幾乎除了微軟以外,其他主要智慧手機瀏覽器都是使用WebKit。蘋果把WebKit技術開放出來,讓行動網路瀏覽器立下了標準。

Adobe也不斷說蘋果行動裝置無法存取完整的Web,因為75%的網路影片都是以Flash製作。但他們沒說的是,這些影片同時也都有提供更現代的格式:H.264,可在iPhone、iPod與iPad上觀看。YouTube(佔了網路影片40%市佔率)便可用在一款蘋果行動裝置都有搭配的應用程式中,iPad所提供的YouTube觀看經驗看是無與倫比。若再加入Vimeo、 Netflix、 Facebook、 ABC、 CBS、 CNN、 MSNBC、 Fox News、 ESPN、 NPR、 Time、 The New York Times、 The Wall Street Journal、 Sports Illustrated、 People、 National Geographic、等等的影片,則iPhone、iPod與iPad用戶並沒有少看太多影片。

Adobe還宣稱蘋果機器無法玩Flash遊戲,這點說得沒錯,但還好我們的App Store有超過5萬種遊戲程式,其中還有許多都是免費的,事實上,iPhone、iPod與iPad可用的遊戲比其他任何平台都還要來得多。

第三,我們看中穩定性、安全性與效能

賽門鐵克最近特別指出Flash是2009年安全性最差的軟體之一,我們也一手深知,Mac當機的頭號理由都是出在Flash。我們曾跟Adobe合作修正這些問題,但這些狀況多年下來依然存在,我們不想因為加入Flash而降低iPhone、iPod與iPad的穩定性與安全性。

此外,Flash在行動裝置上的效能不佳,我們多年來多次要求Adobe提出一個可在行動裝置上擁有良好效能的Flash版本,但我們從來沒看過。Adobe曾公開表示Flash會在2009年初用在一款智慧手機上,之後改口說是2009年下半,之後又延至2010年上半,現在則已經變成2010年下半年了。我們相信最終他們還是會推出,但還好我們不需癡癡等待,誰曉得屆時效能如何?

第四點,電池效能問題

播放影片若要達成電池長效,則手機必須能在硬體中進行影片解碼,若用軟體解碼會耗費太多電力,許多新一代行動裝置中所使用的晶片都含有H.264解碼器,這是一種產業標準,用在每一台藍光DVD播放機中,包括蘋果、Google(YouTube)、Vimeo、Netflix等大廠也都有採用。Flash最近雖然也加入支援H.264,但目前所有Flash網站的影片則必須使用較舊版本的解碼器,無法用在行動晶片中,且必須用軟體來執行,這兩者的差異十分顯著,比如在iPhone上,H.264影片可播放10小時,但若用軟體解碼,則只能播放5小時電池就沒電了。

網站若以H.264來重新編碼影片,則不需使用Flash就能提供出來,他們可在所有瀏覽器播放,比如蘋果的Safari或Google Chrome,不需外掛,而在iPhone、iPod與iPad上觀看效果都很好。

第五,觸控問題

Flash主要是提供給使用滑鼠的PC,而非給使用手指的觸控螢幕,比如許多Flash網站都都使用所謂的「rollovers」(滑鼠移過去會有動作),但蘋果的多重觸控介面不使用滑鼠,也沒有rollover概念。多數Flash網站都得重新改寫才能支援觸控裝置。若開發者需要重寫Flash網站,那何不乾脆使用更現代的技術,如HTML5、CSS與JavaScript?

就算我們真的支援Flash好了,這也無法解決多數Flash網站都必須改寫才能支援觸控裝置的事實。

第六,最重要的理由

除了上述缺點外,我們不允許Flash進入我們的行動裝置還有個最重要的理由:Adobe希望開發者使用Flash來開發可在我們行動裝置上可使用的應用程式。

我們從過去慘痛的經驗得知,讓一個第三方軟體層介入平台與開發者之間,則最終出現的都是次等程式,阻礙平台的創新與進步。若開發者變得很仰賴第三方開發資料庫與工具,則若第三方不提供新功能,他們就無法享受到平台更新的好處,我們不可能讓第三方來決定他們何時會把更新提供給我們的開發者。

若第三方還提供跨平台開發工具,情況則變得更糟,第三方有可能會等到所有平台的更新版本都準備就緒了才會推出,不必然會為單一平台推出更新,結果開發者僅能使用最大公約數的功能。我們無法接受這種結果,開發者竟然是因為其他平台還沒準備好,所以無法使用我們的創新功能。

Flash是跨平台開發工具,Adobe的目標並非協助開發者撰寫最好的iPhone、iPod與iPad程式,他們的目標是協助開發者撰寫跨平台程式。而Adobe向來對於蘋果平台的更新十分緩慢,比如,Mac OS X已經推出快10年了,Adobe才剛在兩週前推出的CS5才完整採用。Adobe是所有主要第三方開發者中,最慢完整採用Mac OS X的。

我們的出發點很簡單,我們希望提供最先進創新的平台給我們的開發者,我們希望他們是直接站在我們的平台肩膀上,寫出全世界最好的程式。我們會持續強化平台,好讓開發者寫出更棒、更強大、更好玩、更實用的程式。這是三贏局面,我們可賣出更多機器,因為我們有最好的程式、而開發者也可接觸更多的客戶,而使用者則可享受到最多的程式選擇性。

結論

Flash是PC與滑鼠時代的產物,Flash的確是Adobe的成功之作,也因此我們能理解為何他們想把Flash延伸至PC之外,但行動時代講究的是低耗電、觸控介面與開放Web標準,Flash在這幾個方面都是不及格的。

這麼多媒體爭相提供內容讓我們放在蘋果行動裝置,顯示Flash已經成了觀看影片或任何Web內容的雞肋。而蘋果App Store超過20萬種應用程式證明開發者不需要Flash一樣可寫出圖像十分豐富的程式,包括遊戲。

行動時代所新推出的開放標準(如HTML5)將在行動裝置上勝出(PC亦然)。或許Adobe應該多花一點時間專心在未來推出好用的HTML5工具,而不是不斷批評蘋果太不念舊。
Steve Jobs

April, 2010


全文轉載自:Steve Jobs談為何蘋果討厭吃Flash(完整公開信,中文版),ZDnet Taiwan

(陳奭璁譯)

2010年4月25日 星期日

dpkg速記

deb的基本安裝過程:
dpkg是Debian底層的套件管理程式,其上還有強大的apt,在其上更有非常強大的aptitude管理系統。Debian系列的linux,如Ubuntu, B2D, LinuxMint等,都是使用dpkg作為底層的套件管理程式。不過由於apt以及aptitude過於強大,許多使用者對於dpkg的熟悉度往往少於Redhat系的使用者對於rpm的熟悉度;本文僅作為一個Debian的死忠支持者對dpkg指令的一篇速記,希望對於Debian迷以及Ubuntu Linux的技術人員亦能有所幫助。
dpkg能用來查詢、安裝以及設定deb檔;如同rpm,dpkg亦使用dpkg資料庫紀錄每個套件安裝、設定、移除等詳細資訊。一個標準的deb檔命名方式如下:

Filename_version-release_arch.deb
例如madedit_0.2.9-1_amd64.deb,madedit就是套件名稱,0.2.9為版本號,1為釋出番號,amd64則表示x86_64位元的平台。安裝一個deb的流程大致如下:
  1. 解開control file
  2. 從dpkgdb檢查系統是否已安裝此套件且版本相同;如果有,則執行prerm script,再執行preinst script。
  3. 備份舊的binaries,解開新的bineries並複製到設計好的位置。
  4. 從dpkgdb檢查系統是否已安裝此套件但版本不同;如果有,則執行postrm script。
  5. 備份舊的config檔,解開新的config檔並複製到設計好的位置。
  6. 執行postinst script。
dpkg有兩個姊妹:dpkg-deb以及dpkg-query。不過dpkg的action以及options能涵蓋大部分這兩個指令的功能,因此本文就僅提dpkg常用的功能。

安裝

dpkg的基本語法是:

dpkg action options
例如
dpkg --install --force-architecture foo.deb
--install對於dpkg而言是action,而--force-architecture則是action的微調選項。 dpkg的安裝並不進行gpg公開金鑰的驗證,而是在apt或是aptitude的部份進行檢查,因此有別於rpm系列的模式。安裝一個deb檔只需要-i(--install)命令:
dpkg -i foo.deb
一個deb的安裝大致可將上述流程一分為二:先解開這個deb檔到檔案系統中並寫入到dpkgdb裡,然後才進行設定。事實上,--install可以手動分成兩個步驟完成:
dpkg --unpack foo.deb
dpkg --configure foo
當然,你也可以在執行一次configure:
dpkg-reconfigure foo
很可惜,dpkg並不支援安裝一個網路上的deb檔,如果你想學rpm的方式:
dpkg -i http://altruistic.lbl.gov/mirrors/ubuntu/pool/universe/x/xosview/xosview_1.8.3+debian-18_i386.deb
你一定會得到錯誤訊息:
dpkg: error processing http://altruistic.lbl.gov/mirrors/ubuntu/pool/universe/x/xosview/xosview_1.8.3+debian-18_i386.deb (--install):
 cannot access archive: No such file or directory
Errors were encountered while processing:
 http://altruistic.lbl.gov/mirrors/ubuntu/pool/universe/x/xosview/xosview_1.8.3+debian-18_i386.deb

升級

嚴格來說,dpkg並沒有從deb去升級套件的指令。從deb的安裝流程來看,dpkg只要遇到版本比系統上的還新,就會自動移除舊的套件並安裝新的套件,備份舊的設定檔並套用新的設定檔。當然,自動移除舊套件這類prerm/preinst script都需要deb套件維護人員的細心維護。如果deb被粗心的維護,這個流程恐怕就不能如預期跑完。

重新安裝/強迫安裝

dpkg並沒有重新安裝這個觀念。使用--install遇到同版本的套件,並不會重新安裝,但是卻會再次執行--configure。如果想要重新安裝而不透過apt/aptitude,則需要移除套件才能再次安裝。
忽略套件的衝突進行強迫安裝。

dpkg -i --force-conflicts foo.deb
忽略套件的相依性進行強迫安裝。
dpkg -i --force-depends foo.deb
忽略套件相依性的版本問題。如果只是版本問題而非缺乏套件相依性,可以用這個option試試看。
dpkg -i --force-depends-version foo.deb
忽略套件的相依性,並且將套件的Desired status(稍後會提到)設定為hold進行強迫安裝。
dpkg -i --force-hold --force-depends foo.deb
更新設定檔時保留舊設定。最常用於安裝新版本的套件。如果想用新的設定檔,則改為--force-confnew。
dpkg -i --force-confold foo.deb
如果你是x86_64的機器,可是binaries只有for x86且沒有source code可供編譯,可以試試看安裝x86的deb。
dpkg --install --force-architecture foo_i386.deb
強迫安裝一個更舊的套件。需注意降級套件並不會顯示任何套件衝突或是相依性問題。使用時不要拿系統主要的套件來嘗試。
dpkg --install --force-downgrade foo.deb
強迫安裝一個套件。利用--refuse停止複寫系統內的檔案,並用--force強制忽略相依性及衝突性來安裝deb檔。
dpkg --install --refuse-overwrite --force-depends --force-conflicts foo.deb

不過這些強迫安裝的套件,都會因為使用apt/aptitude而被移除。

LPI level I也喜歡考這幾個options:
指定一個deb資料夾來安裝(-R/--recursive):

dpkg -iR foo/
安裝時若遇相依性問題,一律拒絕版本降級(-G/--refuse-downgrade):
dpkg -iG foo.deb
安裝時若遇到相同版本的套件,就略過不處理(-E/--skip-same-version):
dpkg -iE *.deb
檢視未安裝完全的套件(-C/--audit):
dpkg -C
-C/--audit並沒有額外options,如果檢視的結果沒有任何輸出,表示所有套件均正確被安裝及設定。

查詢已安裝的套件

1.以最常見的vim為例,查詢某套件的安裝狀態訊息(-l, --list)

dpkg -l vim
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Cfg-files/Unpacked/Failed-cfg/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ 名稱         版本         簡介
+++-==============-==============-============================================
ii  vim            2:7.2.245-2ubu Vi IMproved - enhanced vi editor
輸出結果的狀態欄位為"ii "共三個欄位。
第一個欄位為Desire status(也稱為Selection status),是系統管理員設定某套件將要執行的更動,例如
  1. u(unknown)
  2. i(install)
  3. r(remove)
  4. p(purge,連設定檔也移除)
  5. h(hold,維持版本號)
這個欄位是被特別設定的。例如你要把vim的Desired status設定成hold,也就是不更新此套件:
echo "vim hold" | dpkg --set-selections
可以在試試看dpkg -l vim:
hi  vim            2:7.2.245-2ubu Vi IMproved - enhanced vi editor
可以發現Desired status已經是hold住了。--set-selections只接受stdin,若想知道某個套件的Desired status,就使用--get-selections吧:
dpkg --get-selections vim
vim      install
第二個欄位為Package status(或稱為actual status),是套件目前的狀態
  1. N(not-installed)
  2. dpkg --purge所致,不留設定檔。
  3. C(config-files)
  4. dpkg --remove所致,只剩下設定檔了。
  5. H(half-installed)
  6. 不完全安裝,常見於其他套件執行--force-breaks所影響。
  7. U(unpacked only)
  8. dpkg --unpack之後的結果。
  9. F(half-configured or failed configured)
  10. 是一個設定失敗的套件,通常會是一個服務。
  11. A(triggers-awaited)
  12. 表示下次系統執行apt/aptitude時,會等待某個套件的觸發而觸發,使之變更到Selection status。
  13. P(triggers-pending)
  14. 表示下次系統執行apt/aptitude時會觸發這個套件使之變更到Selection status。
  15. i(installed)
  16. 一個正常的安裝狀態。
第三個欄位為Package Flags(套件旗標),只有一個flag:
r(reinst-required)
出現這個flag表示該套件被標示為broken,他不能夠被移除,並且會嘗試在下次執行apt/aptitude時重新安裝。
我們常用dpkg -l | grep foo來查詢某個套件的狀態,而不要列出一大堆不必要的欄位資訊。

2.查詢某套件的詳細資訊,包含相依性、衝突套件等(-p, --print-avail/-s, --status)
dpkg -p(-s) vim
Package: vim
Priority: optional
Section: editors
Installed-Size: 1516
Maintainer: Debian Vim Maintainers 
Architecture: i386
Version: 1:7.1.314-3+lenny2
Replaces: vim-common (<< 1:7.1-175+1)
Provides: editor
Depends: vim-common (= 1:7.1.314-3+lenny2), vim-runtime (= 1:7.1.314-3+lenny2), libacl1 (>= 2.2.11-1), libc6 (>= 2.7-1), libgpm2 (>= 1.20.4), libncurses5 (>= 5.6+20071006-3), libselinux1 (>= 2.0.59)
Suggests: ctags, vim-doc, vim-scripts
Conflicts: vim-common (<< 1:7.1-175+1)
Size: 776664
...描述省略

3.列出套件所包含的檔案(-L, --listfile)
dpkg -L vim
/usr
/usr/bin
/usr/bin/vim.basic
/usr/share
/usr/share/bug
/usr/share/bug/vim
/usr/share/bug/vim/presubj
/usr/share/doc
/usr/share/lintian
/usr/share/lintian/overrides
/usr/share/lintian/overrides/vim
/usr/share/doc/vim

4.查詢某檔案由哪個套件提供(-S, --search)
dpkg -S /etc/apache2/apache2.conf
apache2.2-common: /etc/apache2/apache2.conf

查詢一個deb檔

1.查詢一個deb檔所包含的檔案(-c, --contents)

dpkg -c xosview_1.8.3+debian-18_i386.deb
drwxr-xr-x root/root         0 2009-09-28 21:17 ./
drwxr-xr-x root/root         0 2009-09-28 21:16 ./etc/
drwxr-xr-x root/root         0 2009-09-28 21:16 ./etc/X11/
drwxr-xr-x root/root         0 2009-09-28 21:16 ./etc/X11/app-defaults/
-rw-r--r-- root/root     11382 2009-09-28 21:16 ./etc/X11/app-defaults/XOsview
drwxr-xr-x root/root         0 2009-09-28 21:16 ./usr/
drwxr-xr-x root/root         0 2009-09-28 21:16 ./usr/share/
drwxr-xr-x root/root         0 2009-09-28 21:16 ./usr/share/applications/
-rw-r--r-- root/root       153 2009-09-28 21:16 ./usr/share/applications/xosview.desktop
drwxr-xr-x root/root         0 2009-09-28 21:16 ./usr/share/pixmaps/
-rw-r--r-- root/root     11447 2009-09-28 21:16 ./usr/share/pixmaps/xosview.xpm
2.查詢一個deb檔的詳細資訊(-I, --info)
dpkg -I xosview_1.8.3+debian-18_i386.deb
(-I是大寫的i,不是小寫的L喔!)
 new debian package, version 2.0.
 size 110050 bytes: control archive= 1210 bytes.
      30 bytes,     1 lines      conffiles            
     704 bytes,    16 lines      control              
     717 bytes,    11 lines      md5sums              
     185 bytes,     7 lines   *  postinst             #!/bin/sh
     160 bytes,     5 lines   *  postrm               #!/bin/sh
 Package: xosview
 Version: 1.8.3+debian-18
 Architecture: i386
 Maintainer: Ubuntu Developers 
 Original-Maintainer: Kartik Mistry 
 Installed-Size: 328
 Depends: libc6 (>= 2.4), libgcc1 (>= 1:4.1.1), libstdc++6 (>= 4.4.0), libx11-6
 ...以下省略

移除(--remove/--purge)

dpkg -r foo
刪除一個套件。需記得dpkg不會幫您解決相依性、套件衝突問題;如果有這些問題,dpkg -r並不會成功動作。
dpkg -P foo
刪除一個套件。並且連設定檔一同刪除。

解開deb(dpkg -x):

dpkg -x foo.deb /path
解開這個deb安裝後的目錄樹。但是真正能控制deb的設定檔並不會被解出來。要一窺deb控制檔的奧秘,你必須使用ar:
ar x foo.deb
可以發現有control.tar.gz、data.tar.gz、debian-binary這三個檔案,其中control.tar.gz便包含了許多安裝前後的script:
./postinst
./postrm
./conffiles
./md5sums
./control
而data.tar.gz就是真正要安裝到檔案系統的內容。

參考文獻:
1. Debian System -- concept and technology
2. A practical guide to Ubuntu Linux
3. Man page of dpkg
4. 次世代Ubuntu Linux完全手冊,第五章

2010年4月24日 星期六

YUM筆記

YUM簡史

YUM(Yellow dog Updater, Modified)是Redhat系列的linux最重要的套件管理程式,他的前身是YUP(Yellow dog UPdater)。Yellow Dog很多人是很陌生的,他是在早期運行在IBM的power平台上的linux,也是使用rpm based。當時能夠跑在power上的linux大概就只有Debian以及Redhat/Fedora Linux;後來在社群不斷地維護、改善下,就產生了重大的改版--YUM。

很顯然的,YUP或是YUM的出現是因為rpm的相依性、版本、套件間衝突的問題用手動很難解決,必須要依靠一個機制來自動替我們解決所有相依性地獄(dependency hell)的問題。yum提供的服務大致有四項:

  1. 自動解決相依性問題
  2. 能夠用command自動化管理,也能有圖形化介面(pirut)
  3. 能夠管理多個套件庫來源
  4. 能夠跟rpm一樣精確的管理套件的版本以及適用平台的種種情況

Repostories

一個Redhat Linux標準的repostories設定檔,是放置在/etc/yum.repos.d/底下,任何以.repo結尾的檔案都會被視為一個套件庫。以一個RHEL5.repo為例,他的格式如下:

[Server]
name= Server catagory
enable = 1
baseurl=http://192.168.2.254/RHEL5/Server/
gpgcheck=0

[VT]
name= Virtualization catagory
enable = 1
baseurl=http://192.168.2.254/RHEL5/VT/
gpgcheck=0

[Cluster]
name= Cluster catagory
enable = 1
baseurl=http://192.168.2.254/RHEL5/Cluster/
gpgcheck=0

[ClusterStorage]
name= ClusterStorage catagory
enable = 1
baseurl=http://192.168.2.254/RHEL5/ClusterStorage/
gpgcheck=0
其中,[XX]就是yum認定的repo category名稱;利用enable變數可以開關一個category。習慣上相同來源不同的category會放在同一個.repo便於維護,當然你也可以將所有來源寫成同一個檔案,或是每個category都獨立成一個.repo,yum都能夠正確解讀。
想知道有哪些categories是enable/disable,或是全部列出,可以使用repolist:
yum repolist all
repo id             repo name                                    status
Cluster             Cluster catagory                             enabled:     32
ClusterStorage      ClusterStorage catagory                      enabled:     30
RHEL5               RHEL5                                        disabled
Server              Server catagory                              enabled:  2,797
VT                  Virtualization catagory                      enabled:     34
rhel-debuginfo      Red Hat Enterprise Linux 5Server - i386 - De disabled
rhel-debuginfo-beta Red Hat Enterprise Linux 5Server Beta - i386 disabled
rpmforge            Red Hat Enterprise 5Server - RPMforge.net -  enabled: 10,305
rpmforge-testing    Red Hat Enterprise 5Server - RPMforge.net -  disabled
repolist: 13,198

安裝(install)

yum有著非常直觀的命令列:install用來安裝數個套件:

yum install foo1 foo2 foo3
如果你的機器是x86_64,你還可以選擇安裝x86版本的套件,此時只要在多指定名稱即可:
yum install f001.x86_64 f002.x86 f003
對於沒有指定平台的套件,如果套件庫兩者都存在,則兩種平台都會安裝;因此還是強烈建議把平台名稱也寫上去。yum的運行機制會先更新yumdb,然後從dbcache裡得知所有套件資訊,因此當你執行yum install foo時,yum已經更新了他的yumdb,並且列出滿足安裝該套件所需要額外安裝的套件,並等待徵求你的同意。有時候你想自動回答yes,那麼就加個-y:
yum install foo3 -y
不過如果你沒有匯入gpg公開金鑰,yum下載完rpm會拒絕你繼續安裝。解決的方法是在.repo檔裡設定gpgcheck=0,或是直接使用nogpgcheck:
yum install foo3 --nogpgcheck -y
如果想忽略訊息,就加個-q吧。當然,你可以用yum安裝一個rpm,讓yum幫你解決惱人的相依性問題(如果yum可以解決的話):
yum localinstall foo3-1.2.3-5.el5-x86_64.rpm
or
yum localupdate foo3-1.2.3-9.el5-x86_64.rpm
yum也支援安裝一個群組套件,這比較少用到,除非你知道有哪些群組套件可用:
yum groupinstall "GNOME Desktop Environment"
當然,yum也可以讓你很容易的重新安裝:
yum reinstall foo

更新(update/upgrade)

更新是很重要的事情。除非一個系統只專門為了某項服務而設立(例如網格計算之類的高速電腦),或是在一個非常封閉的環境裡(例如無法連入的私有網路),否則更新套件以及安全性更新是很重要的。update就是最常用的更新指令:

yum update foo2 foo2
這樣一來便能夠更新這兩個套件。如果不加任何套件名稱,則系統內所有套件都會被更新。yum也可以讓你只看看有哪些東西需要更新,而不會真的更新:
yum check-update
另一個類似的用法:upgrade
yum upgrade
其實等同於
yum update --obsoletes
讓套件的更新會刪除已淘汰(repo不再被維護)的舊套件。通常這個指令只建議做同版本的升級(例如CentOS 4.3->4.4),如果想要從CentOS4.4升級到目前的5.4,恐怕還是建議拿光碟升級或重灌系統。
或是讓你降級安裝:
yum downgrade foo1

許多關鍵的server並不希望更新kernel或是gcc版本,我們可以從yum的設定檔下手:在/etc/yum.conf多加一行
exclude=kernel gcc
就可以防止被yum升級。

移除(remove/erase)

利用remove或是erase:

yum remove foo1 -y
利用yum remove比rpm -e來得方便多了,因為yum能自動幫我們解決相依性的問題。

查詢(list/search/info)

list可使用的對象分成七大類:installed(已安裝套件), available(所有repos裡的套件), updates(可供更新套件), extras(已安裝但不在repos裡), obsoletes(系統內已被repos廢棄的套件), recent(新被加入到repos的套件)以及all(所有安裝到系統的套件)。list可提供套件名稱的模糊搜尋。要查看有沒有可以更新的套件:

yum list updates
查看有沒有安裝http:
yum list installed http*
查看整個套件庫有多少套件:
yum list avaliable | wc -l
search則是比list提供更廣義的搜尋。利用search可以提供套件名稱、描述、摘要以及與該套件相關的模糊搜尋。
yum search python
便會發現所有欄位包含python都會被納入搜尋範圍。
info會列出套件的詳細資訊。如果只下yum info,則會列出所有套件庫內的套件資訊,那是非常龐大且沒有幫助的訊息。一樣可以用list的規範:
yum info installed | grep nfs
當然,info也可以直接指定套件名稱,但也僅限於套件名稱的模糊搜尋:
yum info nfs*
其他的類別就各憑需求去執行囉。

進階查詢(provides/whatprovides)

provides與whatprovides是相同的意義,通常用在尋找某個檔案是由哪個套件所帶來的

yum provides /etc/passwd
setup-2.5.58-1.el5.noarch : A set of system configuration and setup files.
Repo        : Server
Matched from:
Filename    : /etc/passwd

setup-2.5.58-7.el5.noarch : A set of system configuration and setup files.
Repo        : installed
Matched from:
Other       : Provides-match: /etc/passwd
如果有多個repos,就會有多比資料。provides也可提供套件的模糊搜尋。

清除(clean)

cache指的是rpm本身。yum從站台下載下來的rpm都會存在暫存資料夾下安裝,但是安裝成功後並不會幫你清除。

yum clean packages
可以清除的對象還有headers/metadata/dbcache等。你可以直接用一個all代表清除全部:
yum clean all
刪除某套件的cache

建立一個自己的repo

建立一個yum repo比想像中更容易,你只要把rpm放在一個指定的目錄下,就可以建立一個repo:

createrepo -v /path/to/rpmrepo
這個指令在於產生一個repodata的目錄,內含filelists.xml.gz這類重要的檔案。產生一個新的.repo把這個位置加進來,可以是local硬碟file://,也可以是ftp://,也可以是http://。

參考文章:
1. Redhat Enterprise Linux Administration Unleashed, Chapter 3.
2. YUM的使用-PHP5網管實驗室
3. 使用 yum 來做套件管理並建置 yum Server

2010年4月23日 星期五

rpm速記

rpm的基本安裝過程:
RPM(Redhat package Manager)是Redhat系的linux最必須要熟知的套件管理程式,許多非Redhat系的linux也沿用這個管理程式,例如SuSE Linux, Mandirva以及其衍生的PCLinuxOS等。rpm的功能非常完備,比起dpkg管理程式更勝一籌。
rpm的所有動作都會與rpmdb進行互動,也就是透過rpm所安裝的程式都能夠被記錄下來;手動安裝的程式則不在db內,因此也無法享受這方面的便利性。安裝、移除、升級rpm時都會更新rpmdb,但是仍然可以手動更新:

rpm --rebuilddb
rpm檔的命名遵循一定的格式:
Filename-version-release.arch.rpm
例如GConf2-2.14.0-9.el5.i386.rpm,其中的GConf2就是檔案名稱,2.14.0為版本號,9為釋出番號,el5.i386表示這是一個適用於RHEL5 x86平台的rpm檔。一個rpm的安裝會有下列過程:
  1. 檢查數位簽章
  2. 進行相依性檢查
  3. 執行pre script
  4. 複製檔案內容至指定位置
  5. 執行post script

GPG(GNU Private Guard) key數位簽章驗證

GPG key(或稱為signature key)是rpm的發行商應該提供的一個數位簽章(也就是一組公開金鑰)在安裝前rpm會進行檢查。如果rpm檔沒有數位簽章,或是rpmdb沒有紀錄該發行商的公鑰,則rpm數位簽章認證則會出錯:

rpm --checksig http://192.168.2.254/RHEL5/Server/GConf2-2.14.0-9.el5.i386.rpm
http://192.168.2.254/RHEL5/Server/GConf2-2.14.0-9.el5.i386.rpm: 
(SHA1) DSA sha1 md5 (GPG) NOT OK (MISSING KEYS: GPG#37017186)
假設我們想匯入GPG key到系統裡,應該用--import:
rpm --import http://192.168.2.254/RHEL5/RPM-GPG-KEY-redhat-release
我再試一次:
rpm --checksig http://192.168.2.254/RHEL5/Server/GConf2-2.14.0-9.el5.i386.rpm
http://192.168.2.254/RHEL5/Server/GConf2-2.14.0-9.el5.i386.rpm: 
(sha1) dsa sha1 md5 gpg OK
其中,--checksig可以用-K來代替。GPG key的簽章校驗失敗並不會讓安裝無法進行,只是rpm被包裹成類似cpio的格式,沒辦法輕易得知裡面的內容是否被有心人士更動過,因此匯入發行商的公開金鑰進行數位簽章的認證其實是常被忽略但極為重要的一個步驟。

安裝:

rpm -ivh foo.rpm
其中,-i表示install, -v為verbose,-h則是用50個#(hash marks)來顯示進度。如果你對debug rpm感興趣,你還可以用-vv顯示更詳盡的內容。
rpm -i --test foo.rpm
非常有趣的一種方式,利用--test測試安裝,過程並不會真的安裝,而是把-i之後的結果先印給使用者。如果結果符合預期,可以把--test拿掉進行真正的安裝。

升級:

rpm的升級可用兩種方式:

rpm -Uvh foo.rpm
-U表示Upgrade and install的意思。如果系統內已經有舊版本的套件,則會移除後再安裝新版本;如果沒有既有套件,則等同於-i全新安裝;這也是很多人常用-Uvh來安裝rpm的原因。
rpm -Fvh foo.rpm
-F為Freshen之意,意思比upgrade更像upgrade。使用-F,系統內必須已經安裝了較舊或相同版本的套件,她並不會像-U自動升級安裝。
需切記核心的升級要使用-i全新安裝,而不要使用-U/-F。原因是rpm -U會移除舊的kernel並安裝新的,但是我們並無法確定新核心是否有問題,甚至不確定能否正常開機。使用-i進行一個新的安裝,一旦新核心有問題,還可以開回舊核心繼續作業。

重新安裝:

rpm -ivh --replacepkgs foo.rpm
雖然名為replace,但是就是reinstall的意思。適用於相同版本號的套件。
rpm -ivh --replacefiles foo.rpm
如果既有檔案與foo.rpm會安裝到系統的檔案有重複或是套件間有conflict,則會覆蓋掉系統的舊檔案,也就是忽略套件間衝突
rpm -ivh --oldpackage foo.rpm
如果為了讓某些程式可以跑,需要舊一點的套件(最常見的就是舊版的gcc),你可能需要downgrade你的套件。利用--oldpackage指定一個比現有套件還舊的package來安裝。強制安裝一個rpm檔,完全忽略相依性未解決的問題。如果你根本不想理會到底是降級到舊版本或是覆蓋舊檔的問題,你可以用--force代替上面三個範例:
rpm -ivh --force foo.rpm
完全等同於
rpm -ivh --replacefiles --replacepkgs --oldpackage foo.rpm
不過這樣硬幹並非好事,而且還是沒辦法解決相依性的問題。如果你只想忽略相依性而強制安裝,應該用--nodeps:
rpm -ivh --nodeps foo.rpm
如果你是x86_64的機器,可是binaries只有for x86且沒有source code可供編譯,可以試試看安裝不同arch的rpm:
rpm -ivh --ignorearch foo.x86.rpm
如果你的硬碟空間非常有限,系統又跑的是你再熟悉不過的服務跟指令,你可以選擇不裝man pages:
rpm -ivh --excludedocs foo.rpm
如此一來雖然你可以執行一個命令,但是沒有他的man page。

移除:

rpm -e foo
不用接版本號就可以移除(erase)該套件。假設該套件同時安裝了x86及x86_64兩種版本,則只好辛苦一點,指定全名:
rpm -e foo-version-arch

查詢已安裝的rpm檔:

印出套件名稱及版本號:

rpm -q foo
如果要列出系統所安裝『所有』套件,則可用
rpm -qa
來觀察。不過-qa列出的資訊太過龐雜,因此較常見的用法是搭配grep搜尋關鍵字:
rpm -qa | egrep "*samba*"
當然,也可以利用-qa來列出系統已安裝的public key:
rpm -qa gpg-pubkey
如果知道套件名稱,想知道他的詳細訊息(info):
rpm -qi foo
如果想知道系統的某個檔案(file)是由哪個套件提供,可以使用-f:
rpm -qf /etc/passwd
反之,如果你想知道這個rpm究竟裝了哪些東西到你的系統(這恰好是windows最不希望使用者知道的...),可以讓rpm列表(list):
rpm -ql foo
不過,列出的訊息實在太多了,應該可以使用grep撈出有用的資訊,看看有哪些是doc,又有哪些是設定檔;你可以用-qd指查詢docs
rpm -qd foo
或是-qc來查看conf檔:
rpm -qc foo
或是進一步查看套件的相依性:
rpm -q --requires foo
這個指令應該反過來理解:foo套件(或指令)需要哪些套件(或檔案)。例如,python指令需要哪些套件或libs:
rpm -q --requires python
/bin/sh  
/usr/bin/env  
libbz2.so.1  
libc.so.6
...以下略  
相反的,查詢某套件提供了哪些指令或libs,例如,python提供了哪些套件跟libs:
rpm -q --provides python
Distutils  
_bisect.so  
_bsddb.so  
_codecs_cn.so
...中間略  
python = 2.4.3-27.el5
顯示python提供了Distutils套件等,也提供了python自己。
rpm -q --provides foo
跟上面相反:foo套件提供了哪些能力。例如:
rpm -q --provides passwd
config(passwd) = 0.73-1
passwd = 0.73-1
與--provides/--requires類似的兩個options分別是--whatprovides與--whatrequires。
rpm -q --whatprovides python
python-2.4.3-27.el5
rpm -q --whatprovides /etc/passwd
setup-2.5.58-7.el5
被查詢的對象可以是一個檔案,也可以是套件本身。python由python-2.4.3-27.el5提供而來,/etc/passwd則由setup-2.5.58-7.el5而來。
rpm -q --whatrequires bash
info-4.8-14.el5
gpm-1.20.1-74.1
initscripts-8.45.30-2.el5
ypbind-1.19-12.el5
sysklogd-1.4.1-46.el5
vixie-cron-4.1-77.el5_4.1
sendmail-8.13.8-8.el5
squid-2.6.STABLE21-6.el5
vnc-server-4.1.2-14.el5_3.1
bash套件被這些套件所依賴。
rpm -q --whatrequires `which bash`
bash-3.2-24.el5
iproute-2.6.18-11.el5
gpm-1.20.1-74.1
groff-1.18.1.1-11.1
iputils-20020927-46.el5
xorg-x11-filesystem-7.1-2.fc6
crontabs-1.10-8
...族繁不及備載
/bin/bash這個檔案被更多的套件所依賴,不難想像linux就是一個大量shell script架構出來的系統。透過--provides/--whatprovides/--requires/--whatrequires這四個參數就可以把rpm的相依性完全釐清,只是在使用--what參數時總是容易令人混淆。 甚至你也可以檢查這個套件在安裝時的狀態(status):
rpm -qs foo

查詢一個rpm檔:

很幸運的,剛剛我們所列出的options都還可以繼續沿用,要查詢一個rpm檔而不是已經安裝的套件名稱,只需要多加一個-p即可。例如查詢一個rpm的info:

rpm -qpi foo.rpm
想知道這個rpm究竟包含哪些binaries以及libraries:
rpm -qp --provides foo.rpm
以及她需要哪些套件或libs:
rpm -qp --requires foo.rpm
甚至你可以清楚的查看安裝這個rpm的blockquote script以及post script:
rpm -qp --script foo.rpm
在安裝前就先看看這個rpm會裝哪些東西到系統裡:
rpm -qpl foo.rpm
當然還是可以搭配--what,只是別忘了記得加-p

patch檔的查詢:

很多時候我們會下載一個小的patch檔而非一整個全新的rpm,要查看這個rpm patch會更新哪些檔案只需要多一個-P:

rpm -qPpl foo.patch.rpm
有了先前的經驗,我們也可以知道某patch套件更新了哪些檔案:
rpm -qPl foo
當然,你更可以查詢整個系統所有被patch過的檔案有哪些:
rpm -qaP

稽核(Verifying)rpm檔;

稽核rpm檔是比較rpm安裝在檔案系統內的檔案與rpmdb所紀錄的檔案資訊做比較。比對的項目有八項:

  1. file size
  2. 檔案大小是否改變 (S)
  3. file type
  4. 檔案狀態(權限、類型)是否被改變 (M)
  5. MD5 checksum
  6. 以md5sum指令進行計算 (5)
  7. device
  8. 裝置檔是否改變 (D)
  9. linkage
  10. 是否指向另一檔案 (L)
  11. owner
  12. user是否改變 (U)
  13. group
  14. group是否改變 (G)
  15. mtime
  16. 修改時間 (T)
例如,檢查vim套件有哪些檔案被修改過:
rpm -V vim-common
S.5....T  c /etc/vimrc
校驗rpm的結果用上述八個欄位表示,上面的結果表示vimrc在安裝之後大小改變,因此md5 checksum也必定改變,修改時間也改變了。"."表示從未改變。假設這個檔案被移除了,則會顯示missing;如果你是用一般使用者的身份查詢系統檔案,很可能因為權限不足而產生"?"的狀態,請切至root執行rpm -V即可正常檢查。

解開rpm:rpm2cpio

rpm2cpio能解一個rpm檔導入cpio解開成檔案。利用上面所學檢查系統是否有rpm2cpio這個程式:

rpm -qf `which rpm2cpio`
可見這個指令就是包含在rpm套件裡面。
rpm2cpio foo.rpm | cpio -idmv
其中,-i表示解開一個cpio檔,-d建立目錄樹(man pages上說cpio只會解檔案不解目錄,但我測試結果,加不加-d是相同效果),-m使還原後能保留mtime,-v為詳細輸出。
如果只是要查看rpm內容,可以不需要輸出:
rpm2cpio foo.rpm | cpio -vt

參考文獻:
1. Redhat Linux網路及系統管理指南(學貫),第26章
2. 鳥哥的私房菜第23章
3. How To Extract an RPM Package Without Installing It.

2010年4月9日 星期五

批次修改圖片大小-convert

最近在BBS上看到有網友詢問如何利用convert指令做批次轉換。在先前的批次修改圖片大小裡有提到一些方法。不過當時我一直忘記把script寫上來,今天特地補上。

#!/bin/bash

for files in *.ps; do
    name=$(echo $files | cut -d. -f1).pdf
    convert $files $name
done

這個作法的好處就是只要修改.ps跟.pdf這兩個關鍵字即可。當然他不是一個完美script-- 你還可以讓他變得更人性:

#!/bin/bash
## Author: Jim T. Tang (http://maxubuntu.blogspot.com)
if [ -z $1 -a -z $2 ]; then
    echo "usage: $0 jpg png";
    exit 0;
elif [ -z $2 ]; then
    echo "need target format. e.g. ps"
else
    for files in *.$1 ; do
        name=$(echo $files | cut -d. -f1).$2
        convert $files $name
        echo "$name is made."
    done
fi 

2010年3月9日 星期二

終於拿到NCLP證照了(二)!

這個標題很奇怪,但我不得不說一下...Novell這間公司有時候證照辦得太多,也是很容易出錯的。終於拿到NCLP award!這篇文章中,可以發現我只收到NCLA,但是我考的NCLP呢?我從未拿到。由於我從認證資料庫裡查到我確實有CLP的紀錄在,因此也就沒有多疑,即使我沒有拿到紙本的NCLP證照!不過我越想越不對,前幾天又寫信給Novell負責教育訓練的窗口,我列出我所拿到的證照,也就是我在終於拿到NCLP award!這篇文章所列出的證照是否為NCLP所應該有的全部:

Greeting Sir,
In August 2008, I passed NCLP exam.
yesterday I get a Linux Technical Specialist cert in my email box, 
I suddenly found that what I got is a NCLA certification, 
but what I should take is the NCLP cert, right? 
the attached files are what i have, may I know if these are all licences for a NCLP passer?
if these are all for a NCLP passer, why what we got is NCLA instead of NCLP?
if there is NCLP certification but for some reason I never receive awarded emails from Novell,
would you please resend it to me?

And the final question is for NCLP11. If I pass NCLP11 in the future,
will Novell award me both NCLA and NCLP or NCLP only?
thank you! 
--------------------------------
Name: JIM TING TANG
Registration Key:  CSP-XXXXXXXXXX
Candidate ID: 100XXXXX
Email:  maxXXXXXXX@gmail.com
Phone:  886XXXXXXXXXX
Test:  Certified Linux Professional 10

Test Dates:
      08/31/2008  14:30
      08/31/2008  17:00
---------------------------------

我想知道CLP11是不是還會像以前一樣同時送CLA,他的回答如下:

Hello Jim,

Your CLP 10 is showing in your certification progress as completed. I have re-sent the pdf file to you for your certificate. If you complete the CLP you will also be a CLA. Thanks,

Tyler

果然,剛剛我就收到了睽違快要兩年的NCLP證照...雖然已經是過往雲煙了,但這種心情很奇怪,沒啥高興的感覺,我想這大概就是遲來的正義的感覺吧!而且也解決了一個小疑點:即使是SLES 11的版本,拿到NCLP還是一樣同時擁有NCLA的證照,不會改變。

Dear JIM TING TANG:

Congratulations! On behalf of Novell Technical Training, it is a pleasure to grant you the title of:

Novell Certified Linux Professional (Novell CLP)
SUSE Linux Enterprise Server 10

Your Certification ID number is: 100XXXXX

Novell CLP certification allows you access to the Novell Certification Community. From the Community, you may connect to “My Certifications” to view and update your information. Please check this often and keep your contact information updated.

The first time you access the Novell Certification Community, you will need the Registration ID and exam date from your recent exam. All of this information can be found on the score report you received when you took your exam. Please email edcustomer@novell.com if you have any questions.

In order to do our part to protect the environment, Novell is "going green" and discontinuing the mailing of hard copy certificates. I encourage you to print out your attached PDF certificate and display it proudly.

I commend you for your commitment, dedication, and effort in earning the Novell Certified Linux Professional certification.

Sincerely,

MaryJo Swenson
Executive Director
Novell Technical Training

所以雖然我很開心收到了證照,但我還是很客氣的跟他小抱怨了一下,請他補寄紙本的證照給我!

2010年3月8日 星期一

IE6的葬禮

Internet Explore 6(以下簡稱IE6)是全世界使用率最高,使用時間最長的瀏覽器。包含筆者在內從windows 98時代使用IE5,到後來的windows ME, 2000都還是IE5的時代;XP的強勢進攻,IE6也搭這順風車成為全世界最普及的瀏覽器;在XP即將壽終之前,IE7已經推出而且還包含在XP的線上更新內,只是IE7的秀斗與缺陷實在罄竹難書,許多學校、廠商或各級單位甚至都要求使用者不要升級成IE7:IE6的重要性反而在IE7推出之際越顯重要。中道的衰落,從firefox跟opera崛起之後就注定了這個命運;更悲慘的是,chrome來勢洶洶,IE8是否能力挽狂瀾呢?下文轉載自iThome: 設計公司幫IE6舉行葬禮一文:


根據外電報導,這場葬禮甚至還收到微軟IE團隊送來的花藍,IE團隊在卡片上寫著:「感謝IE6所帶來的美好時光」。

一家位於丹佛的設計公司Aten Design Group在上周一(3/1)隨著YouTube將在當天停止對IE6的支援,而舉辦了一場詼諧的IE6葬禮。

Aten藉由一家Pub舉辦IE 6葬禮,並安排了棺木、假的屍體、頭上鑲有IE 6扭曲的表情,墓誌銘上標示著IE6生於2001年8月27日,死於2010年3月1日。參與該場葬禮的入士皆依照傳統禮節盛裝出席。根據外電報導,這場葬禮甚至還收到微軟IE團隊送來的花藍,IE團隊在卡片上寫著:「感謝IE6所帶來的美好時光」。

Aten並且打造了一個專為IE6葬禮所設計的網站,說明享年8歲的IE6因禁不住Google的職業傷害而在3月1日壽終正寢,但IE6的兒子IE7及孫女IE8將會延續其生命。該站並銷售印有相關圖案的T恤,售價25美元。

IE6近來遭受重重打擊,最嚴重的莫過於資安業者發現駭客鎖定包括Google在內的全球數十家企業的攻擊行動,就是利用IE6的安全漏洞,這項指控一度促使歐洲國家呼籲使用者改用IE以外的瀏覽器,另外,Google在今年1月初就表示自3月1日起將分階段陸續淘汰對IE6等舊版瀏覽器的支援,率先執行該政策的就是全球最受歡迎的YouTube影片分享網站。

但根據網路調查機構Net Applications的數據顯示,目前市佔率最高的瀏覽器版本為IE8,市佔率為22.52%,而已經舉行過葬禮的IE6還有高達19.76%的市佔率,排名第二,IE7以13.57%排第四,落後Firefox 3.5的14.54%。各界預期微軟將在本月舉行的MIX會議上揭露IE6曾孫─IE9的面貌。(編譯/陳曉莉)


圖片來源:IE6Funeral.com

實在是很佩服老外的詼諧,也實在是佩服他們的幽默感跟時間多...難怪台灣人常說沒那美國時間理你,是非常切中實際的一句話。Good to go, IE6!

2010年3月7日 星期日

Java方塊字

許多Java應用程式在輸入中文時會出現方塊字,其實這個時候只要把字型設定給Java即可。以我的Ubuntu為例,我安裝的是sun-java6-jre,此時只要幾個步驟:

cd /usr/lib/jvm/java-6-sun/jre/lib/fonts
mkdir fallback
ln -s /usr/share/fonts/truetype/LiHei_ProPC.ttf .

其中LiHei_ProPC.ttf是我要指定讓Java應用程式使用的字體,因此千萬確定你所使用的字體支援中文,否則就失去意義了。
把你的Java應用程式重新啟動,應該就可以看到正常的中文字體了。

2010年3月4日 星期四

Firefox/Chrome遇到flash方塊字

這個問題已經持續好幾個版本了,問題雖然知道是出在字型設定,但為何問題出在字型就不是我感興趣的部份。大致爬了一下大家的blog都提到了/etc/fonts/conf.d/49-sansserif.conf這個檔案。他是一個軟連結,來源是/etc/fonts/conf.avail/49-sansserif.conf。他原本是這樣:

  1. <?xml version="1.0"?>
  2. <!DOCTYPE fontconfig SYSTEM "fonts.dtd">
  3. <fontconfig>
  4. <!--
  5.  If the font still has no generic name, add sans-serif
  6. -->
  7.     <match target="pattern">
  8.         <test qual="all" name="family" compare="not_eq">
  9.             <string>sans-serif</string>
  10.         </test>
  11.         <test qual="all" name="family" compare="not_eq">
  12.             <string>sans-serif</string>
  13.         </test>
  14.         <test qual="all" name="family" compare="not_eq">
  15.             <string>monospace</string>
  16.         </test>
  17.         <edit name="family" mode="append_last">
  18.             <string>sans-serif</string>
  19.         </edit>
  20.     </match>
  21. </fontconfig>

由於他只是一個軟連結,把他幹掉就可以正常顯示字型。但你如果希望讓flash使用系統其他字型,請繼續往下看。

我系統的預設字型是Sans,不過我也可以把他改成我們要的樣子。

sudo rm /etc/fonts/conf.d/49-sansserif.conf
接著,產生一個新的49-sansserif.conf檔案,把字型的部份用喜歡的字型取代,例如Mac的儷黑體:

  1. <?xml version="1.0"?>
  2. <!DOCTYPE fontconfig SYSTEM "fonts.dtd">
  3. <fontconfig>
  4. <!--
  5.  If the font still has no generic name, add sans-serif
  6. -->
  7.     <match target="pattern">
  8.         <test qual="all" name="family" compare="not_eq">
  9.             <string>LiHei Pro</string>
  10.         </test>
  11.         <test qual="all" name="family" compare="not_eq">
  12.             <string>LiHei Pro</string>
  13.         </test>
  14.         <test qual="all" name="family" compare="not_eq">
  15.             <string>LiHei Pro</string>
  16.         </test>
  17.         <edit name="family" mode="append_last">
  18.             <string>LiHei Pro</string>
  19.         </edit>
  20.     </match>
  21. </fontconfig>
  22.  

重新啟動你的chrome/firefox,應該就可以看見正常的字體了!

參考來源:
FourDollars Blog
FireFox中文flash方塊字的問題