基本設定


如果您從安裝一直殺到這裡﹐相信對 Linux 的恐懼感已經沒當初那樣嚴重了吧﹗或許您已經磨刀霍霍﹐躍躍欲試﹐準備進一步馴服這匹黑馬了。好﹗有志氣﹗﹗下面就讓我們按步就班的將 Linux 整治一翻﹐不要讓這匹良驅平白浪費了。

設定LILO

LILO 是 “LInux LOader”的縮寫﹐它是在機器啟動的時候負責載入作業系統的。有時候﹐我們可能需要設定不同的核心來配合不同的測試﹐我們就可以用 lilo 來指定了。

  1. 當您成功的編譯好核心後(在執行 make bzlilo之前﹐請參考上一章節)﹐你可以接著輸入﹕
    cp /usr/src/linux/arch/i386/boot/bzImage /boot/vmlinuz-new
    mv /boot/System.map /boot/System.map.bak
    cp /usr/src/linux/System.map /boot/System.map

  2. 然後修改 lilo 設定檔﹕
    vi /etc/lilo.conf

    我們要將剛才產生的核心(/boot/vmlinuz-new)編進lilo去﹐您可以參考原來的‘image=’那一段文字﹐找到‘root=’所在的位置(假設為hda5)﹐那麼我們就使用該位置好了﹐然後加入下面數行﹕
    default=new-kernel
    image=/boot/vmlinuz-new
            label=new-kernel
            root=/dev/hda5
            read-only
    
    (注意﹕第三行起不要用空白鍵來縮排﹐而應該用‘Tab’鍵。)

    同時﹐如果您的記憶體超過64MB的話﹐也可以加入這樣一行﹕
    append="mem=96M"
    
    (請將 96 改為您自己的記憶體數值)

    最後﹐您的lilo.conf 看上去有點像這樣﹕
    boot=/dev/hda
    map=/boot/map
    install=/boot/boot.b
    prompt
    timeout=50
    append="mem=96M"
    default=new-kernel
    image=/vmlinuz
            label=linux
            root=/dev/hda5
            read-only
    image=/boot/vmlinuz-new
            label=new-kernel
            root=/dev/hda5
            read-only
    image=/boot/vmlinuz-2.2.5-15CLE
            label=linux-cle
            root=/dev/hda5
            read-only
    other=/dev/hda1
            label=nt
            table=/dev/hda        
    
    (注意﹕粗體字就是剛才增加的部份。)

  3. 然後將修改存檔並退出vi:
    ﹕wq

  4. 之後執行﹕
    lilo

    看看您剛才寫進去的“kernel-new”有否出現﹐同時﹐在它旁邊是有有一個“*”標記﹐這表示它被選擇為預設開機核心了。如果您想看看 lilo 究竟做了些什麼修改﹐您可以輸入﹕lilo -v -v -v(越多 -v 越詳盡)。

  5. 當一切確定無誤後﹐可以重新開機看看新核心是否工作。當出現 ‘LILO Boot:’提示的時候﹐您可以按‘Tab’鍵看看有哪些選擇﹐然後輸入您要啟動的名稱。如果直接按‘Enter’就會以預設值開機了(如果在 /etc/lilo.conf 裡面沒有指定 default= ﹐則以排在前面的 image 為預設)。

當然﹐除了使用 LILO 之外﹐我們還可以使用其他開機系統哦﹐比如您的系統原來已經安裝好 NT 了﹐您也可以用 NTLDR 來啟動 linux 呢。下面我粗略的將步驟列出來﹐具體情況要看您實際操作環境了﹕

  1. 參考一下 winNT+Linux 的 HowTO 說明文件。
  2. 修改 /etc/lilo.conf ﹐將 boot= 修改成 superblock 的位置﹐如﹕boot=/dev/hdaX 。注意﹕/dev/hdaX 就是你的 linux root 區域(比方 hda5) 。
    然後執行一次 lilo ﹐確定沒用錯誤信息。
    又或者﹕以正常的方式安裝 Linux , 最後把 lilo 裝到 superblock 內﹐也就是在安裝步驟65那裡選擇‘First sector of boot partition’ 並記得製作一張 Linux 開機片。
  3. 執行﹕
    dd if=/dev/hda5 of=/bootsect.lnx bs=512 count=1
    把產生好的 bootsect.lnx 複製到你的 NT C:\ 的目錄下:
    mkdir /mnt/dos
    mount -t msdos /dev/hda1 /mnt/dos
    cp /bootsect.lnx /mnt/dos/bootsect.lnx
  4. 退出 linux﹐啟動到dos﹐然後執行﹕
    attrib -r -s -h c:\boot.ini
    edit c:\boot.ini ﹐在後面加入: c:\bootsect.lnx="Linux"
    attrib +r +s +h c:\boot.ini
這樣﹐您就可以用NT的Loader 來啟動 Linux 了。

設定modules

當您在編譯核心的時候﹐那些選擇了“*” 就會被編進核心去﹐也就是開機之後隨著核心啟動而啟動。至於那些選擇為“M”的項目﹐就會被編成模組(modules)了﹐它可以由開機程式呼叫而啟動﹐也可以由使用者啟動﹐而且﹐也可以將之卸載。

如果您想看看目前有哪些模組被載入了﹐您可以輸入﹕
lsmod

您就可以看到一堆模組的名字﹐還有它的大小﹐以及被哪些程式使用。

如果您想將一些已經載入的模組移除的話﹐使用rmmod 後接模組名字就可以了。如果您得到該模組正在使用中(in used)的信息﹐那麼先將相關的模組移除就是了。

要載入模組的話﹐我們可以使用 insmodmodprobe 後接模組名字來完成﹐如果您的模組路徑沒有設定正確的話(通常會指向 /lib/modules/下面)﹐那麼您就要加上路徑了。

不過﹐除非您的模組已經成功編譯(例如從某處抄過來的)﹐要成功的載入模組﹐您在安裝核心的時候必須確定程式(或服務)被編成模組了﹐存好核心之後還要跑﹕
make modules
mv /lib/modules/`uname -r` /lib/modules/`uname -r`.backup
(注意﹕“ `uname -r` ”之“ ` ”是在鍵盤上“Tab”鍵上面﹐“1”鍵左邊的符號)
make modules_install

我們之所以在 make modules_install 之前將當前核心版本的模組目錄改名﹐是為了避免和上一次編譯核心時安裝的模組混亂了。

然後﹐還要為模組建立好依賴關係﹐執行下面的命令就可以了﹐除非您有特定的模組設定﹕
depmod -a

如果有錯誤信息出現﹐可根據信息修改。通常會是一些 ‘xxxxx.yyyyy.xxxxxx.o: unrresolved symbol(s)’的錯誤﹐這裡也不打算詳細解析了﹐有興趣的話可以參閱這個連接﹕
http://bbs.ee.ntu.edu.tw/boards/Linux/4/8/1.html

下面這個例子﹐是教您如果用模組的形式來驅動一張 D-Link 530TX 網路卡﹕

  1. 如果在/lib/modules/`uname -r`/net/下面已經有 via-rhine.o的話﹐直接到步驟5 。(注意﹕“ `uname -r` ”之“ ` ”是在鍵盤上“Tab”鍵上面﹐“1”鍵左邊的符號)。
    否則﹐下載 http://cesdis.gsfc.nasa.gov/linux/drivers/test/via-rhine.c
    (請按著“Shift”鍵再點上面這個聯結。如果你只看到source內容﹐可以save as之後改為 via-rhine.c 並複製到軟碟上面。)
  2. 複製到LINUX上面﹕
    mkdir /usr/src/via
    mount -t msdos /dev/fd0 /mnt/floppy
    ls /mnt/floppy 看看檔案名稱是否正確﹐否則用mv 改為 via-rhine.c
    cp /mnt/via-rhine.c /usr/src/via
  3. 用gcc 編譯﹕
    cd /usr/src/via
    gcc -DMODVERSIONS -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c via-rhine.c
    (注意﹕“-D__KERNEL__ ”裡面之“__”是連續兩個“_”符號﹐另外“O6”不是“零六”哦﹐英文字母大寫“O”啦。)
  4. 將編好的模組複製到正確的位置﹕
    cp /usr/src/via/via-rhine.o /lib/modules/`uname -r`/net
  5. 修改/etc/conf.modules﹐增加﹕
    alias eth0 via-rhine
  6. 執行netconf 並選擇"Basic host information"﹐設定如下﹕
    Adapter 1
    [X] Enabled
    (o) Manual ( ) Dhcp ( ) bootp
    設定好 "IP 地址" 和 "Netmask"
    Net device﹕ eth0
    Kernel module﹕ via-rhine
  7. 修改/etc/rc.d/rc.local﹐增加﹕
    insmod /lib/modules/`uname -r`/net/via-rhine.o
  8. 再執行一次insmod /lib/modules/`uname -r`/net/via-rhine.o
  9. sh /etc/rc.d/init.d/network reload
  10. ifconfig查看網路

設定環境

我們已經知道什麼是核心和模組了﹐它們大都是一些與硬體和服務相關的程式﹐換句話說﹐它們的溝通對象是系統本身。而負責和使用者溝通的程式呢﹖我們管它叫 shell

DOS系統的shell就是command.com、Windows9x的shell則是explorer.exe。不過﹐在Linux裡面﹐卻有好幾種的shell可以選擇﹐這裡暫時不去詳細討論它們之間的差別了。RedHat6預設的shell是/bin/bash﹐此外還有 /bin/sh、/bin/csh、/bin/tcsh等﹐其實它們都十分相似的﹐如果沒什麼特殊嗜好﹐接受預設好了。如果您要改變一個使用者的預設shell﹐可以修改 /etc/passwd 這個檔案﹐在每一行的最後部份﹐就是用來指定使用者登錄時候所使用的shell。

如果您打開 /etc/profile 這個檔案看看﹐您就可以發現一些系統環境設定了﹐這些設定通常都適合大部份的使用者﹐我們可以管它做公共設定。然而﹐每位使用者也可以設定自己喜歡的環境﹐這個檔案會存放於使用者的家目錄裡面﹐如果您只輸入 ls 是看不見的﹐如果您改用﹕
ls -al

您就會發現一個 “.bash_profile” 的檔案﹐還記得上面講述 ls -a 這個命令的時候提到檔案前面的“.”麼﹖這個“.”就是用來將檔案隱藏起來的了。

如果您喜歡﹐現在就看一看這個檔案﹕
cat .bash_profile

您或許會看到近似這樣的內容﹕
# .bash_profile
# Get the aliases and functions
if [ -f ~/.bashrc ]; then
        . ~/.bashrc
fi

# User specific environment and startup programs

PATH=$PATH:$HOME/bin
BASH_ENV=$HOME/.bashrc
USERNAME=""

export USERNAME BASH_ENV PATH 

第一行表示出檔案本身的名字(這是一個非常好的習慣﹐如果您會寫自己的程式或腳本﹐也應該如此)。接著是告訴shell一些使用者自定的功能﹐這些設定通常會寫在 ~/.bashrc 這個檔案裡面﹐如果您的家目錄沒有這個檔案也不要緊﹐可以參考 /etc/bashrc 這個檔案。然後是一些使用者自定的環境設定﹐其中有一個關於 PATH 的設定﹐如果您沒忘記在“電腦基礎”裡面關於DOS的檔案結構和 AUTOEXEC.BAT 這個檔案內容的話﹐應該知道 PATH的作用了。

例如﹕您安裝了某一個程式在自己家目錄下面的 bin 裡面﹐如果您要執行這個程式﹐那麼就要輸入絕對的路徑(PATH)才行。但一旦您將‘$HOME/bin’這個路徑加在PATH裡面﹐然後您就可以只輸入該程式的檔案名稱就可以了。有時候﹐對一些程式來說﹐也要回到其自身目錄去讀取檔案﹐如果該目錄不出現在 PATH 裡面﹐或許就找不到了﹐當然﹐這是對那些設計不那麼完善的程式而言啦。

有時候﹐當您自己寫好一個script﹐然後興衝衝就忙著試一試﹐結果卻告訴您 command not found 什麼的﹐這可能是由於您忘了加上路徑﹐也就是忘了在檔案名字前面加上‘./’﹐這是告訴系統﹕檔案在當前的目錄之內。如果您覺得這樣太不方便了﹐可以在 ./bash_profile 裡面的PATH 加上“:.”就可以了。在PATH中的路徑﹐都是用“﹕”來分隔的﹐所以﹐您的PATH看上去就應該有點像這樣﹕
PATH=$PATH:$HOME/bin:.

不過﹗現在的Linux 都不建議您將當前目錄路徑(即“.”) 放進PATH中﹐據說是基於安全理由。別問我是什麼安全理由﹐我也是混飯吃而已﹐知其然不知其所以然啦。

(哈哈~~ 答案找到了哦﹐這要非常多謝 Neil Lee 兄的幫忙﹕因為如果某心存不良的user在自己的目錄下放了一個破壞系統的檔案(or病毒),又碰巧你用root去執行他,那不就完蛋了?舉個例子說,有個傢伙在他的目錄下寫了一隻叫做 ls 的病毒,如果你的 root 的 path設定了 ./ ,剛好你又cd到那個目錄下,一執行 ls 就中了那個傢伙的圈套了。)

用慣了DOS的朋友﹐在 Linux 裡面也常不自覺的輸入 DOS 的命令格式 (事實上﹐DOS的命令都是改自Unix的)﹐現在的Linux為了照顧DOS的慣性使用者﹐也讓您可以打進DOS命令的名稱來得到相類似的結果。很明顯一個例子是﹕‘dir’命令﹐使用以前的Linux﹐如果您輸入‘dir’只會得到 command not found 的回應。不過﹐現在您試著輸入 dir 呢﹐和輸入 ls 的結果是一樣的。這是怎麼做到的呢﹖其實很簡單﹐使用的是 Linux 的 alias (別名) 功能﹐現在請您輸入﹕
alias dir='ls -al'

然後再打 dir 試試﹖您就發現和輸入 ls -al 是一樣結果的。假如您覺得這樣很好用﹐那麼您可以將這句加進 ~/.bashrc 裡面﹐這樣您下次登入之後﹐打 dir 就不用打 ls -al 了。

還有﹐要注意的是﹕修改了環境設定檔後﹐通常會在您下次登錄的時候才生效。如果您想讓設定馬上生效﹐可以執行 soure 命令﹐後接設定檔的路徑﹐就可以了。

認識shell script

如果您以前寫過一些DOS的BATCH檔案﹐相信寫起shell script(腳本)應該不是很難的事情。不過﹐比起DOS的BATCH檔案﹐Linux的shell script功能強多了﹐而事實上﹐Linux的許多設定檔﹐都是shell script來的。當您打開一個檔案﹐如果第一行是這樣起首的﹕
#!/bin/sh

或指向其他的shell﹐這個檔案就十有八九是shell script了。簡單來說﹐一個shell script 會根據條件而為使用者執行一連串的命令。關鍵的字眼在於“條件(condition)”﹐也就是諸如“if....then.....else..”這樣的敘述。在 script 語言中﹐由“#”到句子末的部份﹐都會被視為“註解”﹐也就是不會被執行的﹔如果句子是用“\”結尾的話﹐則代表下一個句子是連接到這個句子末尾的﹐並不當一個新句子看待。如果您善於設定不同的條件而讓shell script執行不同的命令﹐做起事情來就時半功倍了。

這裡並不打算教您如果寫shell script﹐不過您也可以在 /etc/rc.d下面的目錄裡發現大量的shell script。其中有一個檔案叫﹕“rc.local”﹐它有點像DOS的Autoexec.bat那樣﹐您可以將一些每次開機都要執行的自定程式寫在裡面。至於其他的 rc﹖.d 這裡目錄﹐則分別裝載著適合不同的run level而執行的開機和關機shell script。

說到 run level﹐如果您懂得在DOS下面用config.sys和autoexec.bat 來配備不同的開機環境﹐那麼也就好理解多了。不同的 run level 都會執行不同的程式來設定系統環境﹐其中run level 0、1、6 是系統保留的﹐其他的 run level 都可以自己行制定。以前﹐Linux 預設的run level 是3﹐開機後會得到 文字模式的提示。不過﹐如果您在安裝 Redhat 6.0 的時候設定好了 Xwindows﹐同時接受用Xwindows界面來做登入﹐那麼﹐其 run level 就換成 5 了。至於要指定開機進入哪一個 run level﹐您可以在 /etc/inittab 修改﹐您會發現其中有一行是這樣的﹕
id:3:initdefault:

在“id:”後面的數字就是用來指定預設 run level 的了。在此例中﹐在指定預設 run level 是‘3’﹐系統在開機的時候就會執行 /etc/rc.d/rc3.d 目錄下面所有以 “S”(Start)開頭的 shell script 了﹐而在 S 後面的數字﹐則規定出 shell script 被執行的順序﹔如果關機呢﹖則會執行所有以 “K”(Kill)開頭的 shell script。如果您的預設 run level 是 5 的話﹐系統則會執行 /etc/rc.d/rc5.d 目錄下面的腳本了。

或許﹐您已經發現﹐在 /etc/rc.d/rc﹖.d 目錄裡面的檔案﹐其實都是 link 來的﹐原本的檔案都在 /etc/rc.d/init.d 目錄裡面。如果您嘗試輸入這些 shell script 的檔案名稱﹐您很可能會的到這樣的回應﹕
Usage: xxxxxxx {start|stop|restart|reload|status|probe}

在“{}”裡面的選項﹐就是您執行該 shell script 的參數了﹕第一是 start﹐如果該 script 所執行的程式還沒啟動的話﹐可以用 start 來啟動﹔第二個是 stop﹐如果程式已經被啟動了﹐可以將之停止﹔第三個是 reload﹐程式不會被終止﹐但會重新讀取設定數據﹔第四個status﹐可以讓您看一下程式的目前狀態如何﹔最後一個 probe 呢﹐則不是所有 script 都有這個參數的﹐它可以用來進行程式偵測。

比如說﹐如果您修改了網路的一些設定﹐在MS Windows系統裡面﹐您有很大機會會看到“重新啟動系統”的提示。不過﹐在Linux 裡面﹐則要完全戒掉這個習慣﹕也就是動不動就重新啟動系統。您只要執行﹕
/etc/rc.d/init.d/network reload

或是使用 restart 做參數就可以了﹐省時省力﹐怎一個方便了得﹗其實﹐在 Linux 裡面﹐除了要驚動核心 (例如改動硬體)﹐基本上都無需重新啟動系統的。

認識Daemon

在 Linux 系統下面﹐我們通常有兩種方式來啟動服務。第一種我們管它叫 stand alone﹐也就是﹐該服務可以一開機就載入﹐然後一直的執行著﹐這樣比較適合一些常用的和非常繁忙的服務。不過﹐大多數的服務﹐都會以 daemon 的方式載入﹐這個daemon 就好比是公司的接線生﹐它會不停的傾聽著傳給系統的請求﹐然後將請求轉給真正能解決問題的服務來處理。這樣有個好處是﹐服務本身就不用去傾聽系統請求了﹐也就不用一開始就載入一大堆的服務來把系統擠得滿滿的。

如果您看一看 /etc/inetd.conf 這個檔案﹐您會看到其中一部份內容有點像這樣﹕
#
# These are standard services.
#
ftp     stream  tcp     nowait  root    /usr/sbin/tcpd  in.ftpd -l -a
telnet  stream  tcp     nowait  root    /usr/sbin/tcpd  in.telnetd
#
# Shell, login, exec, comsat and talk are BSD protocols.
#
shell   stream  tcp     nowait  root    /usr/sbin/tcpd  in.rshd
login   stream  tcp     nowait  root    /usr/sbin/tcpd  in.rlogind
#exec   stream  tcp     nowait  root    /usr/sbin/tcpd  in.rexecd
#comsat dgram   udp     wait    root    /usr/sbin/tcpd  in.comsat
talk    dgram   udp     wait    root    /usr/sbin/tcpd  in.talkd
ntalk   dgram   udp     wait    root    /usr/sbin/tcpd  in.ntalkd
#dtalk  stream  tcp     waut    nobody  /usr/sbin/tcpd  in.dtalkd
#

這個檔案是一個負責處理 TCP/IP服務的 daemon﹐叫 inetd (通常﹐daemon 的名字都以“d”來結尾的)使用的。在設定檔案中﹐每一個句子都指定一個服務的處理。首先是服務的名字﹐例如﹕ftp、telnet、talk 等﹔然後是該服務的數據類型﹐如﹕stream 或 datagram 等﹔然後是使用的傳輸協定 (transport protocol)﹐如﹕TCP 或 UDP 等﹔接下來是 wait 或 nowait﹐這是告訴系統﹐如果該服務正在處理上一個請求﹐是否需要等待其結束之後再處理新的請求﹔再來是指定服務的執行者是誰﹐如﹕root 或 nobody 等﹔然後是協定和服務的執行程式﹐以及參數等信息。

利用這個設定檔﹐daemon 就可以將請求傳給正確的服務去執行了﹐但是﹐daemon 又怎麼知道哪個請求該傳給誰呢﹖如果您沒忘記我們在“網路基礎”中討論 TCP 封包時提及的 ip 和 port 的話﹐應該知道 ip 是門牌﹐port 是門口。但我們不妨可以這樣想象﹕一個門牌可以有好幾個門口哦~~~。

如果沒有 daemon﹐每一 service 各佔一個門口﹐它們得自己聽有沒有人來敲門。有了 daemon 之後﹐所有門口都由 daemon 來聽﹐各 service 在客廳上打麻將﹐只有當 daemon 呼叫某某 service ﹐才會去處理工作。如果 daemon 打瞌睡了﹐或偷會情人去了﹐那麼各 service 就一直打麻將下去....當然﹐也有些 service 還是愛自己坐在門口的﹐因為外面的美女特多~~~

以上比喻應該好理解了吧﹖現在請您看一下 /etc/services 這個檔案﹐您會看到其中一部份內容有點像這樣﹕
ftp-data        20/tcp
ftp             21/tcp
fsp             21/udp      fspd
ssh             22/tcp                  # SSH Remote Login Protocol
ssh             22/udp                  # SSH Remote Login Protocol
telnet          23/tcp
# 24 - private
smtp            25/tcp      mail
# 26 - unassigned
time            37/tcp      timserver
time            37/udp      timserver

在這個檔案裡面﹐每一行都指定了每一個服務所對應的 port 和 傳輸協定類型。這樣﹐inetd 這個 daemon 傾聽著所有的 port ﹐當發現請求的時候﹐就可以根據這個檔案的設定以及 /etc/inetd.conf 的設定將請求送給正確的服務了。

 

 


© 2000 Netman 網中人
Last Updated: Sep 30, 2000