Linux常見技術支持問題十一則

解答linux技術支持中常見的十一個問題,例如多重啟動、性能調整、檔同步、改變檔清單預設顯示方式、多台機器的時鐘同步、郵件備份,等等。

一. 我想要讓Apache為大量的連接提供服務。為了減小創建進程所需要的時間,我把Apache子進程數量配置為固定的1000。系統的性能很差,有時甚至拒絕連接。你有什麼建議嗎?

A: 看來你很可能遇到了一個通常稱為“thundering herd”(異乎尋常地聚集)的問題。Apache和Linux的文檔都詳細地說明了這個問題,你可以用幾種方法來解決它。

在Linux中,這種情形通常從進程“wake”(喚醒)發展而來。當一個新到達的連接要求Apache/Linux提供服務時,系統向所有正在休眠的進程發出通知。這時,所有這些進程會試圖獲得對新連接的控制權。但是,它們之中只有一個能夠獲得成功,所有其他進程都將失敗並轉入休眠狀態。這被稱為“wake all”(全部喚醒)。Linux 2.2和更早的內核都按照這種方式進行處理。

當正在休眠的Apache進程比較少時,它不會成為問題。通常,Apache會利用httpd.conf中的MinSpareServers和MaxSpareServers配置變數調整休眠進程的數量。然而,如果MaxSpareServer值高得異乎尋常,那麼它可能導致性能問題。我通常把MaxSpareServer值設置為MaxClients值的百分之五到十之間。

如果你的MaxSpareServers值高得異乎尋常,只要減小這個值就可以立即提高性能。一些內核不會遇到這個問題,因為它們具有一種利用“wake one”(喚醒一個)的能力,“wake one”允許為每個連接請求喚醒一個進程。BSD具有這個能力,Linux 2.4內核也一樣。

為了利用“wake one”能力,編譯Apache的時候必須指定一個特殊的選項。如果為2.4內核配置Apache,在編譯之前請按照下面的示例執行命令,它將改善具有“wake one”能力的內核的性能:

# CFLAGS='-DSINGLE_LISTEN_UNSERIALIZED_ACCEPT' ./configure

為給數量巨大的網路連接提供服務,Apache提供了許多調整參數。Apache有一個固定的最大允許連接數量限制,如果要把它設置成大於256,你必須重新編譯Apache。

另外,為了適應大規模服務的要求,Linux也需要進行一些檔案系統方面的調整。你還要檢查一下Linux通過編譯方式固定的進程、系統級、使用者級限制。

簡而言之,當你為了巨大的Apache進程/連接數量而進行調整時,有大量的因素必須考慮。“thundering herd”也許是被忽視最多的問題,但其它需要考慮的因素還有很多。

欲知更多為了提高連接數量而調整Apache的資訊,請訪問http://linuxperf.nl.linux.org/webserving。

二. 我得到了一個伺服器上的帳號。由於管理員推薦使用ssh,這個帳號被禁止使用telnet和ftp。什麼是ssh?如何使用?他們為什麼要禁用telnet?

A: ssh是“secure shell”的簡稱,它完全可以替代telnet。ssh也有一個檔複製命令,即scp(安全拷貝),利用這個命令可以在不同的機器之間移動檔。

由於telnet和ftp的設計不是很安全,許多管理員禁用了telnet和ftp。用telnet和ftp協定登錄伺服器時,密碼以明文的形式發送給伺服器,懷有惡意的人可能監聽網路上傳輸的資料包,進而得到使用者的登錄資訊。雖然發生這種事情的可能性不大,但如果使用象ssh之類的協議,我們可以完全防止這類事情發生。

在使用方法上,ssh和telnet很相似。然而,ssh不僅加密登錄名字和密碼,而且加密整個傳輸過程。因此,ssh能夠防止任何在你和伺服器之間的第三者看到傳輸內容。

有一個廣受歡迎的免費ssh實現,它屬於OpenBSD系統,但也可以在Linux上運行。OpenSSh可以從http://ftp.openbsd.org/pub/OpenBSD/OpenSSH下載。如果你的系統以rpm包為基礎,你可以在portable/rpm目錄下找到rpm包。(直到最近,OpenSSH所用的加密演算法之一還有專利限制。但現在情況已經有了變化。請參見http://www.rsasecurity.com/developers/total-solution)。

安裝好ssh之後,我們可以很方便地在遠端伺服器上利用ssh獲得一個shell。例如,假設我執行:

# ssh dtype@trove.sourceforge.net

首先我看到系統提示輸入密碼,輸入後我就在遠端機器上獲得了一個shell。從這裡開始,ssh的會話過程和telnet會話相似。不同之處在於,我能夠確信所有在我和伺服器之間傳輸的資料都已經經過加密。

如果你很熟悉rsh和它的選項,那麼你很快就可以開始使用ssh。ssh被設計成和rsh具有相同的運作方式。一般情況下,能夠用rsh作為傳輸埠的程式都允許用ssh來替代(例如rsync)。

安全複製命令scp的用法也很簡單,它的語法和cp的語法很相似。例如,要把index.php檔複製到dtype.org伺服器,則我們使用如下命令:

# scp index.php dtype@dtype.org:/usr/local/apache/htdocs/

此時,我們將看到密碼輸入提示(正如ssh)。接下來,本地機器目前的目錄下的index.php檔被複製到dtype.org的/usr/local/apache/htdocs/,使用的登錄名字是dtype。

要瞭解有關OpenSSh的更多資訊,請參見http://www.openssh.com,從這裡你可以找到有關安全協議的詳細說明。

三. 我有一台可攜式電腦。我想要保證便攜機和桌上型電腦上都有最新的資料檔案。你有何建議?

A: 有一個優秀的工具rsync能夠完成這個任務。rsync提供了一種保持兩組檔相同的方法。它以Andrew Tridgell(SAMBA專案的創始人)設計的演算法為基礎。Andrew Tridgell的演算法允許只傳輸對檔的改動。

rsync一般被看成是一個標準的系統工具,因此你的系統上很可能已經安裝了rsync。如果它還沒有安裝,那麼你的Linux安裝盤上應該有它的包檔,或者你也可以從http://rsync.samba.org下載最新的原始程式碼。在命令列直接輸入rsync將提示用法說明,你可以用這種方法測試rsync是否已經安裝。

要保持檔同步,所有機器(在本例中,這是指你的可攜式電腦和桌上型電腦)都必須安裝rsync。另外,這兩台機器應該能夠通過網路互相看到對方。

我強烈建議用ssh作為兩台機器之間的通信機制。但還有其他幾種配置rsync傳輸器的方法,包括rsh和rsync daemon模式,rsync文檔對此有詳細說明。請參見本文有關ssh的說明瞭解更多資訊。

rsync命令的語法和cp命令很相似。從本質上看,你是在把檔從一個位置複製到另一個位置,但rsync多了幾個cp命令沒有的選項。和通常的檔複製相比,檔同步最大的不同之處是你必須指定一台非本地的機器(比如你的桌上型電腦)。

你應該仔細考慮哪些檔要在機器之間保持同步。最好把這些檔放到可攜式電腦的某個專用目錄,避免同步那些不需要同步的檔。例如,你的主目錄下可能有數百兆流覽器緩衝資料。通常情況下,你不會想要傳輸這些資料。

我在自己的桌上型電腦器上創建了一個/home/drew/data目錄,用這個目錄來保存所有資料檔案;為了簡便起見,我在便攜機上也創建了同樣的目錄。

為了用rsync把檔從桌上型電腦同步到便攜機,我在便攜機上輸入下面的命令:

# rsync -vazu -e ssh --delete drew@desktopname:/home/drew/data/ /home/drew/data/

這個命令告訴rsync利用ssh把桌上型電腦上的/home/drew/data目錄複寫到便攜機的同一目錄。為了讓這個命令能夠順利執行,我必須能夠在不依賴rsync的情況下用ssh進入drew@desktopname。如果你不能,請檢查並確保ssh已經正確安裝且可以運行。

下面是對上述命令的分析:-v選項告訴rsync輸出詳細提示資訊;-a選項要求rsync以“archive”模式操作,此時rsync將複製目錄、符號連接等;-z選項用於傳輸時壓縮資料;-u選項表示“只進行更新”,防止rsync覆蓋便攜機上比桌上型電腦新的檔。要讓這個選項能夠正確發揮作用,兩台機器的系統時鐘必須同步。

我用-e ssh選項強制rsync用ssh作為傳輸機制。預設情況下,rsync將使用rsh。--delete選項有點危險,它告訴rsync刪除便攜機上所有在桌上型電腦上不存在的檔。剛開始使用rsync命令時,我建議你不要加上這個選項,直到你熟悉了rsync命令的語法以及該選項的後果。

要把檔從便攜機同步到桌上型電腦時,我在桌上型電腦上執行一個相似的命令:

# rsync -vazu -e ssh /home/drew/data/ drew@desktop
name:/home/drew/data/

注意這次我省略了--delete選項,這是因為對於桌上型電腦,我寧願不使用自動刪除功能。你可能想要加上這個選項,但應該小心。

rsync命令還有其他許多選項,你可以通過man文檔查看這些選項,或者訪問http://rsync.samba.org。

四. 我想要保證幾台機器的系統時鐘同步,有什麼簡便方法嗎?

A: ntpdate程式正是為這個目的設計,而且它很簡單易用。它使用一種協議查詢一個或多個時間伺服器,然後為你的機器設置正確的系統時間。

首先你應該確定使用哪一個時間伺服器。雖然你可以設置自己的某一台機器作為時間伺服器,然後用這台機器同步其他機器的時鐘,但我不推薦這麼做。這種做法要求你自己完成額外的管理工作,而且你必須保證時間伺服器的時鐘精確。

我更喜歡以那些正式的時間伺服器為參考,然後同步所有自己的機器。你可以從http://tycho.usno.navy.mil/ntp.html找到這些時間伺服器的一個清單。

ntpdate命令的語法很簡單,但必須用root身份運行它。你可以在命令列中指定一個或者多個時間伺服器,下面我要使用的是USNO清單中的前面三個。這樣,ntpdate將能夠選擇一個最好的時間伺服器進行同步。

# ntpdate ntp2.usno.navy.mil tock.usno.navy.mil tick.usno.navy.mil
14 Nov 17:19:04 ntpdate[16015]: adjust time server 192.5.41.40 offset -0.017641 sec

為了保證時鐘精確,我們可以把ntpdate命令放入crontab。但是,對於那些不是一直開啟的機器(比如便攜機),這個命令放入啟動腳本或手工運行更合適。

必須指出的是,ntpdate設置的是系統時鐘,但它不設置硬體時鐘(電池供電的時鐘)。要讓硬體時鐘反應系統時鐘的值,請使用如下命令:

# hwclock –systohc

如果ntpdate還沒有安裝到系統上,它應該可以從Linux安裝盤安裝。有關ntpdate命令的更多說明,請參見這個命令的man文檔。

五. 在一台雙重啟動的機器上,我把Windows安裝到了另一個分區之後,不能再看到LILO的啟動提示。怎樣才能讓它重新出現?

A: 在Microsoft Windows作業系統安裝期間,主引導記錄(MBR)一般會被覆蓋,機器啟動時將進入新的OS。Linux分區並沒有消失,但MBR中不再有LILO。

由於你只是想啟動Linux並返回LILO,這個問題比較簡單。如果你事先考慮到了這個問題,那麼可能你在不能啟動Linux之前已經做好了Linux的啟動軟碟。但是,讓我們假定你沒有Linux啟動軟碟……

如果身邊有其他Linux系統,你可以用那台機器方便地做出一個啟動軟碟(假設兩台機器的體系相同)。如果沒有,請啟動Windows(你實在沒有別的選擇了,對吧?)。有一個很簡單的dos工具叫做rawrite2.exe,它能夠從映射檔製作出軟碟。Rawrite2.exe可以從許多Linux發行的網站下載,包括Debian GNU/Linux的網站。

另外,你可以從隨便哪個Linux發行的網站下載一個簡單的拯救磁片映射檔。我曾經試過Debian拯救磁片並獲得了成功,這個磁片映射檔可以從debian.org找到。

下載磁片映射檔之後,從DOS命令列執行rawrite2.exe:

C:\IMAGES\> rawrite2 -f rescue.bin -d a:

成功寫入軟碟後,你就有了Linux拯救開機磁片。現在,你可以從這個軟碟啟動進入內核,然後要求內核從硬碟裝入根檔案系統。如果你不知道是哪一個檔案系統,可能要多試驗幾次。從軟碟啟動之後,你必須輸入類如下面的命令:

LILO: linux root=/dev/hda1

根據系統的配置情況,實際所用的設備也各不相同。如果你的系統是IDE,你要裝入的將是hda、hdb、hdc或者hdd(依次是:第一個IDE控制器的主/從驅動器,第二個IDE控制器的主/從驅動器)。如果是SCSI介面,你要裝入的將是sda、sdb等。跟在驅動器後面的數字代表磁碟分割。

對於典型的IDE配置,Linux根分區通常在hda1到hda3之間。如果指定了一個錯誤的根分區,你將看到內核提示它為什麼“unable to mount root partition”的錯誤資訊。正確指定根分區之後,Linux將正常啟動。如果你瞭解系統的基本配置情況,只要多試幾次你就可以正確地啟動Linux。

成功進入Linux之後,剩下的問題就比較簡單了。也許你想要為Windows分區增加一個入口,請把下面顯示的內容加入到/etc/lilo.conf,注意根據實際情況替換驅動器和分區參數。

other = /dev/hda4 -- # DOS/Windows分區
table = /dev/hda -- # 當前的分區表
label = dos -- # 任意你想使用的名字

把上述內容放入lilo.conf內配置Linux部分的前面或者後面,具體由你希望預設啟動哪一個作業系統決定(預設啟動第一個列出的作業系統)。用超級用戶身份運行lilo,它會把自己安裝到MBR。重新啟動,你就可以看到LILO:提示了。利用lilo.conf中列出的標籤可以選擇啟動哪一個作業系統。

希望本文的回答能夠使你滿意。你可以在http://linuxdocs.org/HOWTOs/LILO-crash-rescue-HOWTO.html找到更多的資訊。

六. 怎樣才能改變目錄清單中檔的預設顯示方式?

A: ls命令能夠以各種方式顯示檔清單。經常使用的選項包括:-a,表示不隱藏“.”文件;-l,表示詳細清單格式,包括檔案屬性和大小;-color,根據檔的屬性用不同的顏色顯示檔/目錄。執行man ls命令可以得到ls命令選項的完整說明。

設置ls預設屬性最簡單的方法之一是建立一個shell別名。這裡我以bash為例進行說明。請把下面這行命令加入主目錄的.bashrc文件:

alias ls = ls -a -color

另外,你也可以在當前shell中直接輸入這個命令,使得別名立即生效(直至你關閉shell)。

.bashrc檔中的命令在你每次啟動一個互動式shell的時候自動執行,確保了別名的自動設置。

七. 在一個多重啟動的系統中,我希望在不同的作業系統之間共用資料。最好的辦法是什麼?

A: 如果說Linux有一個擅長的地方,那麼這個地方就是共用。有許多種方法能夠實現不同檔案系統之間的檔共用。有些人建議創建一個獨立的FAT分區實現作業系統之間的共用,然而,一種更好的方法是:允許每一個作業系統裝入其他作業系統的檔案系統。

直到不久之前,還沒有什麼好的工具能夠在Windows下裝入ext2(Linux)檔案系統。然而,Linux一直能夠很方便地讀寫Windows/DOS FAT檔案系統。最近出現了許多讀/寫ext2檔案系統的Windows工具,但總地看來,對於共用檔案系統來說,這些工具遠遠不如Linux中現有的工具那樣值得信賴。

要在Linux下裝入FAT檔案系統,Linux內核必須提供適當的支援。大多數默認安裝的內核已經包含這方面的支持,但是,如果你選擇了自己編譯Linux內核,請確保選中了FAT和VFAT檔案系統支持。如果你不想把它編譯到內核裡,FAT和VFAT支援也可以作為動態裝入模組運行。

無論是哪種情況,你必須先在Linux下創建一個掛接點(Mount Point)才能共用檔案系統。它可以是你所選擇的檔案系統內的任何目錄,但最好使用一個具有明確含義的名字(如本例的/mnt/msdos)。

# mkdir /mnt/msdos

接下來,你應該在/etc/fstab中為FAT檔案系統加入一行。如果你的內核支援VFAT,你將能夠查看和編輯新版Windows所使用的長檔名。

試著把下面這行內容加入/etc/fstab(注意在這個例子中,我們使用了硬碟的第三個分區/hda2,你應該根據自己系統的具體情況替換這個分區):

/dev/hda2/mnt/msdosvfat defaults 0 1

如果不想讓這個檔案系統在啟動的時候自動裝入,你可以在defaults選項之後加入一個“,noauto”。現在,你應該能夠以root身份裝入Windows分區了。

# mount /mnt/msdos

如果你看到錯誤資訊提示檔案系統存在問題,那麼,很可能你指定了一個錯誤的檔案系統。這時,你應該檢查分區並重新試驗。

如果你看到錯誤資訊提示內核對vfat檔案系統的支持存在問題,請試著把/etc/fstab入口從vfat改成msdos。如果有效,那麼你的內核不支持Windows長檔名。如果無效,那麼你的內核沒有為DOS或Windows提供合適的檔案系統支援。

假設一切都能夠按照設想地那樣完成它們的任務,那麼,現在你應該能夠從Linux下的/mnt/msdos掛接點(或者你所創建的其他掛接點)訪問Windows資料。如果你按照上面介紹的方式進行設置,只有root才能寫入這些檔。記住,FAT系統不提供對使用者許可權的支援。

八. 我有一個Perl腳本,但它不會執行。執行的時候出現bash提示:./script.pl: No such file or directory error。但實際上這個檔卻是存在的,而且它可執行。這是為什麼呢?

A: 可執行腳本通過腳本的第一行命令告訴shell應該用哪一個程式來執行當前腳本。這個命令總是第一行,而且它類似於:

#!/usr/bin/perl

如果第一行命令指定的程式確實存在,則系統利用該程式解釋執行腳本的剩餘部分。如果這個程式不存在,你就會看到“No such file or directory”錯誤。這種腳本執行方式可用於大多數shell腳本,Perl也不例外。

用“#!/bin/sh”或“#!/bin/bash”作為腳本第一行的情況並不少見。一般地,修正該問題的方法也很簡單。Perl可能不在使用者的系統目錄下。執行which perl,你就可以找到Perl所在的位置。然後,修改腳本的第一行使之符合Perl所在的實際位置,這樣你就可以修正這個問題了。

九. 我安裝了一個程式。但我執行它的時候,系統顯示“error in loading shared libraries...no such file or directory”。我已經找到了它說的檔。為什麼我還會得到這個錯誤?

A: 有的程式要用一些稱為“動態庫”的檔保存部分代碼,這部分代碼可以供其他程式使用。當程式執行時,作業系統會在某些預定義的地方尋找這些代碼庫。如果不能找到這些庫,作業系統就會顯示象你所描述的那種錯誤。

如果你看到了這個錯誤,那麼下面兩個原因必居其一:或者你根本沒有程式所要求的庫;或者雖然你有這個庫,但Linux由於某種原因不能找到它。如果你沒有這個庫,那麼你應該想辦法得到它;否則,只要進行一些簡單的設置就能解決問題。

解決問題的一種方法是確保檔安裝到了標準的庫目錄,包括/lib和/usr/lib。然而,簡單地把檔移入這些目錄將干擾包管理軟體的工作,因此必須避免。把檔安裝到標準目錄應該通過包管理軟體或在配置/安裝時進行。

如果你要讓庫檔留在原來的位置,那麼,你首先必須找到這些檔,然後把目錄加入到搜索路徑之中。

例如,假設我們要尋找錯誤資訊中出現的檔。首先以超級用戶身份執行命令“# find / -name filename.so”。找到目錄之後,編輯/etc/ld.so.conf檔把該目錄加入到檔末尾。再運行ldconfig,它將為運行時連接器重新構造連接和緩衝。這就是全部的工作!現在你的程式應該能夠找到它運行所需要的庫檔了。

十. 我的硬碟空間不足,現在想要找到系統中最大的目錄/檔,看看能否刪除它。有沒有幫助我完成這個任務的工具?

A: 有兩個簡單的命令能夠幫助你輕鬆地完成這個任務。這兩個命令就是du和sort。

du命令用來計算檔或目錄的大小。這個命令有許多選項,下面的說明説明你掌握這兩個命令的基本用法。你最好以超級用戶身份執行這兩個命令,否則可能看到大量“Permission denied”錯誤,因為很可能你沒有訪問許多目錄的許可權。

找出所有根級目錄及其子目錄的大小:

# cd /
# du -max-depth=1

修改max-depth參數,對更深一層的目錄進行統計:

# du -max-depth=2

如果不指定max-depth參數,du將統計出目錄樹中所有目錄和檔的大小。結合sort命令運用du命令,你就可以方便地流覽du的輸出結果。

查看硬碟上所有目錄和檔的大小,按照大小排序(這可能需要不少時間):

# du | sort -nr | less

注意,隨意地刪除檔可能非常危險,特別是那些作業系統必需的檔。如果要尋找那些擁有大型主目錄的使用者,這種技術也許是最合適的。如果你找到了看來不再需要的程式檔,最好的刪除方法應該是:找出安裝這個檔的包,然後用rpm(基於rpm的系統)或者dpkg(基於deb的系統)把整個包都刪除乾淨。

十一. 為了進行備份,我希望複製並保存所有收到的email。我應該怎麼做?

A: 這可以通過procmail程式輕鬆地完成。這裡我不再介紹procmail的安裝和配置,因為現在的大多數包管理系統(RPM,DEB)能夠很好地做到這一點。如果你已經有了一個Linux系統的帳號(或者系統屬於你自己所有),很可能procmail已經安裝和設置完畢。如果沒有,你可以聯繫系統管理員,或者自己用包管理器安裝。

要快速找出系統中是否已經安裝了procmail,請執行如下命令:

# which procmail

如果procmail已經成功安裝,which將顯示出procmail的位置(可能是/usr/bin/procmail)。在你的主目錄下創建一個.procmailrc文件,許可權0700:

# touch ~/.procmailrc
# chmod 0700 ~/.procmailrc

procmail“recipes”的選項(對於不同類型的email,決定採取什麼動作的配置區域)有很多。procmailrc的man文檔描述了其中一部分。然而,作為一個簡單的起步,請在.procmailrc檔內試一下下面的內容,注意根據具體情況進行適當的替換:

LOGFILE=$HOME/.procmail-log
:0 c:
/home/dtype/Mail/backup
:0 c:
* ^FROMdtype@dtype.org
/home/dtype/Mail/sent-mail
:0
* ^Sender: owner-linux-kernel
/home/dtype/Mail/linux-kernel

LOGFILE指定了一個檔,這個檔將記錄procmail所有的活動。如果出現任何問題,它是你首先應該檢查的地方。

這個.procmailrc檔有三項不同的內容。第一項指定了保存所有備份郵件的檔(在本例中,它是/home/dtype/Mail/backup)。“c:”告訴procmail保存郵件並繼續進行正常的郵件處理,包括設定檔的剩餘部分。如果不指定“c:”,所有郵件被保存到備份檔案,但不再保存到其他地方。

為了進行跟蹤,我們想要保存外發的email,.procmailrc檔中包含了一項為外發email設置的內容。

最後一項內容是一個利用procmail保存特定郵寄清單所傳入email的例子,本例中的郵寄清單是linux-kernel郵寄清單。procmail將在郵件的Sender:頭中檢查“owner-linux-kernel”文字。注意這裡不再包含“c:”這是因為我們希望郵件發送到指定的郵箱,但不再同時發送到Inbox。

現在你已經可以上手使用procmail。如果你要管理的email數量很大,procmail值得你學習。至少對於前面所討論的備份問題來說,procmail很有用。

(此篇文章為網路轉載,如有冒犯,請來信告知,當即刻移除!)