diff --git a/zh_TW.Big5/books/handbook/basics/chapter.sgml b/zh_TW.Big5/books/handbook/basics/chapter.sgml index 4ed225bafc..f570ed39a6 100644 --- a/zh_TW.Big5/books/handbook/basics/chapter.sgml +++ b/zh_TW.Big5/books/handbook/basics/chapter.sgml @@ -1,2395 +1,2382 @@ Chris Shumway Rewritten by UNIX 基礎概念 概述 接下來的這一章將涵蓋 FreeBSD 作業系統的基本指令及功能。 大部份的內容在 &unix;-like 作業系統中都是相通的。 如果您對這些內容熟悉的話,可以放心的跳過。 如果您剛接觸 FreeBSD,那您一定要仔細的讀完這章。 - 讀完這一章,您將會了解: + 讀完這章,您將了解: 如何使用 FreeBSD 的virtual consoles &unix; 檔案權限運作的方式以及 &os; 中檔案的 flags。 預設的 &os; 檔案系統配置。 &os; 的磁碟結構。 如何掛載(mount)、卸載(umount)檔案系統 什麼是processes、daemons 以及 signals 。 什麼是 shell ,以及如何變更您預設的登入環境。 如何使用基本的文字編輯器。 什麼是 devices 和 device nodes 。 &os; 下使用的 binary 格式。 如何閱讀 manual pages 以獲得更多的資訊。 Virtual Consoles 和終端機 virtual consoles terminals 有很多方法可以操作 FreeBSD ,其中一種就是在文字終端機上打字。 如此使用 FreeBSD 即可輕易的體會到 &unix; 作業系統的威力和彈性。 這一節描述什麼是終端機console ,以及可以如何在 FreeBSD 中運用它們。 The Console console 如果您沒有將 FreeBSD 設定成開機時自動進入圖形化模式,系統會在啟動的 script 跑完之後顯示登入的提示符號。 您將會看到像是這樣的東西: Additional ABI support:. Local package initialization:. Additional TCP options:. Fri Sep 20 13:01:06 EEST 2002 FreeBSD/i386 (pc3.example.org) (ttyv0) login: 這個訊息在您的系統上會有些許的不同,但是應該會看到類似的東西。 我們感興趣的是最後兩行,最後兩行是: FreeBSD/i386 (pc3.example.org) (ttyv0) 這行包含了剛開機完系統的資訊。 您看到的是在 Intel 或相容處理器的 x86 架構上執行的 FreeBSD的 console 這就是 i386 的意義。 注意即使您不是在 Intel 的 386 處理器上執行 FreeBSD ,一樣是i386。 這不是指你的處理器的型號,這裡顯示的是你處理器的架構 。 這台機器的名字(每台 &unix; 機器都有一個名字)是 pc3.example.org,而您現在看到的是它的系統 console— ttyv0終端機。 最後的一行應該都會是: login: 這是您應該要輸入您的帳號名稱的地方。 下一小節將告訴您如何登入 FreeBSD。 登入 FreeBSD FreeBSD 是一個 multiuser、multiprocessing 的系統。 這是一個正式的名稱,指的是在單一機器上可以同時被不同人使用, 但同時可以執行很多程式的系統。 每一種多使用者系統都需要可以分辨不同使用者的方法。 在 FreeBSD (以及所有的 &unix;-like 作業系統) 中,所有的使用者在執行程式之前必須先登入系統。 每個使用者都有一組獨特的帳號名稱 (username)及密碼(password)。 FreeBSD 在允許使用者執行程式前將會先問這兩個問題。 startup scripts 在 FreeBSD 開機並跑完起動的 script 之後 這些起動的 script 是在開機的時候 FreeBSD 會自動執行的程式。 他們主要的功能是將所有該執行的東西設定好, 並將您設定成背景執行的服務啟動。 ,它將會印出提示字元要求您輸入正確的帳號名稱: login: 在這個範例裡,我們假設您的帳號是john。 在提示字元處輸入 john 並按下 Enter 。 接著您應該會看到另一個提示字元要您輸入密碼 login: john Password: 輸入 john 的密碼,再按下 Enter。 輸入的密碼 不會顯示在螢幕上。 您不需要為此擔心,這樣做是為了安全上的問題。 如果您輸入了正確的密碼,您應該已經登入 FreeBSD。 現在就可以嘗試所有可用的指令了。 您應該會看到MOTD (即今日訊息、Messages Of The Day),後面接著命令提示字元 (一個 #,$, 或是 % 字元)。 這就表示您已經成功登入 FreeBSD 了。 多重 Console 在一個 Console 下執行 &unix; 當然是沒有問題,然而 FreeBSD 是可以同時執行很多程式的。 像 FreeBSD 這樣可以同時執行一大堆程式的作業系統,只有一個 console 可以輸入指令實在是有點浪費。 因此 virtual consoles 就顯得相當好用。 可以設定讓 FreeBSD 同時有很多 virtual console, 用幾個按鍵的組合就可以從一個 virtual console 跳到別的 virtual console 。 每一個 console 都有自已不同的輸出頻道,當從某一個 virtual console 切換到下一個的時候,FreeBSD 會自動處理鍵盤輸入及螢幕輸出。 FreeBSD 保留了特別的按鍵組合來切換 console 在 &man.syscons.4;、&man.atkbd.4;、&man.vidcontrol.1;、以及 &man.kbdcontrol.1;等 manual page 中,對於 FreeBSD 的 console 及鍵盤驅動程式有詳細的技術說明。 我們在這裡不討論細節, 有興趣的讀者隨時可以在 manual pages 中查到關於運作方式的更詳細且完整的解釋。。 您可以用 AltF1AltF2、到 AltF8 來切換 FreeBSD 的不同 console。 當您從一個 console 切換到下一個的時候,FreeBSD 會處理螢幕輸出的儲存及回復。 這就好像有很多虛擬的螢幕和鍵盤, 可以讓您輸入指令到 FreeBSD 執行。 在某一個 console 上執行的程式並不會因為切到別的 console 而停止執行,切換到另一個 console 時,它們仍會繼續執行。 <filename>/etc/ttys</filename> 檔 FreeBSD 預設的虛擬 console 總共有 8 個, 但這並非硬性規定,您可輕鬆設定這些虛擬 console 的數量增減。 有關虛擬 console 的編號跟設定都在 /etc/ttys 這檔案內設定。 可以用 /etc/ttys 檔案來設定 FreeBSD 的虛擬 console。 檔案內每行非註解文字(該行開頭沒有 # 這字)都是設定終端機或虛擬 console。 FreeBSD 預設有 9 個虛擬 console 但只啟動 8 個,也就是以下以 ttyv 開頭的那幾行設定。 # name getty type status comments # ttyv0 "/usr/libexec/getty Pc" cons25 on secure # Virtual terminals ttyv1 "/usr/libexec/getty Pc" cons25 on secure ttyv2 "/usr/libexec/getty Pc" cons25 on secure ttyv3 "/usr/libexec/getty Pc" cons25 on secure ttyv4 "/usr/libexec/getty Pc" cons25 on secure ttyv5 "/usr/libexec/getty Pc" cons25 on secure ttyv6 "/usr/libexec/getty Pc" cons25 on secure ttyv7 "/usr/libexec/getty Pc" cons25 on secure ttyv8 "/usr/X11R6/bin/xdm -nodaemon" xterm off secure 有關各欄位的設定以及其他選項,請參閱 &man.ttys.5; 說明。 Single User 模式的 Console 有關 single user 模式 的介紹在 這邊有詳盡介紹。 在 single user 模式時,能夠使用的 console 只有一個,並無虛擬 console 可用。 而 single user 模式相關設定值可以在 /etc/ttys 檔做調整。 下面以 console 開頭的那行,就是了: # name getty type status comments # # If console is marked "insecure", then init will ask for the root password # when going to single-user mode. console none unknown off secure console 那行前面的註解有提到,可以把那行的 secure 改為 insecure, 如此一來,即使 FreeBSD 進入 single user 模式, 仍會要求您輸入 root 的密碼。 請審慎考慮是否要改為 insecure。 因為萬一忘記 root 密碼的話,若要登入 single user 模式就有些麻煩了。儘管還有其他方式可以登入,但對不熟 FreeBSD 開機程序的人而言,就會相當棘手。 權限 UNIX FreeBSD 源自於 BSD &unix;,繼承了幾個重要的 &unix; 概念。 首先也最明顯,它是一款 multi-user 作業系統。 它可以同時處理多人多工, 負責徹底的分享與管理來自每位使用者對硬碟裝置、週邊設備、記憶體及 CPU 時間的要求。 也因為系統能夠支援多使用者, 所以系統管理的一切都有權限來決定誰可以讀取、寫入或執行資源。 這些權限分別使用三組八進位的數字儲存,一組代表檔案的所有者, 一組代表檔案所屬的群組,而最後一組則代表其他所有人。 表示這些數字的方式如下: permissions file permissions 權限 目錄顯示 0 不可讀取, 不可寫入, 不可執行 --- 1 不可讀取, 不可寫入, 可執行 --x 2 不可讀取, 可寫入, 不可執行 -w- 3 不可讀取, 可寫入, 可執行 -wx 4 可讀取, 不可寫入, 不可執行 r-- 5 可讀取, 不可寫入, 可執行 r-x 6 可讀取, 可寫入, 不可執行 rw- 7 可讀取, 可寫入, 可執行 rwx ls directories 使用 &man.ls.1; 指令時,可以加上 參數, 來檢視詳細的目錄清單。 清單中欄位的資訊包含檔案對所有者、群組及其他人的權限。 在任一個目錄底下執行 ls -l,會顯示如下的結果: &prompt.user; ls -l total 530 -rw-r--r-- 1 root wheel 512 Sep 5 12:31 myfile -rw-r--r-- 1 root wheel 512 Sep 5 12:31 otherfile -rw-r--r-- 1 root wheel 7680 Sep 5 12:31 email.txt ... 在這裡告所您該如何區分 ls -l 第一欄當中的資訊: -rw-r--r-- 第一個 (最左邊) 的字元用來表示這個檔案的類型為何, 除標準檔案以外,尚有目錄、特殊字元裝置 (Special character device)、 Socket 及其他特殊虛擬檔案裝置 (Special pseudo-file device), 在此例當中,- 表示該檔案為一個標準的檔案。 範例中接下來的三個字元中,rw- 代表所有者對檔案擁有的權限。 再接下來的三個字元, r-- 則代表群組對檔案擁有的權限, 最後三個字元,r-- 則代表其他人對檔案擁有的權限。 破折號 (-) 表示沒有權限,範例中的這個檔案的權限, 只允許所有者讀取、寫入檔案,群組以及其他人僅能讀取檔案。 根據以上的表格,此種權限的檔案可以使用 644 來表示, 每組數字分別代表檔案的三種權限。 以上是不錯的方式,但系統該如何控制裝置的權限? 實際上 FreeBSD 對大多的硬碟裝置就如同檔案,程式可以開啟、讀取以及寫入資料如一般檔案。 這些特殊裝置檔案 (Special device file) 都儲存於 /dev 目錄中。 目錄也同如檔案,擁有讀取、寫入及執行的權限, 但在執行權限上與檔案有明顯的差異。 當目錄被標示為可執行時,代表可以使用 cd (更改目錄) 進入該目錄。 也代表能夠存取在此目錄之中的已知檔名的檔案 (當然,檔案仍擁有自己的權限) 尤其,要能夠列出目錄內容,必須擁有目錄的讀取權限。 而當要刪除已知檔名的檔案時,也必須擁有檔案所在目錄的寫入 以及 執行的權限。 還有一些權限,但這些權限主要在特殊情況使用,如 setuid binaries 及 sticky directories。 如果您還想知道更多檔案權限的資訊及使用方法,請務必參閱 &man.chmod.1; 說明文件。 Tom Rhodes Contributed by 權限符號 permissionssymbolic 權限符號可稱做符號表示, 使用字元的方式來取代使用數值來設定檔案或目錄的權限。 符號表示的格式依序為 (某人)(動作)(權限),可使用的符號如下: 項目 字母 意義 (某人) u 使用者 (某人) g 群組所有者 (某人) o 其他 (某人) a 全部(world) (動作) + 增加權限 (動作) - 移除權限 (動作) = 指定權限 (權限) r 讀取 (權限) w 寫入 (權限) x 執行 (權限) t Sticky bit (權限) s Set UID 或 GID 如先前同樣使用 &man.chmod.1; 指令來設定,但使用的參數為這些字元。 例如,您可以使用下列指令禁止其他使用者存取檔案 FILE: &prompt.user; chmod go= FILE 若有兩個以上的符號表示可以使用逗號 (,) 區隔。 例如,下列指令將會移除群組及其他人對檔案 FILE 的寫入權限, 並使全部人(world)對該檔有執行權限。 &prompt.user; chmod go-w,a+x FILE Tom Rhodes Contributed by &os; 檔案旗標(Flag) 除了前面提到的檔案權限外,&os; 支援使用 檔案旗標。 這些旗標增加了檔案的安全性及管理性,但不包含目錄。 檔案旗標增加了管理性,確保在某些時候 root 不會意外將檔案修改或移除。 修改的檔案 flag 僅需要使用擁有簡易的介面的 &man.chflags.1; 工具。 例如,標示系統禁止刪除的旗標於檔案 file1,使用下列指令: &prompt.root; chflags sunlink file1 若要移除系統禁止刪除的旗標,只需要簡單在 前加上 no,例如: &prompt.root; chflags nosunlink file1 使用 &man.ls.1; 及參數 可檢視檔案目前的旗標: &prompt.root; ls -lo file1 輸出的結果如下: -rw-r--r-- 1 trhodes trhodes sunlnk 0 Mar 1 05:54 file1 多數的旗標僅能由 root 使用者來標示或移除,而部份旗標可由檔案所有者設定。 我們建議系統管理者可閱讀 &man.chflags.1; 及 &man.chflags.2; 說明以瞭解相關細節。 目錄結構 directory hierarchy 認識 FreeBSD 的目錄架構,就可對系統有概略的基礎理解。 最重要的莫過於整個目錄的根目錄,就是 / 目錄, 該目錄會在開機時最先掛載 (mount),裡面會有開機所會用到必備檔案。 此外,根目錄還有紀錄其他檔案系統的掛載點相關設定。 「掛載點」就是讓新增的檔案系統,能接到上層的檔案系統 (通常就是「根目錄」檔案系統) 的目錄。 在 這邊對此有更詳細介紹。 標準的掛載點包括了 /usr/var/tmp/mnt 以及 /cdrom。 這些目錄通常會記錄在 /etc/fstab 設定檔內。 /etc/fstab 是記錄各檔案系統及相關掛載點的表格。 大部分在 /etc/fstab 有記錄的檔案系統,會在開機時由 &man.rc.8; script 來自動掛載,除非它們有設定 選項。 其中細節說明可參閱 有關檔案系統架構的完整說明可參閱 &man.hier.7;。 現在呢,讓我們大致先一窺常見的目錄有哪些吧。 目錄 說明 / 檔案系統的根目錄。 /bin/ single-user、multi-user 兩種模式皆可使用的基本工具 。 /boot/ 作業系統開機過程會用到的程式、設定檔。 /boot/defaults/ 預設的開機啟動設定檔,詳情請參閱 &man.loader.conf.5; 。 /dev/ Device nodes,詳情請參閱 &man.intro.4;。 /etc/ 系統設定檔及一些 script 檔。 /etc/defaults/ 預設的系統設定檔,詳情請參閱 &man.rc.8;。 /etc/mail/ MTA(Mail Transport Agent)的相關設定檔,像是 &man.sendmail.8;。 /etc/namedb/ named 設定檔,詳情請參閱 &man.named.8;。 /etc/periodic/ 每日、每週、每月透過 &man.cron.8;; 執行的定期排程 script, 詳情請參閱 &man.periodic.8;。 /etc/ppp/ ppp 設定檔,詳情請參閱 &man.ppp.8;。 /mnt/ 系統管理者慣用充當臨時掛載點的空目錄。 /proc/ Process 檔案系統,詳情請參閱 &man.procfs.5; 及 &man.mount.procfs.8;。 /rescue/ 緊急救援用途的一些 statically linked 程式,詳情請參閱 &man.rescue.8;。 /root/ root 帳號的家目錄。 /sbin/ 供 single-user 及 multi-user 環境使用的系統程式及管理工具 。 /tmp/ 臨時檔案。 一般而言,重開機之後 /tmp 內的東西會被清除掉。 而通常會將 memory-based 檔案系統掛載在 /tmp 上。 這些瑣事可透過 tmpmfs 相關的 &man.rc.conf.5; 環境變數來自動完成 。(或是在 /etc/fstab 內做設定, 詳情請參閱 &man.mdmfs.8;。) /usr/ 主要是使用者所安裝的工具程式、應用程式存放處。 /usr/bin/ 常用工具、開發工具、應用軟體。 /usr/include/ 標準 C include 的相關 header 檔案庫。 /usr/lib/ 函式庫存放處。 /usr/libdata/ 其他各式工具的資料檔。 /usr/libexec/ 系統 daemons 及系統工具程式(透過其他程式來執行)。 /usr/local/ 存放一些自行安裝的執行檔、函式庫等等。 同時,也是 FreeBSD ports 架構的預設安裝目錄。 /usr/local 內的目錄架構大致與 /usr 相同,詳情請參閱 &man.hier.7; 說明。 但 man 目錄例外,它們是直接放在 /usr/local 底下,而非 /usr/local/share,而 ports 所安裝的說明文件則在 share/doc/port /usr/obj/ 在編譯 /usr/src 目錄時所產生的相關架構 object 檔案。 /usr/ports FreeBSD Ports Collection (optional)。 /usr/sbin/ 系統 daemon 及系統工具(直接由使用者執行)。 /usr/share/ 各架構皆共通的檔案。 /usr/src/ BSD 本身的原始碼(或自行新增的)。 /usr/X11R6/ X11R6 相關套件的執行檔、函式庫等(optional)。 /var/ 存放各種用途的 log 檔、臨時或暫時存放、列印或郵件的 spool 檔案。有時候,memory-based 檔案系統也會掛載在 /var。 這些瑣事可透過 varmfs 相關的 &man.rc.conf.5 環境變數來自動完成。(或是在 /etc/fstab 內做設定,相關細節請參閱 &man.mdmfs.8;。) /var/log/ 各項系統記錄的 log 檔案。 /var/mail/ 各使用者的 mailbox 檔案。 /var/spool/ 各種印表機、郵件系統的 spool 目錄。 /var/tmp/ 臨時檔案。 這些檔案在重開機後通常仍會保留,除非 /var 是屬於 memory-based 檔案系統。 /var/yp 記錄 NIS maps。 磁碟組織 FreeBSD 用來尋找檔案的最小單位就是檔案的名稱了。 檔案的名稱有大小寫之分,所以說 readme.txtREADME.TXT 是兩個不同的檔案。 FreeBSD 並不使用副檔名 (.txt) 來判別這是一個程式檔、文件檔或是其他類型的檔案。 檔案存在目錄裡面。 一個目錄中可能沒有任何檔案,也可能有好幾百個檔案。 目錄之中也可以包含其他的目錄; 您可以建立階層式的目錄以便資料的管理。 檔案或目錄的對應是藉由給定的檔案或目錄名稱,然後加上正斜線符號 (/);之後再視需要加上其他的目錄名稱。 如果您有一個目錄 foo ,裡面有一個目錄叫作 bar,這個目錄中又包含了一個叫 readme.txt 的檔案,那麼這個檔案的全名,或者說檔案的路徑就是 foo/bar/readme.txt 目錄及檔案儲存在檔案系統之中。 每個檔案系統都有唯一一個最上層的目錄,叫做根目錄 (root directory)。 然後在這個根目錄下面才能有其他的目錄。 到目前為止大概和其他您用過的的作業系統都差不多。 還是有些不一樣的地方就是了,例如 &ms-dos; 用 \ 當檔案和目錄名稱的分隔符號,而 &macos; 則是用 : 符號。 FreeBSD 的路徑中並沒有使用磁碟機代號或其他的磁碟名稱。 因此,您不可以使用像 c:/foo/bar/readme.txt 這樣子的檔案名稱。 相對的,在 FreeBSD 系統中有一個檔案系統被指定為根檔案系統。 根檔案系統的根目錄由 / 表示。 然後其他的檔案系統再掛載 (mount) 在根檔案系統之下。因此無論您的 FreeBSD 系統上有多少顆硬碟,每一個目錄看起來就像在同一個磁碟上。 假設您有三個檔案系統,分別叫作 ABC。 每個檔案系統都包含兩個目錄,叫做 A1A2 (依此類推得 B1B2C1C2)。 A 為主要的檔案系統;如果您用 ls 指令查看此目錄的內容,您會看到兩個子目錄: A1A2,如下所示: / | +--- A1 | `--- A2 一個檔案系統必須以目錄形式掛載於另一個檔案系統上。 因此,假設您將 B 掛載於 A1 之上,則 B 的根目錄就變成了 A1,而在 B 之下的任何目錄的路徑也隨之改變: / | +--- A1 | | | +--- B1 | | | `--- B2 | `--- A2 B1B2 目錄中的任何檔案必須經由路徑 /A1/B1/A1/B2 才能達到。 所有原來在 /A1 中的檔案會暫時被隱藏起來,直到 B 被「移除 (unmounted)」後才會再顯現出來。 如果 B 掛載在 A2 之上,則會變成: / | +--- A1 | `--- A2 | +--- B1 | `--- B2 上面的路徑分別為 /A2/B1/A2/B2 檔案系統可以掛在其他檔案系統的目錄之上。 延續之前的例子,C 檔案系統可以掛在檔案系統 BB1 目錄之上,如圖所示: / | +--- A1 | `--- A2 | +--- B1 | | | +--- C1 | | | `--- C2 | `--- B2 或者 C 直接掛載於 AA1 目錄之上: / | +--- A1 | | | +--- C1 | | | `--- C2 | `--- A2 | +--- B1 | `--- B2 如果您熟悉 &ms-dos; 的話,這和 join 指令很類似 (雖然不儘相同)。 一般情況下您不需要擔心這些東西。 除非您要安裝新的磁碟,不然通常在您安裝 FreeBSD 時建立好檔案系統並決定好要掛載在何處之後就不會再做任何更動了。 您完全可以使用單一的一個大的根檔案系統 (root file system) 而不建立其他的檔案系統。 這樣有好處也有有壞處。 使用多個檔案系統的好處 不同的檔案系統在掛上的時候可以有不同的 掛載參數。 舉例來說,為求謹慎您可以將根檔案系統設成唯讀, 以避免不小心刪除或修改掉重要的檔案。 將使用者可寫入的檔案系統 (例如 /home) 獨立出來也可以讓他們用 nosuid 的參數掛載,此選項可以讓在這個檔案系統中執行檔的 suid/guid bits 失效,也許可以讓系統更安全。 FreeBSD 會自動根據您檔案系統的使用方式來做最佳的檔案配置方式。 因此,一個有很多小檔案、 常常寫入的檔案系統跟只有幾個較大的檔案的檔案系統配置是不一樣的。 如果您只有單一一個大的檔案系統,這部分就沒用了。 FreeBSD 的檔案系統在停電的時候很穩固。 然而,在某些重要的時候停電仍然會對檔案系統結構造成損害。 分割成許多個檔案系統的話在系統在停電後比較能夠正常啟動, 以便您在需要的時候將備份資料回存回來。 使用單一檔案系統的好處 檔案系統的大小是固定的。 您當初安裝 FreeBSD 的時候應該會給定一個大小,可是後來您可能會想把空間加大。 如果沒有備份的話是很難達成的; 您必須將檔案系統重新建立為您需要的大小,然後將備份回存回來。 FreeBSD 的 &man.growfs.8; 指令可以突破此限制直接變更檔案系統的大小。 檔案系統包含在分割區裡面。 因為 &os; 承襲 &unix 架構,這邊講的分割區和一般提到的分割區 (例如 &ms-dos; 分割區) 不同。 每一個分割區由一個代號(字母)表示,從 ah。 每個分割區只能包含一個檔案系統。 因此除了說常見到用檔案系統同的掛載點來表示檔案系統外, 也可以用包含他的分割區代號來表示。 FreeBSD 也會拿磁碟空間來當 swap space。 Swap space 給 FreeBSD 當作虛擬記憶體用。 這讓您的電腦好像擁有比實際更多的記憶體。 當 FreeBSD 的記憶體用完的時候,它會把一些目前沒用到的資料移到 swap space,然後在用到的時候移回去 (同時移出部份沒用到的)。 某些分割區有慣例的使用方式如下: 分割區 慣例 a 通常包含根檔案系統 (root file system) b 通常是 swap space c 通常和整個 slice 的大小一樣,給一些會用到整個 slice 的工具程式 (例如硬碟壞軌檢查工具) 來使用。 一般來說您應該不會把檔案系統建立在這個分割區。 d 分割區 d 曾經有代表特殊意義,但是已經不再使用。 所以現在 d 就和其他一般的分割區相同了。 每個包含有檔案系統的分割區是存在所謂的 slice 裡面。 FreeBSD 的 slice 就是指平常我們稱為分割區 (partition) 的東西。 同樣地,會這樣子稱呼也是因為 FreeBSD 的 &unix; 色彩。 而 slice 是有編號的,從 1 號編到 4 號。 slices partitions dangerously dedicated slice 號碼跟在裝置名稱後面,先接一個字母 s,然後從 1 號開始編下去。 因此 da0s1 就是指第一個 SCSI 硬碟的第一個 slice。 一個磁碟上只能有四個實體的 slice,但是在實體的 slice 中您可以塞進適當類型的邏輯 slice。 這些延伸的 slice 編號從 5 開始,所以 ad0s5 是第一個 IDE 硬碟上的第一個延伸 slice。 檔案系統在裝置 (device) 裡就是在一個 slice 之中。 Slices、dangerously dedicated 模式的實體磁碟機,以及其他包含分割區(partition) 的磁碟都是以字母 ah 的編號來表示。 編號是接在裝置名稱的後面的,因此 da0a 是磁碟機 da 上的第一個 dangerously dedicated模式之分割區。 而 ad1s3e 則是第二顆 IDE 硬碟上第三個 slice 的第五個分割區。 最後,我們就可以把系統上的每個磁碟都區分出來了。 一個磁碟的名稱會有一個代碼來表示這個磁碟的類型,接著是一個數字, 表示這是哪一個磁碟。 這邊跟 slice 每個磁碟編號從 0 開始不一樣。 常見的代碼可以參考 當要參照一個分割區的時候,FreeBSD 會要您一併輸入包含這個分割區的 slice 及磁碟機名稱;當要參照一個 slice 的時候,也必須輸入包含這個 slice 的磁碟名稱。 怎麼做呢?首先先列出磁碟名稱,然後 s 加上 slice 編號,最後再輸入分割區字母代號。 範例可以參考 . 示範了一個基本的磁碟分布模式,相信對您有些幫助。 要安裝 FreeBSD,您必須先建置磁碟的 slice,接著於 slice 中建立要給 FreeBSD 用的分割區。 最後在這些分割區中建立檔案系統 (或 swap space) 並決定要將這些檔案系統掛載於哪裡。 磁碟機代號 代號 意義 ad ATAPI(IDE) 磁碟機 da SCSI 直接存取磁碟機 acd ATAPI(IDE) 光碟機 cd SCSI 光碟機 fd 軟碟機
磁碟、slice 及分割區命名範例 名稱 意義 ad0s1a 第一個 IDE 硬碟 (ad0) 上第一個 slice (s1)的第一個分割區(a) 。 da1s2e 第二個 SCSI 硬碟 (da1) 上第二個 slice (s2) 的第五個分割區 (e) 。 磁碟的概念模型 此圖顯示 FreeBSD 中接到系統的第一個 IDE 磁碟機內部配置圖。 假設這個磁碟的容量是 4 GB,並且包含了兩個 2 GB 的 slice (&ms-dos; 的分割區)。 第一個 slice 是 DOS 的 C: 磁碟機,第二個則安裝了 FreeBSD。 本範例的 FreeBSD 有三個分割區以及一個 swap 分割區。 這三個分割區每個都是一個檔案系統。 a 分割是根 (root) 檔案系統;分割 e/var;而 f 分割是 /usr 目錄結構。 .-----------------. --. | | | | DOS / Windows | | : : > First slice, ad0s1 : : | | | | :=================: ==: --. | | | Partition a, mounted as / | | | > referred to as ad0s2a | | | | | :-----------------: ==: | | | | Partition b, used as swap | | | > referred to as ad0s2b | | | | | :-----------------: ==: | Partition c, no | | | Partition e, used as /var > file system, all | | > referred to as ad0s2e | of FreeBSD slice, | | | | ad0s2c :-----------------: ==: | | | | | : : | Partition f, used as /usr | : : > referred to as ad0s2f | : : | | | | | | | | --' | `-----------------' --'
掛載與卸載檔案系統 檔案系統就像一顆樹。/ 就像是樹根,而 /dev/usr 以及其他在根目錄下的目錄就像是樹枝,而這些樹枝上面又還有分支,像是 /usr/local 等。 根檔案系統 因為某些原因,我們會將一些目錄分別放在不同的檔案系統上。 如 /var 包含了可能會滿出來的 log/spool/ 等目錄以及各式各樣的暫存檔。 把根檔案系統塞到滿出來顯然不是個好主意,所以我們往往會比較傾向把 /var/ 中拉出來。 另一個常見到把某些目錄放在不同檔案系統上的理由是: 這些檔案在不同的實體或虛擬磁碟機上。 像是網路檔案系統 (Network File System) 或是光碟機。 <filename>fstab</filename> 檔 檔案系統 file systems 由fstab掛載 mounted with fstab /etc/fstab 裡面有設定的檔案系統會在開機 的過程中自動地被掛載 (除非該檔案系統有被加上 參數)。 /etc/fstab 檔案內容的格式如下: device /mount-point fstype options dumpfreq passno device 裝置名稱 (該裝置必須真的存在)。 詳情請參閱 . mount-point 檔案系統要掛載到的目錄 (該目錄必須真的存在)。 fstype 檔案系統類型,這是要傳給 &man.mount.8; 的參數。 FreeBSD 預設的檔案系統是 ufs options 可讀可寫的檔案系統用 ,而唯讀的檔案系統則是用 ,後面視需要還可以加其他選項。 常見的選項如 是用在不要於開機過程中自動的掛載的檔案系統。 其他選項可參閱 &man.mount.8; 說明。 dumpfreq &man.dump.8; 由此項目決定那些檔案系統需要傾印。 如果這格空白則以零為預設值。 passno 這個項目決定檔案系統檢查的順序。 對於要跳過檢查的檔案系統,它們的 passno 值要設為零。 根檔案系統的 passno 值應設為一 (因為需要比所有其他的還要先檢查),而其他的檔案系統的 passno 值應該要設得比一大。 若有多個檔案系統具有相同的 passno 值,則 &man.fsck.8; 會試著平行地(如果可能的話)檢查這些檔案系統。 更多關於 /etc/fstab 檔案格式及選項的資訊請參閱 &man.fstab.5; 說明文件。 <command>mount</command> 指令 檔案系統 file systems 掛載 mounting &man.mount.8; 指令是拿來掛載檔案系統用的。 基本的操作指令格式如下: &prompt.root; mount device mountpoint 在 &man.mount.8; 裡面有提到一大堆的選項,不過最常用的就是這些: 掛載選項 /etc/fstab 裡面所有還沒有被掛載、沒有被標記成 noauto 而且沒有用 排除的檔案系統掛載起來。 執行所有的動作,但是不真的去呼叫掛載的 system call。 這個選項和 搭配拿來推測 &man.mount.8; 將要做什麼動作時很好用。 強迫掛載不乾淨的檔案系統 (危險),或是用來強制取消寫入權限 (把檔案系統的掛載狀態從可存取變成唯讀)。 用唯讀的方式掛載檔案系統。 這個選項和在 選項中指定 (在 &os; 5.2之前的版本是用 ) 參數是一樣的。 fstype 用指定的檔案系統型態 (fstype) 來掛載指定的檔案系統,或是在有 選項時只掛載指定型態的檔案系統。 預設的檔案系統是 ufs 更新檔案系統的掛載選項。 顯示較詳細資訊。 以可存取的模式掛載檔案系統。 選項後面會接著以逗號分隔的參數,例如: noexec 不允許在這個檔案系統上執行二進位程式碼, 這也是一個蠻有用的安全選項。 nosuid 不解析檔案系統上的 setuid 或 setgid 旗標, 這也是一個蠻有用的安全選項。 <command>umount</command> 指令 檔案系統 file systems 卸載 unmounting &man.umount.8; 指令的參數可以是掛載點 (mountpoint),裝置名稱,以及 或是 等選項。 加上 可以強制卸載,加上 則是會顯示詳細資訊。 要注意的是一般來說用 並不是個好主意,強制卸載檔案系統有可能會造成電腦當機, 或者損壞檔案系統內的資料。 是用來卸載所有已掛載的檔案系統,另外還可以用 來指定要卸載的是哪些種類的檔案系統。 要注意的是 並不會試圖卸載根檔案系統。 程序 FreeBSD 是一個多工的作業系統,也就是說在同一時間內可以跑超過一個程式。 每一個正在花時間跑的程式就叫做 程序 (process)。 您下的每個指令都至少會開啟一個新的程序, 而有些系統程序是一直在跑以維持系統正常運作的。 每一個程序都有一個不重覆的數字叫做 process ID ,或稱為 PID ,而且就像檔案一樣,每一個程序也有擁有者及群組。 擁有者及群組的資訊是用來決定什麼檔案或裝置是這個程序可以開啟的 (前面有提到過檔案權限)。 大部份的程序都有父程序。 父程序是開啟這個程序的程序,例如:您對 shell 輸入指令,shell 本身就是一個程序,而您執行的指令也是程序。 每一個您用這種方式跑的程序的父程序都是 shell。 有一個特別的程序叫做 &man.init.8; 是個例外。init 永遠是第一個程序,所以他的 PID 一直都會是 1。 在 FreeBSD 開機的時候 init 會自動地被 kernel 開啟。 要看系統執行中的程序,有兩個相當有用的指令可用: &man.ps.1; 以及 &man.top.1;。ps 指令是用來列出正在執行之程序,而且可以秀它們的 PID、用了多少記憶體、執行的指令名稱及其後之參數是什麼等等。 top 指令則是顯示所有正在執行的程序, 並且數秒鐘更新一次。因此您可以互動式的觀看您的電腦正在做什麼。 在預設的情況下,ps 指令只會顯示您所擁有的的程序。 例如: &prompt.user; ps PID TT STAT TIME COMMAND 298 p0 Ss 0:01.10 tcsh 7078 p0 S 2:40.88 xemacs mdoc.xsl (xemacs-21.1.14) 37393 p0 I 0:03.11 xemacs freebsd.dsl (xemacs-21.1.14) 48630 p0 S 2:50.89 /usr/local/lib/netscape-linux/navigator-linux-4.77.bi 48730 p0 IW 0:00.00 (dns helper) (navigator-linux-) 72210 p0 R+ 0:00.00 ps 390 p1 Is 0:01.14 tcsh 7059 p2 Is+ 1:36.18 /usr/local/bin/mutt -y 6688 p3 IWs 0:00.00 tcsh 10735 p4 IWs 0:00.00 tcsh 20256 p5 IWs 0:00.00 tcsh 262 v0 IWs 0:00.00 -tcsh (tcsh) 270 v0 IW+ 0:00.00 /bin/sh /usr/X11R6/bin/startx -- -bpp 16 280 v0 IW+ 0:00.00 xinit /home/nik/.xinitrc -- -bpp 16 284 v0 IW 0:00.00 /bin/sh /home/nik/.xinitrc 285 v0 S 0:38.45 /usr/X11R6/bin/sawfish 在這個範例裡可以看到 &man.ps.1; 的輸出分成好幾個欄位。 PID 就是前面有提到的 process ID。 PID 的分配是從 1 開始一直到 99999,如果用完的話又會繞回來重頭開始分配 (若該 PID 已經在用了,則 PID 不會重新分配)。 TT 欄位是指這個程式在哪個 tty 上執行,在這裡可以先忽略不管。STAT 是程式的狀態,也可以先不要管。TIME 是這個程式在 CPU 上執行的時間—這通常不是程式總共花的時間, 因為當您開始執行程式後,大部份的程式在 CPU 上執行前會先花上不少時間等待 。 最後,COMMAND 是執行這個程式的命令列。 &man.ps.1; 有幾個不同的選項組合可以用來變更顯示出來的資訊,其中一個最有用的組合是 auxww 可以顯示所有正在跑的程序的指令,不只是您自已的。 則是顯示程序的擁有者名稱以及記憶體使用情況。 可以把 daemon 程序顯示出來, 而 可讓 &man.ps.1; 顯示出每個程序完整的內容, 而不致因過長而被螢幕截掉了。 &man.top.1; 也有類似的輸出。 一般的情況看像是這樣: &prompt.user; top last pid: 72257; load averages: 0.13, 0.09, 0.03 up 0+13:38:33 22:39:10 47 processes: 1 running, 46 sleeping CPU states: 12.6% user, 0.0% nice, 7.8% system, 0.0% interrupt, 79.7% idle Mem: 36M Active, 5256K Inact, 13M Wired, 6312K Cache, 15M Buf, 408K Free Swap: 256M Total, 38M Used, 217M Free, 15% Inuse PID USERNAME PRI NICE SIZE RES STATE TIME WCPU CPU COMMAND 72257 nik 28 0 1960K 1044K RUN 0:00 14.86% 1.42% top 7078 nik 2 0 15280K 10960K select 2:54 0.88% 0.88% xemacs-21.1.14 281 nik 2 0 18636K 7112K select 5:36 0.73% 0.73% XF86_SVGA 296 nik 2 0 3240K 1644K select 0:12 0.05% 0.05% xterm 48630 nik 2 0 29816K 9148K select 3:18 0.00% 0.00% navigator-linu 175 root 2 0 924K 252K select 1:41 0.00% 0.00% syslogd 7059 nik 2 0 7260K 4644K poll 1:38 0.00% 0.00% mutt ... 輸出的資訊分成兩個部份。開頭 (前五行) 秀出最近一個程序的 PID、系統平均負載 (系統有多忙錄的測試)、系統的開機時間 (從上次重開算起) 以及現在的時間等。 在開頭裡面的其他數字分別是在講有多少程序正在執行 (在本例中為47)、有多少記憶體及 swap space 被占用了,還有就是系統分別花了多少時間在不同的 CPU 狀態上。 接下來的部份是由好幾個欄位所構成,和 &man.ps.1; 輸出的資訊類似。 就如同前例,您可以看到 PID、使用者名稱、CPU 花費的時間以及正在執行的指令。 &man.top.1; 在預設的情況下還會告訴您程序用掉了多少的記憶體空間。 在這邊會分成兩欄,一個是總用量 (total size),另一個是實際用量 (resident size)—總用量是指這個應用程式需要的記憶體空間, 而實際用量則是指實際上該程式的記憶體使用量。 在這個例子裡面您可以看到 &netscape; 要了幾乎到 30 MB 的 RAM,但是只有用到 9 MB。 &man.top.1; 每隔 2 秒鐘會自動更新顯示內容,可用 選項來改變間隔的時間。 Daemon、信號及終止程序 當在執行文書編輯器時,您可以很容易地使用它,叫它讀取檔案或是什麼的。 可以這樣做是因為編輯器有提供這些功能, 還有就是編輯器依附在一個終端機 (Terminal) 之上。 有些程式並不是設計成一直在接收使用者的輸入的, 所以它們在一開始執行的時候就從終端機斷開了。 例如說, 網頁伺服器整天都在回應網頁方面的要求,它通常不需要您輸入任何東西。 另外,像是把信從一個站傳送到另一個站的程式,也是這種類型的應用程式。 我們把這種程式稱作 daemon。 Daemon (惡魔、守護神) 是希臘神話中的角色:祂們不屬於善良陣營或邪惡陣營,是守護的小精靈。 大致上來說祂們就是在替人類做一些有用的事情, 跟今天的網頁伺服器或是郵件伺服器很像。 這也就是為何 BSD 的吉祥物,長期以來都是一隻穿著帆布鞋拿著三叉耙的快樂小惡魔的原因。 通常來說 deamon 程式的名字後面都會加一個字母 dBIND 是 Berkeley Internet Name Domain 的縮寫 (但實際上執行的程式名稱是 named)、Apache 網頁伺服器的程式名稱是 httpd、印表機服務程式是 lpd,依此類推。 這是習慣用法,並沒有硬性規定,例如 Sendmail 主要的寄信 daemon 是叫做 sendmail 而不是 maild,跟您想像的不一樣。 有些時候會需要跟某個 daemon 程序溝通, 這些溝通是透過所謂的信號(signal)來傳遞給該 daemon 程序(或是其他執行中的程序)。 藉由送出信號,您可以和一個 daemon (或是任何一個正在跑的程序) 溝通。 信號有很多種—有些有特定的意義,有些則是會由應用程式來解讀。 應用程式的說明文件會告訴您該程式是如何解讀信號的。 您只能送信號給您擁有的程序,送 &man.kill.1; 或 &man.kill.2; 的信號給別人的程序是不被允許的。 不過 root 不受此限制,他可以送信號給任何人的程序。 FreeBSD 本身在某些情況也會送信號給應用程式。 假設有個應用程式寫得很爛,然後企圖要存取它不該碰的記憶體的時候,FreeBSD 會送一個 Segmentation Violation 信號 (SIGSEGV) 給這個程序。 又如果有一個應用程式用了 &man.alarm.3; 的 system call 要求系統在過一段時間之後叫他一下,時間到了的時候鬧鐘的信號 (SIGALRM) 就會被送出了,其他的依此類推。 SIGTERM and SIGKILL 這兩個信號可以拿來終止程序。 用 SIGTERM 結束程序是比較有禮貌的方式,該程序會捕捉 (catch) 這個信號而了解到您想要把他關掉。 接著下來它會把它自已開的記錄檔通通關掉, 然後在關掉程序之前結束掉手邊的工作。 在某些情況下程序有可能會裝作沒看見 SIGTERM,假如它正在做一些不能中斷的工作的話。 SIGKILL 就沒有辦法被程序忽略了。 這是一個我管你正在幹嘛,現在就給我停下來的信號。 如果您送了 SIGKILL 信號給某個程序,FreeBSD 將會把它停掉 不完全正確—還是有少數東西不能被中斷。 例如有個程序正在從網路上的別的電腦讀一個檔案, 而那部電腦因為某些理由連不到 (機器被關掉,或是網路爛掉了), 那這個程序我們就說他是一個不能中斷的程序。 通常在經過兩分鐘左右之後這個程序會逾時。 當發生逾時的時候這個程序就會被結束掉了。 這些是其他您有可能會要用到的信號: SIGHUPSIGUSR1,以及 SIGUSR2。 這些是通用的信號,當送出時不同的應用程式會有不同的反應。 假設您更動了您的網頁伺服器的設定檔— 您想要叫網頁伺服器去重新讀取設定值。 您可以關閉後再重新啟動 httpd,但是這麼做會造成網頁伺服器暫停服務一段時間, 這樣子可能不太好。 大部份的 daemon 都寫成會去回應 SIGHUP。 當收到這個信號之後,它們會去重新讀取自已的設定檔。 因此您可以用送 SIGHUP 信號來取代關掉重開。 又因為沒有標準在規範如何回應這些信號,不同的 daemon 可能會有不同的行為,所以有疑問的話請先確認並翻閱 deamon 的說明文件。 信號是由 &man.kill.1; 指令送出的,如範例所示: 送信號給程序 這個範例將會示範如何送一個信號給 &man.inetd.8;。 inetd 的設定檔是 /etc/inetd.conf,而 inetd 會在收到 SIGHUP 的時候重新讀取這個設定檔。 找出您想要送信號的那個程序的 ID。 您會用到 &man.ps.1; 以及 &man.grep.1; 這兩個指令。 &man.grep.1; 是用來在輸出中搜尋, 找出您指定的字串。 這個指令是由一般使用者執行,而 &man.inetd.8; 是由 root 執行,所以在使用 &man.ps.1; 時需要加上 選項。 &prompt.user; ps -ax | grep inetd 198 ?? IWs 0:00.00 inetd -wW 因此可知 &man.inetd.8; 的 PID 為 198。 在某些情況下 grep inetd 這個指令本身也會出現在輸出裡。 這是因為 &man.ps.1; 乃是找所有執行中的程序的方式造成的。 用 &man.kill.1; 來送信號。 又因為 &man.inetd.8; 是由 root 執行的,您必須用 &man.su.1; 切換成 root先。 &prompt.user; su Password: &prompt.root; /bin/kill -s HUP 198 一般情況對大多數 &unix; 指令來講,當 &man.kill.1; 執行成功時並不會輸出任何訊息。 假設您送一個信號給某個不是您所擁有的程序, 那麼您就會吃到這個錯誤訊息: kill: PID: Operation not permitted。 而如果您打錯 PID 的話,那就會把信號送給錯誤的程序。 這樣可能會很糟, 不過如果您夠幸運的話,可能剛好就只是把信號送給一個非使用中的 PID,那您就只會看到 kill: PID: No such process 而已。 為什麼用 <command>/bin/kill</command>? 很多 shell 有提供內建的 kill 指令。 也就是說這種 shell 會直接送信號,而不是執行 /bin/kill。 這樣是蠻方便的沒錯啦,但是不同的 shell 會有不同的語法來指定信號的名稱等。 與其嘗試去把它們通通學會,不如就單純的直接用 /bin/kill ... 吧。 要送其他的信號的話也是非常類似,就視需要把指令中的 TERMKILL 替換掉即可。 隨便抓一個系統中的程序然後把他砍掉並不是個好主意。 特別是 &man.init.8;, process ID 1,一個非常特別的程序。 執行 /bin/kill -s KILL 1 的結果就是系統立刻關機。 因此在您按下 Return 要執行 &man.kill.1;之前, 請一定要記得再次確認您下的參數。 Shells shells - command line - - In FreeBSD, a lot of everyday work is done in a command line - interface called a shell. A shell's main job is to take commands - from the input channel and execute them. A lot of shells also have - built in functions to help everyday tasks such as file management, - file globbing, command line editing, command macros, and environment - variables. FreeBSD comes with a set of shells, such as - sh, the Bourne Shell, and tcsh, - the improved C-shell. Many other shells are available - from the FreeBSD Ports Collection, such as - zsh and bash. - - Which shell do you use? It is really a matter of taste. If you - are a C programmer you might feel more comfortable with a C-like shell - such as tcsh. If you have come from Linux or are new - to a &unix; command line interface you might try bash. - The point is that each - shell has unique properties that may or may not work with your - preferred working environment, and that you have a choice of what - shell to use. - - One common feature in a shell is filename completion. Given - the typing of the first few letters of a command or filename, you - can usually have the shell automatically complete the rest of the - command or filename by hitting the Tab key on the keyboard. Here is - an example. Suppose you have two files called - foobar and foo.bar. You - want to delete foo.bar. So what you would type - on the keyboard is: rm fo[Tab].[Tab]. - - The shell would print out rm - foo[BEEP].bar. - - The [BEEP] is the console bell, which is the shell telling me it - was unable to totally complete the filename because there is more - than one match. Both foobar and - foo.bar start with fo, but - it was able to complete to foo. If you type in - ., then hit Tab again, the shell would be able to - fill in the rest of the filename for you. + 命令列 command line + + 在 FreeBSD 中,很多日常的工作是在一個叫做 shell + 的文字介面中完成的。 + Shell 的主要工作就是從輸入中收到命令並執行它們。 + 許多 shell 也有內建一些有助於日常工作的指令, + 像是檔案管理、檔案比對、命令列編輯、指令巨集以及環境變數等。 + FreeBSD 有內附了幾個 shell,像是 sh, + Bourne Shell,以及 tcsh,改良版的 C-shell。 + 還有許多其他的 shell 可以從 FreeBSD Ports Collection + 中取得,像是 zsh 以及 bash + 等。 + + 您用哪個 shell 呢? 其實每個人的喜好都不一樣。 + 如果您是一個 C 程式設計師,那對於使用像是 tcsh + 這種 C-like 的 shell 可能會感到相當愉快。 如果你是從 Linux + 跳過來的,或者您是一個 &unix; 新手,那您也許會想要用 + bash 來當作文字介面。 + 每一個 shell 都有自已獨特之處,至於這些特點能不能配合您的工作環境? + 那就是您選擇 shell 的重點了。 + + 檔名自動補齊就是常見的 shell 功能。 + 首先輸入指令或檔案的前幾個字母,這時通常您只需要按下 Tab + 鍵,接下來 shell 就會自動把指令或是檔案名稱剩餘的部份補齊。 + 假設您有兩個檔案分別叫作 foobar 及 + foo.bar。 現在要刪掉 + foo.bar,那麼可以輸入: + rm fo[Tab].[Tab] + + + Shell 會印出這個: rm foo[嗶].bar + + [嗶] 是 console 的響鈴,這嗶的一聲是 shell + 在告訴我說它沒有辦法完全自動補齊檔名,因為有不只一個檔名符合條件。 + foobarfoo.bar 都是 + fo 開頭的檔名,不過它至少可以補齊到 foo。 + 如果您接著輸入 . 然後再按 Tab + 一次,那 shell 就能夠替您把剩下的檔名填滿了。 + environment variables - Another feature of the shell is the use of environment variables. - Environment variables are a variable/key pair stored in the shell's - environment space. This space can be read by any program invoked by - the shell, and thus contains a lot of program configuration. Here - is a list of common environment variables and what they mean: + Shell 的另一項特點是使用了環境變數。 + 環境變數是以變數與鍵值(variable/key)的對應關係儲存於 shell + 的環境空間中,任何由 shell 所產生的程序都可以讀取此空間, + 因此這個空間儲存了許多程序的設定組態。在此附上 + 一份常見環境變數與其含意的列表: environment variables - Variable - Description + 變數 + 詳細說明 USER - Current logged in user's name. + 目前登入的使用者名稱。 PATH - Colon-separated list of directories to search for - binaries. + 以冒號(:)隔開的目錄列表,用以搜尋執行檔的路徑。 DISPLAY - Network name of the X11 display to connect to, if - available. + 若存在這個環境變數,則代表 X11 連結顯示器的網路名稱。 SHELL - The current shell. + 目前使用的 shell。 TERM - The name of the user's type of terminal. Used to determine - the capabilities of the terminal. + 使用者終端機的名稱,能藉由此變數判斷終端機的能力。 TERMCAP Database entry of the terminal escape codes to perform various terminal functions. OSTYPE - Type of operating system. e.g., FreeBSD. + 作業系統的種類,如:FreeBSD。 MACHTYPE - The CPU architecture that the system is running - on. + 目前系統所用的 CPU 架構。 EDITOR - The user's preferred text editor. + 使用者偏好的文字編輯器。 PAGER - The user's preferred text pager. + 使用者偏好的文字分頁器(text pager)。 MANPATH - Colon-separated list of directories to search for - manual pages. + 以冒號(:)隔開的目錄列表,用以搜尋 manual pages 的路徑。 Bourne shells - Setting an environment variable differs somewhat from - shell to shell. For example, in the C-Style shells such as - tcsh and csh, you would use - setenv to set environment variables. - Under Bourne shells such as sh and - bash, you would use - export to set your current environment - variables. For example, to set or modify the - EDITOR environment variable, under csh or - tcsh a - command like this would set EDITOR to - /usr/local/bin/emacs: + 在不同的 shell 底下設定環境變數的方式也有所不同。 + 舉例來說,在 C-Style 的 shell 底下,像是 + tcshcsh,你必須使用 + setenv 來設定環境變數。 + 但在 Bourne shells 底下,像是 sh 和 + bash,你則必須使用 + export 來設定你所使用的環境變數。 + 再舉個例子來說,若要設定或是修改 + EDITOR 這個環境變數,在 csh 或 + tcsh 下設定 EDITOR 這個環境變數為 + /usr/local/bin/emacs 的指令是: &prompt.user; setenv EDITOR /usr/local/bin/emacs - Under Bourne shells: + 在 Bourne shells 下則是: &prompt.user; export EDITOR="/usr/local/bin/emacs" - You can also make most shells expand the environment variable by - placing a $ character in front of it on the - command line. For example, echo $TERM would - print out whatever $TERM is set to, because the shell - expands $TERM and passes it on to echo. + 大多數的 shell 都支援使用者在命令列中將 + $ 字元放在變數之前,以取得環境變數的值。 + 舉例來說,echo $TERM 會 + 顯示出 $TERM 的設定值,這是因為 shell 取得了 + $TERM 的設定值,並將他傳給 echo 顯示出來。 Shells treat a lot of special characters, called meta-characters as special representations of data. The most common one is the * character, which represents any number of characters in a filename. These special meta-characters can be used to do filename globbing. For example, typing in echo * is almost the same as typing in ls because the shell takes all the files that match * and puts them on the command line for echo to see. To prevent the shell from interpreting these special characters, they can be escaped from the shell by putting a backslash (\) character in front of them. echo $TERM prints whatever your terminal is set to. echo \$TERM prints $TERM as is. - Changing Your Shell - - The easiest way to change your shell is to use the - chsh command. Running chsh will - place you into the editor that is in your EDITOR - environment variable; if it is not set, you will be placed in - vi. Change the Shell: line - accordingly. - - You can also give chsh the - option; this will set your shell for you, - without requiring you to enter an editor. - For example, if you wanted to - change your shell to bash, the following should do the - trick: - + 變更你的 Shell + + 變更 shell 最簡單的方法就是透過 chsh 命令。 + 執行 chsh 將會呼叫環境變數中 EDITOR 指定的 + 文字編輯器。如果沒有設定,則預設是 vi。依照需求去修改 + Shell: 的值。 + + 你也可以透過 chsh 的參數 ,這可以 + 直接設定你的 shell 而不需要透過任何文字編輯器。例如,假設你想將 shell 變更為 + bash,可以透過下列的方式: + &prompt.user; chsh -s /usr/local/bin/bash The shell that you wish to use must be present in the /etc/shells file. If you have installed a shell from the ports collection, then this should have been done for you already. If you installed the shell by hand, you must do this. For example, if you installed bash by hand and placed it into /usr/local/bin, you would want to: &prompt.root; echo "/usr/local/bin/bash" >> /etc/shells Then rerun chsh. 文字編輯器 text editors editors A lot of configuration in FreeBSD is done by editing text files. Because of this, it would be a good idea to become familiar with a text editor. FreeBSD comes with a few as part of the base system, and many more are available in the Ports Collection. ee editors ee The easiest and simplest editor to learn is an editor called ee, which stands for easy editor. To start ee, one would type at the command line ee filename where filename is the name of the file to be edited. For example, to edit /etc/rc.conf, type in ee /etc/rc.conf. Once inside of ee, all of the commands for manipulating the editor's functions are listed at the top of the display. The caret ^ character represents the Ctrl key on the keyboard, so ^e expands to the key combination Ctrle. To leave ee, hit the Esc key, then choose leave editor. The editor will prompt you to save any changes if the file has been modified. vi editors vi emacs editors emacs FreeBSD also comes with more powerful text editors such as vi as part of the base system, while other editors, like Emacs and vim, are part of the FreeBSD Ports Collection (editors/emacs and editors/vim). These editors offer much more functionality and power at the expense of being a little more complicated to learn. However if you plan on doing a lot of text editing, learning a more powerful editor such as vim or Emacs will save you much more time in the long run. Devices and Device Nodes A device is a term used mostly for hardware-related activities in a system, including disks, printers, graphics cards, and keyboards. When FreeBSD boots, the majority of what FreeBSD displays are devices being detected. You can look through the boot messages again by viewing /var/run/dmesg.boot. For example, acd0 is the first IDE CDROM drive, while kbd0 represents the keyboard. Most of these devices in a &unix; operating system must be accessed through special files called device nodes, which are located in the /dev directory. Creating Device Nodes When adding a new device to your system, or compiling in support for additional devices, new device nodes must be created. <literal>DEVFS</literal> (DEVice File System) The device file system, or DEVFS, provides access to kernel's device namespace in the global file system namespace. Instead of having to create and modify device nodes, DEVFS maintains this particular file system for you. See the &man.devfs.5; manual page for more information. Binary Formats To understand why &os; uses the &man.elf.5; format, you must first know a little about the three currently dominant executable formats for &unix;: &man.a.out.5; The oldest and classic &unix; object format. It uses a short and compact header with a magic number at the beginning that is often used to characterize the format (see &man.a.out.5; for more details). It contains three loaded segments: .text, .data, and .bss plus a symbol table and a string table. COFF The SVR3 object format. The header now comprises a section table, so you can have more than just .text, .data, and .bss sections. &man.elf.5; The successor to COFF, featuring multiple sections and 32-bit or 64-bit possible values. One major drawback: ELF was also designed with the assumption that there would be only one ABI per system architecture. That assumption is actually quite incorrect, and not even in the commercial SYSV world (which has at least three ABIs: SVR4, Solaris, SCO) does it hold true. FreeBSD tries to work around this problem somewhat by providing a utility for branding a known ELF executable with information about the ABI it is compliant with. See the manual page for &man.brandelf.1; for more information. FreeBSD comes from the classic camp and used the &man.a.out.5; format, a technology tried and proven through many generations of BSD releases, until the beginning of the 3.X branch. Though it was possible to build and run native ELF binaries (and kernels) on a FreeBSD system for some time before that, FreeBSD initially resisted the push to switch to ELF as the default format. Why? Well, when the Linux camp made their painful transition to ELF, it was not so much to flee the a.out executable format as it was their inflexible jump-table based shared library mechanism, which made the construction of shared libraries very difficult for vendors and developers alike. Since the ELF tools available offered a solution to the shared library problem and were generally seen as the way forward anyway, the migration cost was accepted as necessary and the transition made. FreeBSD's shared library mechanism is based more closely on Sun's &sunos; style shared library mechanism and, as such, is very easy to use. So, why are there so many different formats? Back in the dim, dark past, there was simple hardware. This simple hardware supported a simple, small system. a.out was completely adequate for the job of representing binaries on this simple system (a PDP-11). As people ported &unix; from this simple system, they retained the a.out format because it was sufficient for the early ports of &unix; to architectures like the Motorola 68k, VAXen, etc. Then some bright hardware engineer decided that if he could force software to do some sleazy tricks, then he would be able to shave a few gates off the design and allow his CPU core to run faster. While it was made to work with this new kind of hardware (known these days as RISC), a.out was ill-suited for this hardware, so many formats were developed to get to a better performance from this hardware than the limited, simple a.out format could offer. Things like COFF, ECOFF, and a few obscure others were invented and their limitations explored before things seemed to settle on ELF. In addition, program sizes were getting huge and disks (and physical memory) were still relatively small so the concept of a shared library was born. The VM system also became more sophisticated. While each one of these advancements was done using the a.out format, its usefulness was stretched more and more with each new feature. In addition, people wanted to dynamically load things at run time, or to junk parts of their program after the init code had run to save in core memory and swap space. Languages became more sophisticated and people wanted code called before main automatically. Lots of hacks were done to the a.out format to allow all of these things to happen, and they basically worked for a time. In time, a.out was not up to handling all these problems without an ever increasing overhead in code and complexity. While ELF solved many of these problems, it would be painful to switch from the system that basically worked. So ELF had to wait until it was more painful to remain with a.out than it was to migrate to ELF. However, as time passed, the build tools that FreeBSD derived their build tools from (the assembler and loader especially) evolved in two parallel trees. The FreeBSD tree added shared libraries and fixed some bugs. The GNU folks that originally wrote these programs rewrote them and added simpler support for building cross compilers, plugging in different formats at will, and so on. Since many people wanted to build cross compilers targeting FreeBSD, they were out of luck since the older sources that FreeBSD had for as and ld were not up to the task. The new GNU tools chain (binutils) does support cross compiling, ELF, shared libraries, C++ extensions, etc. In addition, many vendors are releasing ELF binaries, and it is a good thing for FreeBSD to run them. ELF is more expressive than a.out and allows more extensibility in the base system. The ELF tools are better maintained, and offer cross compilation support, which is important to many people. ELF may be a little slower than a.out, but trying to measure it can be difficult. There are also numerous details that are different between the two in how they map pages, handle init code, etc. None of these are very important, but they are differences. In time support for a.out will be moved out of the GENERIC kernel, and eventually removed from the kernel once the need to run legacy a.out programs is past. 更多資訊 Manual Pages manual pages The most comprehensive documentation on FreeBSD is in the form of manual pages. Nearly every program on the system comes with a short reference manual explaining the basic operation and various arguments. These manuals can be viewed with the man command. Use of the man command is simple: &prompt.user; man command command is the name of the command you wish to learn about. For example, to learn more about ls command type: &prompt.user; man ls The online manual is divided up into numbered sections: User commands. System calls and error numbers. Functions in the C libraries. Device drivers. File formats. Games and other diversions. Miscellaneous information. System maintenance and operation commands. Kernel developers. In some cases, the same topic may appear in more than one section of the online manual. For example, there is a chmod user command and a chmod() system call. In this case, you can tell the man command which one you want by specifying the section: &prompt.user; man 1 chmod This will display the manual page for the user command chmod. References to a particular section of the online manual are traditionally placed in parenthesis in written documentation, so &man.chmod.1; refers to the chmod user command and &man.chmod.2; refers to the system call. This is fine if you know the name of the command and simply wish to know how to use it, but what if you cannot recall the command name? You can use man to search for keywords in the command descriptions by using the switch: &prompt.user; man -k mail With this command you will be presented with a list of commands that have the keyword mail in their descriptions. This is actually functionally equivalent to using the apropos command. So, you are looking at all those fancy commands in /usr/bin but do not have the faintest idea what most of them actually do? Simply do: &prompt.user; cd /usr/bin &prompt.user; man -f * or &prompt.user; cd /usr/bin &prompt.user; whatis * which does the same thing. GNU Info Files Free Software Foundation FreeBSD includes many applications and utilities produced by the Free Software Foundation (FSF). In addition to manual pages, these programs come with more extensive hypertext documents called info files which can be viewed with the info command or, if you installed emacs, the info mode of emacs. To use the &man.info.1; command, simply type: &prompt.user; info For a brief introduction, type h. For a quick command reference, type ?.
diff --git a/zh_TW.Big5/books/handbook/config/chapter.sgml b/zh_TW.Big5/books/handbook/config/chapter.sgml index 1a4597903c..4d488ad549 100644 --- a/zh_TW.Big5/books/handbook/config/chapter.sgml +++ b/zh_TW.Big5/books/handbook/config/chapter.sgml @@ -1,3051 +1,3171 @@ Chern Lee Written by Mike Smith Based on a tutorial written by Matt Dillon Also based on tuning(7) written by 設定與效能調校(Tuning) 概述 system configuration system optimization 在 &os; 使用過程中,相當重要的環節之一就是系統設定部分。 正確的系統設定,可以讓你減輕日後升級的頭痛壓力。 本章著重於介紹 &os; 的相關重要設定上,包括一些可以調整 &os; 效能的參數設定。 讀完這章,您將了解: 如何有效運用檔案系統以及 swap 分割區。 rc.conf 的設定與 /usr/local/etc/rc.d 的啟動架構。 如何設定、測試網路卡。 如何設定 virtual hosts。 如何設定 /etc 內的各種設定檔。 如何以 sysctl 來調整 &os; 的系統效能。 如何調整硬碟效能,以及更改 kernel 限制。 在開始閱讀這章之前,您需要︰ 瞭解 &unix; 及 &os; 相關基本概念()。 要有設定、編譯 kernel 的基礎概念()。 一開始的規劃 規劃分割區(Partition) partition layout /etc /var /usr Base Partitions 用 &man.bsdlabel.8; 或 &man.sysinstall.8; 來規劃檔案系統時,請記住: 硬碟在傳輸資料方面,(由於結構為碟片因素)外圈會比內圈來得快些。 因此,建議把較小、常會存取的分割區儘量放外圈,而較大的分割區像是 /usr 則應放在較內圈。 建議建立分割區的順序,以像是:root, swap, /var, /usr 這樣順序來建立會較妥。 /var 的大小要視機器的用途而定。 /var 是用來放 信箱、log 紀錄檔以及印表機佇列(spools)。 信箱以及記錄檔的成長幅度可能無法預估, 因為這些成長幅度乃是取決於多少用戶、要放多久等管理原則而定。 通常這些使用者並沒有用到 1 GB 以上,但請切記:至少要保留一定空間給 /var/tmp 以便存放 packages。 /usr 分割區主要是用來放系統運作時所需的檔案、工具程式等,例如: &man.ports.7; collection(建議安裝)跟 source tree(optional)。 在安裝 FreeBSD 時,這兩者都是可選擇裝與不裝的。 不過,這個分割區建議至少要有 2 GB 空間以上才夠用。 規劃分割區大小時,記得多保留些成長空間。 否則若某個分割區滿了,但另一個分割區卻還剩很多空間,就會相當困窘。 有些人可能會發現 &man.sysinstall.8; 的 Auto-defaults(自動預設值) 所做的分割區大小, 有時候會把 /var 以及 / 分割區設太小了。 我們建議是:請依使用情況以及需求,來手動調整相關分割區大小。 Swap 分割區 swap sizing swap partition 根據經驗法則,通常 swap 分割區應該設為系統記憶體(RAM)大小的兩倍即可。 舉例來說:若機器有 128 MB RAM 的話,那麼 - swap 則應該設為 256 MB。 Systems with - less memory may perform better with more swap. - Less than 256 megabytes of swap is not recommended and - memory expansion should be considered. - The kernel's VM paging algorithms are tuned to - perform best when the swap partition is at least two times the - size of main memory. Configuring too little swap can lead to - inefficiencies in the VM page scanning code and might create - issues later if more memory is added. - - On larger systems with multiple SCSI disks (or - multiple IDE disks operating on different controllers), it is - recommend that a swap is configured on each drive (up - to four drives). The swap partitions should be - approximately the same size. The kernel can handle arbitrary - sizes but internal data structures scale to 4 times the - largest swap partition. Keeping the swap partitions near the - same size will allow the kernel to optimally stripe swap space - across disks. - Large swap sizes are fine, even if swap is not - used much. It might be easier to recover - from a runaway program before being forced to reboot. + swap 則應該設為 256 MB。 記憶體較少的機器,可以透過增加更多 swap 空間來提昇效能。 + 我們建議 swap 空間不要設低於 256 MB,而且該考慮增加記憶體才是良策。 + 當 swap 最少為記憶體的兩倍大時,kernel 的 VM paging 演算法會把效能調整到最佳狀態。 + 但若是機器記憶體很大,但 swap 卻劃分太少的話,會導致 VM page 掃瞄的效率過低, + 此外日後若增加更多記憶體時,也會導致一些異常狀況發生。 + + 在較大型的機器內,通常會有多顆 SCSI 磁碟(或多顆 IDE 磁碟接在不同 IDE 匯流排上), + 建議在每顆磁碟上都建立 swap(最多到四顆)。 + 而這些 swap 應該都大約一樣大小, + Kernel 可接受任意大小的 swap,但內部資料結構則是最大塊 swap 的 4 倍。 + 若有保持 swap 為同樣大小的話,則可讓 kernel 最佳化運用各磁碟之中的 swap 空間。 + 即使不太常會用到,分配大的 swap 也都還可接受, + 因為它可在強制重開機之前讓你更容易從當掉的程式中恢復正常。 為何要規劃 Partition? - Several users think a single large partition will be fine, - but there are several reasons why this is a bad idea. - First, each partition has different operational - characteristics and separating them allows the file system to - tune accordingly. For example, the root - and /usr partitions are read-mostly, without - much writing. While a lot of reading and writing could - occur in /var and - /var/tmp. + 有些人覺得把硬碟就直接劃分一個大分割區就好了, + 但是事實上有些原因會證明為何這是個爛點子, + 首先,每個分割區都有不同的運作特性,把它們分開的話可以讓檔案系統來調整。 + 比如: / 以及 /usr 分割區大多只是讀取而已, + 比較少在寫入。 而讀寫都很頻繁的則是 /var 及 + /var/tmp By properly partitioning a system, fragmentation introduced in the smaller write heavy partitions will not bleed over into the mostly-read partitions. Keeping the write-loaded partitions closer to the disk's edge, will increase I/O performance in the partitions where it occurs the most. Now while I/O performance in the larger partitions may be needed, shifting them more toward the edge of the disk will not lead to a significant performance improvement over moving /var to the edge. Finally, there are safety concerns. A smaller, neater root partition which is mostly read-only has a greater chance of surviving a bad crash. 最主要的設定檔 rc files rc.conf The principal location for system configuration information is within /etc/rc.conf. This file contains a wide range of configuration information, principally used at system startup to configure the system. Its name directly implies this; it is configuration information for the rc* files. An administrator should make entries in the rc.conf file to override the default settings from /etc/defaults/rc.conf. The defaults file should not be copied verbatim to /etc - it contains default values, not examples. All system-specific changes should be made in the rc.conf file itself. A number of strategies may be applied in clustered applications to separate site-wide configuration from system-specific configuration in order to keep administration overhead down. The recommended approach is to place site-wide configuration into another file, such as /etc/rc.conf.site, and then include this file into /etc/rc.conf, which will contain only system-specific information. As rc.conf is read by &man.sh.1; it is trivial to achieve this. For example: rc.conf: . /etc/rc.conf.site hostname="node15.example.com" network_interfaces="fxp0 lo0" ifconfig_fxp0="inet 10.1.1.1" rc.conf.site: defaultrouter="10.1.1.254" saver="daemon" blanktime="100" The rc.conf.site file can then be distributed to every system using rsync or a similar program, while the rc.conf file remains unique. Upgrading the system using &man.sysinstall.8; or make world will not overwrite the rc.conf file, so system configuration information will not be lost. 各式應用程式的設定檔 - Typically, installed applications have their own - configuration files, with their own syntax, etc. It is - important that these files be kept separate from the base - system, so that they may be easily located and managed by the - package management tools. + 原則上,安裝的軟體都會有其自有的設定檔,也會有自己的格式及語法。 + 因此,將其與系統分開獨立是件非常重要的事情。如此一來,套件管理工具將可以 + 很輕易的找出這些設定檔並管理這些設定檔。 /usr/local/etc - Typically, these files are installed in - /usr/local/etc. In the case where an - application has a large number of configuration files, a - subdirectory will be created to hold them. + 原則上,設定檔會被放置在 /usr/local/etc。 + 若某軟體的設定檔為數眾多,那將會其下建立一個目錄以供放置 - Normally, when a port or package is installed, sample - configuration files are also installed. These are usually - identified with a .default suffix. If there - are no existing - configuration files for the application, they will be created by - copying the .default files. + 通常,當一個 port 或 package 被安裝的同時,一些基本的設定範例 + 也會一併被安裝至此。這些範例通常會被用 .default 做為副檔名。 + 若安裝時沒有自行撰寫的軟體設定檔,那麼將會複製一份 .default 設定 + 做為預設設定檔 - For example, consider the contents of the directory - /usr/local/etc/apache: + 舉個例子,我們來看看 /usr/local/etc/apache -rw-r--r-- 1 root wheel 2184 May 20 1998 access.conf -rw-r--r-- 1 root wheel 2184 May 20 1998 access.conf.default -rw-r--r-- 1 root wheel 9555 May 20 1998 httpd.conf -rw-r--r-- 1 root wheel 9555 May 20 1998 httpd.conf.default -rw-r--r-- 1 root wheel 12205 May 20 1998 magic -rw-r--r-- 1 root wheel 12205 May 20 1998 magic.default -rw-r--r-- 1 root wheel 2700 May 20 1998 mime.types -rw-r--r-- 1 root wheel 2700 May 20 1998 mime.types.default -rw-r--r-- 1 root wheel 7980 May 20 1998 srm.conf -rw-r--r-- 1 root wheel 7933 May 20 1998 srm.conf.default - The file sizes show that only the srm.conf - file has been changed. A later update of the Apache port would not - overwrite this changed file. + srm.conf 的檔案被修改過了,爾後 Apache 的更新 + 將不會對這個已修改過的設定檔做任何變動。 Tom Rhodes Contributed by 各種 Services 的啟動方式 services Many users choose to install third party software on &os; from the Ports Collection. In many of these situations it may be necessary to configure the software in a manner which will allow it to be started upon system initialization. Services, such as mail/postfix or www/apache13 are just two of the many software packages which may be started during system initialization. This section explains the procedures available for starting third party software. In &os;, most included services, such as &man.cron.8;, are started through the system start up scripts. These scripts may differ depending on &os; or vendor version; however, the most important aspect to consider is that their start up configuration can be handled through simple startup scripts. Before the advent of rc.d, applications would drop a simple start up script into the /usr/local/etc/rc.d directory which would be read by the system initialization scripts. These scripts would then be executed during the latter stages of system start up. While many individuals have spent hours trying to merge the old configuration style into the new system, the fact remains that some third party utilities still require a script simply dropped into the aforementioned directory. The subtle differences in the scripts depend whether or not rc.d is being used. Prior to &os; 5.1 the old configuration style is used and in almost all cases a new style script would do just fine. While every script must meet some minimal requirements, most of the time these requirements are &os; version agnostic. Each script must have a .sh extension appended to the end and every script must be executable by the system. The latter may be achieved by using the chmod command and setting the unique permissions of 755. There should also be, at minimal, an option to start the application and an option to stop the application. The simplest start up script would probably look a little bit like this one: #!/bin/sh echo -n ' utility' case "$1" in start) /usr/local/bin/utility ;; stop) kill -9 `cat /var/run/utility.pid` ;; *) echo "Usage: `basename $0` {start|stop}" >&2 exit 64 ;; esac exit 0 This script provides for a stop and start option for the application hereto referred simply as utility. Could be started manually with: &prompt.root; /usr/local/etc/rc.d/utility.sh start While not all third party software requires the line in rc.conf, almost every day a new port will be modified to accept this configuration. Check the final output of the installation for more information on a specific application. Some third party software will provide start up scripts which permit the application to be used with rc.d; although, this will be discussed in the next section. Extended Application Configuration Now that &os; includes rc.d, configuration of application startup has become easier, and more featureful. Using the key words discussed in the rc.d section, applications may now be set to start after certain other services for example DNS; may permit extra flags to be passed through rc.conf in place of hard coded flags in the start up script, etc. A basic script may look similar to the following: #!/bin/sh # # PROVIDE: utility # REQUIRE: DAEMON # KEYWORD: shutdown # # DO NOT CHANGE THESE DEFAULT VALUES HERE # SET THEM IN THE /etc/rc.conf FILE # utility_enable=${utility_enable-"NO"} utility_flags=${utility_flags-""} utility_pidfile=${utility_pidfile-"/var/run/utility.pid"} . /etc/rc.subr name="utility" rcvar=`set_rcvar` command="/usr/local/sbin/utility" load_rc_config $name pidfile="${utility_pidfile}" start_cmd="echo \"Starting ${name}.\"; /usr/bin/nice -5 ${command} ${utility_flags} ${command_args}" run_rc_command "$1" This script will ensure that the provided utility will be started after the daemon service. It also provides a method for setting and tracking the PID, or process ID file. This application could then have the following line placed in /etc/rc.conf: utility_enable="YES" This new method also allows for easier manipulation of the command line arguments, inclusion of the default functions provided in /etc/rc.subr, compatibility with the &man.rcorder.8; utility and provides for easier configuration via the rc.conf file. 以 Services 來啟動各式 Services Other services, such as POP3 server daemons, IMAP, etc. could be started using the &man.inetd.8;. This involves installing the service utility from the Ports Collection with a configuration line appended to the /etc/inetd.conf file, or uncommenting one of the current configuration lines. Working with inetd and its configuration is described in depth in the inetd section. In some cases, it may be more plausible to use the &man.cron.8; daemon to start system services. This approach has a number of advantages because cron runs these processes as the crontab's file owner. This allows regular users to start and maintain some applications. The cron utility provides a unique feature, @reboot, which may be used in place of the time specification. This will cause the job to be run when &man.cron.8; is started, normally during system initialization. Tom Rhodes Contributed by 設定 <command>cron</command> cron configuration &os; 最好用的工具之一就是 &man.cron.8;。 cron 會在背景下運作,並不斷檢查 /etc/crontab 檔以及 /var/cron/tabs 目錄,來搜尋是否有新 crontab 檔案。 這些 crontab 檔會存放一些排程工作的設定,來給 cron 執行。 cron 程式,可同時採用兩種不同類型的設定檔:系統本身的 crontab 及使用者本身的 crontab。而兩種格式唯一差別在於第六欄的不同;In the system crontab, the sixth field is the name of a user for the command to run as. This gives the system crontab the ability to run commands as any user. In a user crontab, the sixth field is the command to run, and all commands run as the user who created the crontab; this is an important security feature. User crontabs allow individual users to schedule tasks without the need for root privileges. Commands in a user's crontab run with the permissions of the user who owns the crontab. The root user can have a user crontab just like any other user. This one is different from /etc/crontab (the system crontab). Because of the system crontab, there is usually no need to create a user crontab for root. Let us take a look at the /etc/crontab file (the system crontab): # /etc/crontab - root's crontab for &os; # # $&os;: src/etc/crontab,v 1.32 2002/11/22 16:13:39 tom Exp $ # # SHELL=/bin/sh PATH=/etc:/bin:/sbin:/usr/bin:/usr/sbin HOME=/var/log # # #minute hour mday month wday who command # # */5 * * * * root /usr/libexec/atrun Like most &os; configuration files, the # character represents a comment. A comment can be placed in the file as a reminder of what and why a desired action is performed. Comments cannot be on the same line as a command or else they will be interpreted as part of the command; they must be on a new line. Blank lines are ignored. First, the environment must be defined. The equals (=) character is used to define any environment settings, as with this example where it is used for the SHELL, PATH, and HOME options. If the shell line is omitted, cron will use the default, which is sh. If the PATH variable is omitted, no default will be used and file locations will need to be absolute. If HOME is omitted, cron will use the invoking users home directory. This line defines a total of seven fields. Listed here are the values minute, hour, mday, month, wday, who, and command. These are almost all self explanatory. minute is the time in minutes the command will be run. hour is similar to the minute option, just in hours. mday stands for day of the month. month is similar to hour and minute, as it designates the month. The wday option stands for day of the week. All these fields must be numeric values, and follow the twenty-four hour clock. The who field is special, and only exists in the /etc/crontab file. This field specifies which user the command should be run as. When a user installs his or her crontab file, they will not have this option. Finally, the command option is listed. This is the last field, so naturally it should designate the command to be executed. This last line will define the values discussed above. Notice here we have a */5 listing, followed by several more * characters. These * characters mean first-last, and can be interpreted as every time. So, judging by this line, it is apparent that the atrun command is to be invoked by root every five minutes regardless of what day or month it is. For more information on the atrun command, see the &man.atrun.8; manual page. Commands can have any number of flags passed to them; however, commands which extend to multiple lines need to be broken with the backslash \ continuation character. This is the basic set up for every crontab file, although there is one thing different about this one. Field number six, where we specified the username, only exists in the system /etc/crontab file. This field should be omitted for individual user crontab files. 工作排程(Crontab)的排定與管理 You must not use the procedure described here to edit/install the system crontab. Simply use your favorite editor: the cron utility will notice that the file has changed and immediately begin using the updated version. See this FAQ entry for more information. To install a freshly written user crontab, first use your favorite editor to create a file in the proper format, and then use the crontab utility. The most common usage is: &prompt.user; crontab crontab-file In this example, crontab-file is the filename of a crontab that was previously created. There is also an option to list installed crontab files: just pass the option to crontab and look over the output. For users who wish to begin their own crontab file from scratch, without the use of a template, the crontab -e option is available. This will invoke the selected editor with an empty file. When the file is saved, it will be automatically installed by the crontab command. If you later want to remove your user crontab completely, use crontab with the option. Tom Rhodes Contributed by - 在 &os; 5.X (含之後) 使用 rc + 在 &os; 使用 rc 從 2002 年起,&os; 整合了 NetBSD 的 rc.d 機制來作為系統服務啟動機制。 可以到 /etc/rc.d 目錄下去看,很多檔案都是基本服務,可以用 , 作為使用時的選項。 舉個例子,可以用下列指令來重新啟動 &man.sshd.8;: &prompt.root; /etc/rc.d/sshd restart 其他服務也是類似作法。當然, 服務通常只要在 &man.rc.conf.5; 內有指定的話,都會在開機時就自動啟動。舉例來說,若要開機時啟動 NAT(Network Address Translation) daemon 的話,只要在 /etc/rc.conf 內加上下列這行即可: natd_enable="YES" 若原本寫的是 那麼只要把 改為 就好了。rc scripts 會在下次重開機時,自動載入相關(有相依)的服務,以下我們會講到這部分。 Since the rc.d system is primarily intended to start/stop services at system startup/shutdown time, the standard , and options will only perform their action if the appropriate /etc/rc.conf variables are set. For instance the above sshd restart command will only work if sshd_enable is set to in /etc/rc.conf. To , or a service regardless of the settings in /etc/rc.conf, the commands should be prefixed with force. For instance to restart sshd regardless of the current /etc/rc.conf setting, execute the following command: &prompt.root; /etc/rc.d/sshd forcerestart It is easy to check if a service is enabled in /etc/rc.conf by running the appropriate rc.d script with the option . Thus, an administrator can check that sshd is in fact enabled in /etc/rc.conf by running: &prompt.root; /etc/rc.d/sshd rcvar # sshd $sshd_enable=YES The second line (# sshd) is the output from the sshd command, not a root console. 若要檢查服務是否有在運作,可以用 選項來查詢。比如:若要確認 sshd 是否真的有啟動的話,那麼打: &prompt.root; /etc/rc.d/sshd status sshd is running as pid 433. In some cases it is also possible to a service. This will attempt to send a signal to an individual service, forcing the service to reload its configuration files. In most cases this means sending the service a SIGHUP signal. Support for this feature is not included for every service. The rc.d system is not only used for network services, it also contributes to most of the system initialization. For instance, consider the bgfsck file. When this script is executed, it will print out the following message: Starting background file system checks in 60 seconds. Therefore this file is used for background file system checks, which are done only during system initialization. Many system services depend on other services to function properly. For example, NIS and other RPC-based services may fail to start until after the rpcbind (portmapper) service has started. To resolve this issue, information about dependencies and other meta-data is included in the comments at the top of each startup script. The &man.rcorder.8; program is then used to parse these comments during system initialization to determine the order in which system services should be invoked to satisfy the dependencies. The following words may be included at the top of each startup file: PROVIDE: Specifies the services this file provides. REQUIRE: Lists services which are required for this service. This file will run after the specified services. BEFORE: Lists services which depend on this service. This file will run before the specified services. By using this method, an administrator can easily control system services without the hassle of runlevels like some other &unix; operating systems. Additional information about the rc.d system can be found in the &man.rc.8; and &man.rc.subr.8; manual pages. Marc Fonvieille Contributed by 設定網路卡 network cards configuration Nowadays we can not think about a computer without thinking about a network connection. Adding and configuring a network card is a common task for any &os; administrator. 選擇正確、可用的驅動程式(Driver) network cards driver Before you begin, you should know the model of the card you have, the chip it uses, and whether it is a PCI or ISA card. &os; supports a wide variety of both PCI and ISA cards. Check the Hardware Compatibility List for your release to see if your card is supported. Once you are sure your card is supported, you need to determine the proper driver for the card. /usr/src/sys/conf/NOTES and /usr/src/sys/arch/conf/NOTES will give you the list of network interface drivers with some information about the supported chipsets/cards. If you have doubts about which driver is the correct one, read the manual page of the driver. The manual page will give you more information about the supported hardware and even the possible problems that could occur. If you own a common card, most of the time you will not have to look very hard for a driver. Drivers for common network cards are present in the GENERIC kernel, so your card should show up during boot, like so: dc0: <82c169 PNIC 10/100BaseTX> port 0xa000-0xa0ff mem 0xd3800000-0xd38 000ff irq 15 at device 11.0 on pci0 dc0: Ethernet address: 00:a0:cc:da:da:da miibus0: <MII bus> on dc0 ukphy0: <Generic IEEE 802.3u media interface> on miibus0 ukphy0: 10baseT, 10baseT-FDX, 100baseTX, 100baseTX-FDX, auto dc1: <82c169 PNIC 10/100BaseTX> port 0x9800-0x98ff mem 0xd3000000-0xd30 000ff irq 11 at device 12.0 on pci0 dc1: Ethernet address: 00:a0:cc:da:da:db miibus1: <MII bus> on dc1 ukphy1: <Generic IEEE 802.3u media interface> on miibus1 ukphy1: 10baseT, 10baseT-FDX, 100baseTX, 100baseTX-FDX, auto In this example, we see that two cards using the &man.dc.4; driver are present on the system. If the driver for your NIC is not present in GENERIC, you will need to load the proper driver to use your NIC. This may be accomplished in one of two ways: The easiest way is to simply load a kernel module for - your network card with &man.kldload.8;. Not all NIC + your network card with &man.kldload.8;, or automatically at boot time by adding the appropriate line to the file /boot/loader.conf. Not all NIC drivers are available as modules; notable examples of devices for which modules do not exist are ISA cards. Alternatively, you may statically compile the support for your card into your kernel. Check /usr/src/sys/conf/NOTES, /usr/src/sys/arch/conf/NOTES and the manual page of the driver to know what to add in your kernel configuration file. For more information about recompiling your kernel, please see . If your card was detected at boot by your kernel (GENERIC) you do not have to build a new kernel. + + + Using &windows; NDIS Drivers + + NDIS + NDISulator + &windows; drivers + Microsoft Windows + Microsoft Windows + device drivers + KLD (kernel loadable + object) + + + Unfortunately, there are still many vendors that do not + provide schematics for their drivers to the open source + community because they regard such information as trade + secrets. Consequently, the developers of &os; and other + operating systems are left two choices: develop the drivers + by a long and pain-staking process of reverse engineering or + using the existing driver binaries available for the + µsoft.windows; platforms. Most developers, including + those involved with &os;, have taken the latter + approach. + + Thanks to the contributions of Bill Paul (wpaul), as of + &os; 5.3-RELEASE there is native support + for the Network Driver Interface Specification (NDIS). The + &os; NDISulator (otherwise known as Project Evil) takes a + &windows; driver binary and basically tricks it into + thinking it is running on &windows;. Because the + &man.ndis.4; driver is using a &windows; binary, it is only + usable on &i386; and amd64 systems. + + + The &man.ndis.4; driver is designed to support mainly + PCI, CardBus and PCMCIA devices, USB devices are not yet + supported. + + + In order to use the NDISulator, you need three + things: + + + + Kernel sources + + + &windowsxp; driver binary + (.SYS extension) + + + &windowsxp; driver configuration file + (.INF extension) + + + + Locate the files for your specific card. Generally, + they can be found on the included CDs or at the vendors' + websites. In the following examples, we will use + W32DRIVER.SYS and + W32DRIVER.INF. + + + You can not use a &windows;/i386 driver with + &os;/amd64, you must get a &windows;/amd64 driver to make it + work properly. + + + The next step is to compile the driver binary into a + loadable kernel module. To accomplish this, as + root, use &man.ndisgen.8;: + + &prompt.root; ndisgen /path/to/W32DRIVER.INF /path/to/W32DRIVER.SYS + + The &man.ndisgen.8; utility is interactive and will + prompt for any extra information it requires; it will + produce a kernel module in the current directory which can + be loaded as follows: + + &prompt.root; kldload ./W32DRIVER.ko + + In addition to the generated kernel module, you must + load the ndis.ko and + if_ndis.ko modules. This should be + automatically done when you load any module that depends on + &man.ndis.4;. If you want to load them manually, use the + following commands: + + &prompt.root; kldload ndis +&prompt.root; kldload if_ndis + + The first command loads the NDIS miniport driver + wrapper, the second loads the actual network + interface. + + Now, check &man.dmesg.8; to see if there were any errors + loading. If all went well, you should get output resembling + the following: + + ndis0: <Wireless-G PCI Adapter> mem 0xf4100000-0xf4101fff irq 3 at device 8.0 on pci1 +ndis0: NDIS API version: 5.0 +ndis0: Ethernet address: 0a:b1:2c:d3:4e:f5 +ndis0: 11b rates: 1Mbps 2Mbps 5.5Mbps 11Mbps +ndis0: 11g rates: 6Mbps 9Mbps 12Mbps 18Mbps 36Mbps 48Mbps 54Mbps + + From here you can treat the + ndis0 device like any other network + interface (e.g., dc0). + + You can configure the system to load the NDIS modules at + boot time in the same way as with any other module. First, + copy the generated module, + W32DRIVER.ko, to the /boot/modules directory. Then, + add the following line to + /boot/loader.conf: + + W32DRIVER_load="YES" + 設定網路卡 network cards configuration Once the right driver is loaded for the network card, the card needs to be configured. As with many other things, the network card may have been configured at installation time by sysinstall. To display the configuration for the network interfaces on your system, enter the following command: &prompt.user; ifconfig dc0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500 inet 192.168.1.3 netmask 0xffffff00 broadcast 192.168.1.255 ether 00:a0:cc:da:da:da media: Ethernet autoselect (100baseTX <full-duplex>) status: active dc1: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500 inet 10.0.0.1 netmask 0xffffff00 broadcast 10.0.0.255 ether 00:a0:cc:da:da:db media: Ethernet 10baseT/UTP status: no carrier lp0: flags=8810<POINTOPOINT,SIMPLEX,MULTICAST> mtu 1500 lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> mtu 16384 inet 127.0.0.1 netmask 0xff000000 tun0: flags=8010<POINTOPOINT,MULTICAST> mtu 1500 Old versions of &os; may require the option following &man.ifconfig.8;, for more details about the correct syntax of &man.ifconfig.8;, please refer to the manual page. Note also that entries concerning IPv6 (inet6 etc.) were omitted in this example. In this example, the following devices were displayed: dc0: The first Ethernet interface dc1: The second Ethernet interface lp0: The parallel port interface lo0: The loopback device tun0: The tunnel device used by ppp &os; uses the driver name followed by the order in which one the card is detected at the kernel boot to name the network card. For example sis2 would be the third network card on the system using the &man.sis.4; driver. In this example, the dc0 device is up and running. The key indicators are: UP means that the card is configured and ready. The card has an Internet (inet) address (in this case 192.168.1.3). It has a valid subnet mask (netmask; 0xffffff00 is the same as 255.255.255.0). It has a valid broadcast address (in this case, 192.168.1.255). The MAC address of the card (ether) is 00:a0:cc:da:da:da The physical media selection is on autoselection mode (media: Ethernet autoselect (100baseTX <full-duplex>)). We see that dc1 was configured to run with 10baseT/UTP media. For more information on available media types for a driver, please refer to its manual page. The status of the link (status) is active, i.e. the carrier is detected. For dc1, we see status: no carrier. This is normal when an Ethernet cable is not plugged into the card. If the &man.ifconfig.8; output had shown something similar to: dc0: flags=8843<BROADCAST,SIMPLEX,MULTICAST> mtu 1500 ether 00:a0:cc:da:da:da it would indicate the card has not been configured. To configure your card, you need root privileges. The network card configuration can be done from the command line with &man.ifconfig.8; but you would have to do it after each reboot of the system. The file /etc/rc.conf is where to add the network card's configuration. Open /etc/rc.conf in your favorite editor. You need to add a line for each network card present on the system, for example in our case, we added these lines: ifconfig_dc0="inet 192.168.1.3 netmask 255.255.255.0" ifconfig_dc1="inet 10.0.0.1 netmask 255.255.255.0 media 10baseT/UTP" You have to replace dc0, dc1, and so on, with the correct device for your cards, and the addresses with the proper ones. You should read the card driver and &man.ifconfig.8; manual pages for more details about the allowed options and also &man.rc.conf.5; manual page for more information on the syntax of /etc/rc.conf. If you configured the network during installation, some lines about the network card(s) may be already present. Double check /etc/rc.conf before adding any lines. You will also have to edit the file /etc/hosts to add the names and the IP addresses of various machines of the LAN, if they are not already there. For more information please refer to &man.hosts.5; and to /usr/share/examples/etc/hosts. 測試與疑難排除 Once you have made the necessary changes in /etc/rc.conf, you should reboot your system. This will allow the change(s) to the interface(s) to be applied, and verify that the system restarts without any configuration errors. Once the system has been rebooted, you should test the network interfaces. 測試乙太網路卡(Ethernet Card) network cards testing To verify that an Ethernet card is configured correctly, you have to try two things. First, ping the interface itself, and then ping another machine on the LAN. First test the local interface: &prompt.user; ping -c5 192.168.1.3 PING 192.168.1.3 (192.168.1.3): 56 data bytes 64 bytes from 192.168.1.3: icmp_seq=0 ttl=64 time=0.082 ms 64 bytes from 192.168.1.3: icmp_seq=1 ttl=64 time=0.074 ms 64 bytes from 192.168.1.3: icmp_seq=2 ttl=64 time=0.076 ms 64 bytes from 192.168.1.3: icmp_seq=3 ttl=64 time=0.108 ms 64 bytes from 192.168.1.3: icmp_seq=4 ttl=64 time=0.076 ms --- 192.168.1.3 ping statistics --- 5 packets transmitted, 5 packets received, 0% packet loss round-trip min/avg/max/stddev = 0.074/0.083/0.108/0.013 ms Now we have to ping another machine on the LAN: &prompt.user; ping -c5 192.168.1.2 PING 192.168.1.2 (192.168.1.2): 56 data bytes 64 bytes from 192.168.1.2: icmp_seq=0 ttl=64 time=0.726 ms 64 bytes from 192.168.1.2: icmp_seq=1 ttl=64 time=0.766 ms 64 bytes from 192.168.1.2: icmp_seq=2 ttl=64 time=0.700 ms 64 bytes from 192.168.1.2: icmp_seq=3 ttl=64 time=0.747 ms 64 bytes from 192.168.1.2: icmp_seq=4 ttl=64 time=0.704 ms --- 192.168.1.2 ping statistics --- 5 packets transmitted, 5 packets received, 0% packet loss round-trip min/avg/max/stddev = 0.700/0.729/0.766/0.025 ms You could also use the machine name instead of 192.168.1.2 if you have set up the /etc/hosts file. 疑難排除 network cards troubleshooting Troubleshooting hardware and software configurations is always a pain, and a pain which can be alleviated by checking the simple things first. Is your network cable plugged in? Have you properly configured the network services? Did you configure the firewall correctly? Is the card you are using supported by &os;? Always check the hardware notes before sending off a bug report. Update your version of &os; to the latest STABLE version. Check the mailing list archives, or perhaps search the Internet. If the card works, yet performance is poor, it would be worthwhile to read over the &man.tuning.7; manual page. You can also check the network configuration as incorrect network settings can cause slow connections. Some users experience one or two device timeout messages, which is normal for some cards. If they continue, or are bothersome, you may wish to be sure the device is not conflicting with another device. Double check the cable connections. Perhaps you may just need to get another card. At times, users see a few watchdog timeout errors. The first thing to do here is to check your network cable. Many cards require a PCI slot which supports Bus Mastering. On some old motherboards, only one PCI slot allows it (usually slot 0). Check the network card and the motherboard documentation to determine if that may be the problem. No route to host messages occur if the system is unable to route a packet to the destination host. This can happen if no default route is specified, or if a cable is unplugged. Check the output of netstat -rn and make sure there is a valid route to the host you are trying to reach. If there is not, read on to . ping: sendto: Permission denied error messages are often caused by a misconfigured firewall. If ipfw is enabled in the kernel but no rules have been defined, then the default policy is to deny all traffic, even ping requests! Read on to for more information. Sometimes performance of the card is poor, or below average. In these cases it is best to set the media selection mode from autoselect to the correct media selection. While this usually works for most hardware, it may not resolve this issue for everyone. Again, check all the network settings, and read over the &man.tuning.7; manual page. 虛擬主機(Virtual Hosts) virtual hosts IP aliases A very common use of &os; is virtual site hosting, where one server appears to the network as many servers. This is achieved by assigning multiple network addresses to a single interface. A given network interface has one real address, and may have any number of alias addresses. These aliases are normally added by placing alias entries in /etc/rc.conf. An alias entry for the interface fxp0 looks like: ifconfig_fxp0_alias0="inet xxx.xxx.xxx.xxx netmask xxx.xxx.xxx.xxx" Note that alias entries must start with alias0 and proceed upwards in order, (for example, _alias1, _alias2, and so on). The configuration process will stop at the first missing number. The calculation of alias netmasks is important, but fortunately quite simple. For a given interface, there must be one address which correctly represents the network's netmask. Any other addresses which fall within this network must have a netmask of all 1s (expressed as either 255.255.255.255 or 0xffffffff). For example, consider the case where the fxp0 interface is connected to two networks, the 10.1.1.0 network with a netmask of 255.255.255.0 and the 202.0.75.16 network with a netmask of 255.255.255.240. We want the system to appear at 10.1.1.1 through 10.1.1.5 and at 202.0.75.17 through 202.0.75.20. As noted above, only the first address in a given network range (in this case, 10.0.1.1 and 202.0.75.17) should have a real netmask; all the rest (10.1.1.2 through 10.1.1.5 and 202.0.75.18 through 202.0.75.20) must be configured with a netmask of 255.255.255.255. The following /etc/rc.conf entries configure the adapter correctly for this arrangement: ifconfig_fxp0="inet 10.1.1.1 netmask 255.255.255.0" ifconfig_fxp0_alias0="inet 10.1.1.2 netmask 255.255.255.255" ifconfig_fxp0_alias1="inet 10.1.1.3 netmask 255.255.255.255" ifconfig_fxp0_alias2="inet 10.1.1.4 netmask 255.255.255.255" ifconfig_fxp0_alias3="inet 10.1.1.5 netmask 255.255.255.255" ifconfig_fxp0_alias4="inet 202.0.75.17 netmask 255.255.255.240" ifconfig_fxp0_alias5="inet 202.0.75.18 netmask 255.255.255.255" ifconfig_fxp0_alias6="inet 202.0.75.19 netmask 255.255.255.255" ifconfig_fxp0_alias7="inet 202.0.75.20 netmask 255.255.255.255" 還有哪些主要設定檔呢? <filename>/etc</filename> Layout There are a number of directories in which configuration information is kept. These include: /etc Generic system configuration information; data here is system-specific. /etc/defaults Default versions of system configuration files. /etc/mail Extra &man.sendmail.8; configuration, other MTA configuration files. /etc/ppp Configuration for both user- and kernel-ppp programs. /etc/namedb Default location for &man.named.8; data. Normally named.conf and zone files are stored here. /usr/local/etc Configuration files for installed applications. May contain per-application subdirectories. /usr/local/etc/rc.d Start/stop scripts for installed applications. /var/db Automatically generated system-specific database files, such as the package database, the locate database, and so on Hostnames hostname DNS <filename>/etc/resolv.conf</filename> resolv.conf /etc/resolv.conf dictates how &os;'s resolver accesses the Internet Domain Name System (DNS). The most common entries to resolv.conf are: nameserver The IP address of a name server the resolver should query. The servers are queried in the order listed with a maximum of three. search Search list for hostname lookup. This is normally determined by the domain of the local hostname. domain The local domain name. A typical resolv.conf: search example.com nameserver 147.11.1.11 nameserver 147.11.100.30 Only one of the search and domain options should be used. If you are using DHCP, &man.dhclient.8; usually rewrites resolv.conf with information received from the DHCP server. <filename>/etc/hosts</filename> hosts /etc/hosts is a simple text database reminiscent of the old Internet. It works in conjunction with DNS and NIS providing name to IP address mappings. Local computers connected via a LAN can be placed in here for simplistic naming purposes instead of setting up a &man.named.8; server. Additionally, /etc/hosts can be used to provide a local record of Internet names, reducing the need to query externally for commonly accessed names. # $&os;$ # # Host Database # This file should contain the addresses and aliases # for local hosts that share this file. # In the presence of the domain name service or NIS, this file may # not be consulted at all; see /etc/nsswitch.conf for the resolution order. # # ::1 localhost localhost.my.domain myname.my.domain 127.0.0.1 localhost localhost.my.domain myname.my.domain # # Imaginary network. #10.0.0.2 myname.my.domain myname #10.0.0.3 myfriend.my.domain myfriend # # According to RFC 1918, you can use the following IP networks for # private nets which will never be connected to the Internet: # # 10.0.0.0 - 10.255.255.255 # 172.16.0.0 - 172.31.255.255 # 192.168.0.0 - 192.168.255.255 # # In case you want to be able to connect to the Internet, you need # real official assigned numbers. PLEASE PLEASE PLEASE do not try # to invent your own network numbers but instead get one from your # network provider (if any) or from the Internet Registry (ftp to # rs.internic.net, directory `/templates'). # /etc/hosts takes on the simple format of: [Internet address] [official hostname] [alias1] [alias2] ... For example: 10.0.0.1 myRealHostname.example.com myRealHostname foobar1 foobar2 Consult &man.hosts.5; for more information. Log File Configuration log files <filename>syslog.conf</filename> syslog.conf syslog.conf is the configuration file for the &man.syslogd.8; program. It indicates which types of syslog messages are logged to particular log files. # $&os;$ # # Spaces ARE valid field separators in this file. However, # other *nix-like systems still insist on using tabs as field # separators. If you are sharing this file between systems, you # may want to use only tabs as field separators here. # Consult the syslog.conf(5) manual page. *.err;kern.debug;auth.notice;mail.crit /dev/console *.notice;kern.debug;lpr.info;mail.crit;news.err /var/log/messages security.* /var/log/security mail.info /var/log/maillog lpr.info /var/log/lpd-errs cron.* /var/log/cron *.err root *.notice;news.err root *.alert root *.emerg * # uncomment this to log all writes to /dev/console to /var/log/console.log #console.info /var/log/console.log # uncomment this to enable logging of all log messages to /var/log/all.log #*.* /var/log/all.log # uncomment this to enable logging to a remote log host named loghost #*.* @loghost # uncomment these if you're running inn # news.crit /var/log/news/news.crit # news.err /var/log/news/news.err # news.notice /var/log/news/news.notice !startslip *.* /var/log/slip.log !ppp *.* /var/log/ppp.log Consult the &man.syslog.conf.5; manual page for more information. <filename>newsyslog.conf</filename> newsyslog.conf newsyslog.conf is the configuration file for &man.newsyslog.8;, a program that is normally scheduled to run by &man.cron.8;. &man.newsyslog.8; determines when log files require archiving or rearranging. logfile is moved to logfile.0, logfile.0 is moved to logfile.1, and so on. Alternatively, the log files may be archived in &man.gzip.1; format causing them to be named: logfile.0.gz, logfile.1.gz, and so on. newsyslog.conf indicates which log files are to be managed, how many are to be kept, and when they are to be touched. Log files can be rearranged and/or archived when they have either reached a certain size, or at a certain periodic time/date. # configuration file for newsyslog # $&os;$ # # filename [owner:group] mode count size when [ZB] [/pid_file] [sig_num] /var/log/cron 600 3 100 * Z /var/log/amd.log 644 7 100 * Z /var/log/kerberos.log 644 7 100 * Z /var/log/lpd-errs 644 7 100 * Z /var/log/maillog 644 7 * @T00 Z /var/log/sendmail.st 644 10 * 168 B /var/log/messages 644 5 100 * Z /var/log/all.log 600 7 * @T00 Z /var/log/slip.log 600 3 100 * Z /var/log/ppp.log 600 3 100 * Z /var/log/security 600 10 100 * Z /var/log/wtmp 644 3 * @01T05 B /var/log/daily.log 640 7 * @T00 Z /var/log/weekly.log 640 5 1 $W6D0 Z /var/log/monthly.log 640 12 * $M1D0 Z /var/log/console.log 640 5 100 * Z Consult the &man.newsyslog.8; manual page for more information. <filename>sysctl.conf</filename> sysctl.conf sysctl sysctl.conf looks much like rc.conf. Values are set in a variable=value form. The specified values are set after the system goes into multi-user mode. Not all variables are settable in this mode. A sample sysctl.conf turning off logging of fatal signal exits and letting Linux programs know they are really running under &os;: kern.logsigexit=0 # Do not log fatal signal exits (e.g. sig 11) compat.linux.osname=&os; compat.linux.osrelease=4.3-STABLE Tuning with sysctl sysctl tuning with sysctl &man.sysctl.8; is an interface that allows you to make changes to a running &os; system. This includes many advanced options of the TCP/IP stack and virtual memory system that can dramatically improve performance for an experienced system administrator. Over five hundred system variables can be read and set using &man.sysctl.8;. At its core, &man.sysctl.8; serves two functions: to read and to modify system settings. To view all readable variables: &prompt.user; sysctl -a To read a particular variable, for example, kern.maxproc: &prompt.user; sysctl kern.maxproc kern.maxproc: 1044 To set a particular variable, use the intuitive variable=value syntax: &prompt.root; sysctl kern.maxfiles=5000 kern.maxfiles: 2088 -> 5000 Settings of sysctl variables are usually either strings, numbers, or booleans (a boolean being 1 for yes or a 0 for no). If you want to set automatically some variables each time the machine boots, add them to the /etc/sysctl.conf file. For more information see the &man.sysctl.conf.5; manual page and the . Tom Rhodes Contributed by &man.sysctl.8; Read-only In some cases it may be desirable to modify read-only &man.sysctl.8; values. While this is sometimes unavoidable, it can only be done on (re)boot. For instance on some laptop models the &man.cardbus.4; device will not probe memory ranges, and fail with errors which look similar to: cbb0: Could not map register memory device_probe_and_attach: cbb0 attach returned 12 Cases like the one above usually require the modification of some default &man.sysctl.8; settings which are set read only. To overcome these situations a user can put &man.sysctl.8; OIDs in their local /boot/loader.conf. Default settings are located in the /boot/defaults/loader.conf file. Fixing the problem mentioned above would require a user to set in the aforementioned file. Now &man.cardbus.4; will work properly. Tuning Disks Sysctl Variables <varname>vfs.vmiodirenable</varname> vfs.vmiodirenable The vfs.vmiodirenable sysctl variable may be set to either 0 (off) or 1 (on); it is 1 by default. This variable controls how directories are cached by the system. Most directories are small, using just a single fragment (typically 1 K) in the file system and less (typically 512 bytes) in the buffer cache. With this variable turned off (to 0), the buffer cache will only cache a fixed number of directories even if you have a huge amount of memory. When turned on (to 1), this sysctl allows the buffer cache to use the VM Page Cache to cache the directories, making all the memory available for caching directories. However, the minimum in-core memory used to cache a directory is the physical page size (typically 4 K) rather than 512  bytes. We recommend keeping this option on if you are running any services which manipulate large numbers of files. Such services can include web caches, large mail systems, and news systems. Keeping this option on will generally not reduce performance even with the wasted memory but you should experiment to find out. <varname>vfs.write_behind</varname> vfs.write_behind The vfs.write_behind sysctl variable defaults to 1 (on). This tells the file system to issue media writes as full clusters are collected, which typically occurs when writing large sequential files. The idea is to avoid saturating the buffer cache with dirty buffers when it would not benefit I/O performance. However, this may stall processes and under certain circumstances you may wish to turn it off. <varname>vfs.hirunningspace</varname> vfs.hirunningspace The vfs.hirunningspace sysctl variable determines how much outstanding write I/O may be queued to disk controllers system-wide at any given instance. The default is usually sufficient but on machines with lots of disks you may want to bump it up to four or five megabytes. Note that setting too high a value (exceeding the buffer cache's write threshold) can lead to extremely bad clustering performance. Do not set this value arbitrarily high! Higher write values may add latency to reads occurring at the same time. There are various other buffer-cache and VM page cache related sysctls. We do not recommend modifying these values, the VM system does an extremely good job of automatically tuning itself. <varname>vm.swap_idle_enabled</varname> vm.swap_idle_enabled The vm.swap_idle_enabled sysctl variable is useful in large multi-user systems where you have lots of users entering and leaving the system and lots of idle processes. Such systems tend to generate a great deal of continuous pressure on free memory reserves. Turning this feature on and tweaking the swapout hysteresis (in idle seconds) via vm.swap_idle_threshold1 and vm.swap_idle_threshold2 allows you to depress the priority of memory pages associated with idle processes more quickly then the normal pageout algorithm. This gives a helping hand to the pageout daemon. Do not turn this option on unless you need it, because the tradeoff you are making is essentially pre-page memory sooner rather than later; thus eating more swap and disk bandwidth. In a small system this option will have a determinable effect but in a large system that is already doing moderate paging this option allows the VM system to stage whole processes into and out of memory easily. <varname>hw.ata.wc</varname> hw.ata.wc &os; 4.3 flirted with turning off IDE write caching. This reduced write bandwidth to IDE disks but was considered necessary due to serious data consistency issues introduced by hard drive vendors. The problem is that IDE drives lie about when a write completes. With IDE write caching turned on, IDE hard drives not only write data to disk out of order, but will sometimes delay writing some blocks indefinitely when under heavy disk loads. A crash or power failure may cause serious file system corruption. &os;'s default was changed to be safe. Unfortunately, the result was such a huge performance loss that we changed write caching back to on by default after the release. You should check the default on your system by observing the hw.ata.wc sysctl variable. If IDE write caching is turned off, you can turn it back on by setting the kernel variable back to 1. This must be done from the boot loader at boot time. Attempting to do it after the kernel boots will have no effect. For more information, please see &man.ata.4;. <literal>SCSI_DELAY</literal> (<varname>kern.cam.scsi_delay</varname>) kern.cam.scsi_delay kernel options SCSI_DELAY The SCSI_DELAY kernel config may be used to reduce system boot times. The defaults are fairly high and can be responsible for 15 seconds of delay in the boot process. Reducing it to 5 seconds usually works (especially with modern drives). Newer versions of &os; (5.0 and higher) should use the kern.cam.scsi_delay boot time tunable. The tunable, and kernel config option accept values in terms of milliseconds and not seconds. Soft Updates Soft Updates tunefs The &man.tunefs.8; program can be used to fine-tune a file system. This program has many different options, but for now we are only concerned with toggling Soft Updates on and off, which is done by: &prompt.root; tunefs -n enable /filesystem &prompt.root; tunefs -n disable /filesystem A filesystem cannot be modified with &man.tunefs.8; while it is mounted. A good time to enable Soft Updates is before any partitions have been mounted, in single-user mode. Soft Updates drastically improves meta-data performance, mainly file creation and deletion, through the use of a memory cache. We recommend to use Soft Updates on all of your file systems. There are two downsides to Soft Updates that you should be aware of: First, Soft Updates guarantees filesystem consistency in the case of a crash but could very easily be several seconds (even a minute!) behind updating the physical disk. If your system crashes you may lose more work than otherwise. Secondly, Soft Updates delays the freeing of filesystem blocks. If you have a filesystem (such as the root filesystem) which is almost full, performing a major update, such as make installworld, can cause the filesystem to run out of space and the update to fail. More Details about Soft Updates Soft Updates details There are two traditional approaches to writing a file systems meta-data back to disk. (Meta-data updates are updates to non-content data like inodes or directories.) Historically, the default behavior was to write out meta-data updates synchronously. If a directory had been changed, the system waited until the change was actually written to disk. The file data buffers (file contents) were passed through the buffer cache and backed up to disk later on asynchronously. The advantage of this implementation is that it operates safely. If there is a failure during an update, the meta-data are always in a consistent state. A file is either created completely or not at all. If the data blocks of a file did not find their way out of the buffer cache onto the disk by the time of the crash, &man.fsck.8; is able to recognize this and repair the filesystem by setting the file length to 0. Additionally, the implementation is clear and simple. The disadvantage is that meta-data changes are slow. An rm -r, for instance, touches all the files in a directory sequentially, but each directory change (deletion of a file) will be written synchronously to the disk. This includes updates to the directory itself, to the inode table, and possibly to indirect blocks allocated by the file. Similar considerations apply for unrolling large hierarchies (tar -x). The second case is asynchronous meta-data updates. This is the default for Linux/ext2fs and mount -o async for *BSD ufs. All meta-data updates are simply being passed through the buffer cache too, that is, they will be intermixed with the updates of the file content data. The advantage of this implementation is there is no need to wait until each meta-data update has been written to disk, so all operations which cause huge amounts of meta-data updates work much faster than in the synchronous case. Also, the implementation is still clear and simple, so there is a low risk for bugs creeping into the code. The disadvantage is that there is no guarantee at all for a consistent state of the filesystem. If there is a failure during an operation that updated large amounts of meta-data (like a power failure, or someone pressing the reset button), the filesystem will be left in an unpredictable state. There is no opportunity to examine the state of the filesystem when the system comes up again; the data blocks of a file could already have been written to the disk while the updates of the inode table or the associated directory were not. It is actually impossible to implement a fsck which is able to clean up the resulting chaos (because the necessary information is not available on the disk). If the filesystem has been damaged beyond repair, the only choice is to use &man.newfs.8; on it and restore it from backup. The usual solution for this problem was to implement dirty region logging, which is also referred to as journaling, although that term is not used consistently and is occasionally applied to other forms of transaction logging as well. Meta-data updates are still written synchronously, but only into a small region of the disk. Later on they will be moved to their proper location. Because the logging area is a small, contiguous region on the disk, there are no long distances for the disk heads to move, even during heavy operations, so these operations are quicker than synchronous updates. Additionally the complexity of the implementation is fairly limited, so the risk of bugs being present is low. A disadvantage is that all meta-data are written twice (once into the logging region and once to the proper location) so for normal work, a performance pessimization might result. On the other hand, in case of a crash, all pending meta-data operations can be quickly either rolled-back or completed from the logging area after the system comes up again, resulting in a fast filesystem startup. Kirk McKusick, the developer of Berkeley FFS, solved this problem with Soft Updates: all pending meta-data updates are kept in memory and written out to disk in a sorted sequence (ordered meta-data updates). This has the effect that, in case of heavy meta-data operations, later updates to an item catch the earlier ones if the earlier ones are still in memory and have not already been written to disk. So all operations on, say, a directory are generally performed in memory before the update is written to disk (the data blocks are sorted according to their position so that they will not be on the disk ahead of their meta-data). If the system crashes, this causes an implicit log rewind: all operations which did not find their way to the disk appear as if they had never happened. A consistent filesystem state is maintained that appears to be the one of 30 to 60 seconds earlier. The algorithm used guarantees that all resources in use are marked as such in their appropriate bitmaps: blocks and inodes. After a crash, the only resource allocation error that occurs is that resources are marked as used which are actually free. &man.fsck.8; recognizes this situation, and frees the resources that are no longer used. It is safe to ignore the dirty state of the filesystem after a crash by forcibly mounting it with mount -f. In order to free resources that may be unused, &man.fsck.8; needs to be run at a later time. This is the idea behind the background fsck: at system startup time, only a snapshot of the filesystem is recorded. The fsck can be run later on. All file systems can then be mounted dirty, so the system startup proceeds in multiuser mode. Then, background fscks will be scheduled for all file systems where this is required, to free resources that may be unused. (File systems that do not use Soft Updates still need the usual foreground fsck though.) The advantage is that meta-data operations are nearly as fast as asynchronous updates (i.e. faster than with logging, which has to write the meta-data twice). The disadvantages are the complexity of the code (implying a higher risk for bugs in an area that is highly sensitive regarding loss of user data), and a higher memory consumption. Additionally there are some idiosyncrasies one has to get used to. After a crash, the state of the filesystem appears to be somewhat older. In situations where the standard synchronous approach would have caused some zero-length files to remain after the fsck, these files do not exist at all with a Soft Updates filesystem because neither the meta-data nor the file contents have ever been written to disk. Disk space is not released until the updates have been written to disk, which may take place some time after running rm. This may cause problems when installing large amounts of data on a filesystem that does not have enough free space to hold all the files twice. Tuning Kernel Limits tuning kernel limits File/Process Limits <varname>kern.maxfiles</varname> kern.maxfiles kern.maxfiles can be raised or lowered based upon your system requirements. This variable indicates the maximum number of file descriptors on your system. When the file descriptor table is full, file: table is full will show up repeatedly in the system message buffer, which can be viewed with the dmesg command. Each open file, socket, or fifo uses one file descriptor. A large-scale production server may easily require many thousands of file descriptors, depending on the kind and number of services running concurrently. - kern.maxfile's default value is + In older FreeBSD releases, kern.maxfile's default + value is derived from the option in your dictated by the option in your kernel configuration file. kern.maxfiles grows proportionally to the value of . When compiling a custom kernel, it is a good idea to set this kernel configuration option according to the uses of your system. From this number, the kernel is given most of its pre-defined limits. Even though a production machine may not actually have 256 users connected at once, the resources needed may be similar to a high-scale web server. + As of FreeBSD 4.5, kern.maxusers is + automatically sized at boot based on the amount of memory available + in the system, and may be determined at run-time by inspecting the + value of the read-only kern.maxusers sysctl. + Some sites will require larger or smaller values of + kern.maxusers and may set it as a loader tunable; + values of 64, 128, and 256 are not uncommon. We do not recommend + going above 256 unless you need a huge number of file descriptors; + many of the tunable values set to their defaults by + kern.maxusers may be individually overridden at + boot-time or run-time in /boot/loader.conf (see + the &man.loader.conf.5; man page or the + /boot/defaults/loader.conf file for some hints) + or as described elsewhere in this document. Systems older than + FreeBSD 4.4 must set this value via the kernel &man.config.8; + option instead. + The system will auto-tune maxusers for you if you explicitly set it to 0 The auto-tuning algorithm sets maxusers equal to the amount of memory in the system, with a minimum of 32, and a maximum of 384. . When setting this option, you will want to set maxusers to at least 4, especially if you are using the X Window System or compiling software. The reason is that the most important table set by maxusers is the maximum number of processes, which is set to 20 + 16 * maxusers, so if you set maxusers to 1, then you can only have 36 simultaneous processes, including the 18 or so that the system starts up at boot time and the 15 or so you will probably create when you start the X Window System. Even a simple task like reading a manual page will start up nine processes to filter, decompress, and view it. Setting maxusers to 64 will allow you to have up to 1044 simultaneous processes, which should be enough for nearly all uses. If, however, you see the dreaded proc table full error when trying to start another program, or are running a server with a large number of simultaneous users (like ftp.FreeBSD.org), you can always increase the number and rebuild. maxusers does not limit the number of users which can log into your machine. It simply sets various table sizes to reasonable values considering the maximum number of users you will likely have on your system and how many processes each of them will be running. One keyword which does limit the number of simultaneous remote logins and X terminal windows is pseudo-device pty 16. With &os; 5.X, you do not have to worry about this number since the &man.pty.4; driver is auto-cloning; you simply use the line device pty in your configuration file. <varname>kern.ipc.somaxconn</varname> kern.ipc.somaxconn The kern.ipc.somaxconn sysctl variable limits the size of the listen queue for accepting new TCP connections. The default value of 128 is typically too low for robust handling of new connections in a heavily loaded web server environment. For such environments, it is recommended to increase this value to 1024 or higher. The service daemon may itself limit the listen queue size (e.g. &man.sendmail.8;, or Apache) but will often have a directive in its configuration file to adjust the queue size. Large listen queues also do a better job of avoiding Denial of Service (DoS) attacks. Network Limits The NMBCLUSTERS kernel configuration option dictates the amount of network Mbufs available to the system. A heavily-trafficked server with a low number of Mbufs will hinder &os;'s ability. Each cluster represents approximately 2 K of memory, so a value of 1024 represents 2 megabytes of kernel memory reserved for network buffers. A simple calculation can be done to figure out how many are needed. If you have a web server which maxes out at 1000 simultaneous connections, and each connection eats a 16 K receive and 16 K send buffer, you need approximately 32 MB worth of network buffers to cover the web server. A good rule of thumb is to multiply by 2, so 2x32 MB / 2 KB = 64 MB / 2 kB = 32768. We recommend values between 4096 and 32768 for machines with greater amounts of memory. Under no circumstances should you specify an arbitrarily high value for this parameter as it could lead to a boot time crash. The option to &man.netstat.1; may be used to observe network cluster use. kern.ipc.nmbclusters loader tunable should be used to tune this at boot time. Only older versions of &os; will require you to use the NMBCLUSTERS kernel &man.config.8; option. For busy servers that make extensive use of the &man.sendfile.2; system call, it may be necessary to increase the number of &man.sendfile.2; buffers via the NSFBUFS kernel configuration option or by setting its value in /boot/loader.conf (see &man.loader.8; for details). A common indicator that this parameter needs to be adjusted is when processes are seen in the sfbufa state. The sysctl variable kern.ipc.nsfbufs is a read-only glimpse at the kernel configured variable. This parameter nominally scales with kern.maxusers, however it may be necessary to tune accordingly. Even though a socket has been marked as non-blocking, calling &man.sendfile.2; on the non-blocking socket may result in the &man.sendfile.2; call blocking until enough struct sf_buf's are made available. <varname>net.inet.ip.portrange.*</varname> net.inet.ip.portrange.* The net.inet.ip.portrange.* sysctl variables control the port number ranges automatically bound to TCP and UDP sockets. There are three ranges: a low range, a default range, and a high range. Most network programs use the default range which is controlled by the net.inet.ip.portrange.first and net.inet.ip.portrange.last, which default to 1024 and 5000, respectively. Bound port ranges are used for outgoing connections, and it is possible to run the system out of ports under certain circumstances. This most commonly occurs when you are running a heavily loaded web proxy. The port range is not an issue when running servers which handle mainly incoming connections, such as a normal web server, or has a limited number of outgoing connections, such as a mail relay. For situations where you may run yourself out of ports, it is recommended to increase net.inet.ip.portrange.last modestly. A value of 10000, 20000 or 30000 may be reasonable. You should also consider firewall effects when changing the port range. Some firewalls may block large ranges of ports (usually low-numbered ports) and expect systems to use higher ranges of ports for outgoing connections — for this reason it is not recommended that net.inet.ip.portrange.first be lowered. TCP Bandwidth Delay Product TCP Bandwidth Delay Product Limiting net.inet.tcp.inflight.enable The TCP Bandwidth Delay Product Limiting is similar to TCP/Vegas in NetBSD. It can be enabled by setting net.inet.tcp.inflight.enable sysctl variable to 1. The system will attempt to calculate the bandwidth delay product for each connection and limit the amount of data queued to the network to just the amount required to maintain optimum throughput. This feature is useful if you are serving data over modems, Gigabit Ethernet, or even high speed WAN links (or any other link with a high bandwidth delay product), especially if you are also using window scaling or have configured a large send window. If you enable this option, you should also be sure to set net.inet.tcp.inflight.debug to 0 (disable debugging), and for production use setting net.inet.tcp.inflight.min to at least 6144 may be beneficial. However, note that setting high minimums may effectively disable bandwidth limiting depending on the link. The limiting feature reduces the amount of data built up in intermediate route and switch packet queues as well as reduces the amount of data built up in the local host's interface queue. With fewer packets queued up, interactive connections, especially over slow modems, will also be able to operate with lower Round Trip Times. However, note that this feature only effects data transmission (uploading / server side). It has no effect on data reception (downloading). Adjusting net.inet.tcp.inflight.stab is not recommended. This parameter defaults to 20, representing 2 maximal packets added to the bandwidth delay product window calculation. The additional window is required to stabilize the algorithm and improve responsiveness to changing conditions, but it can also result in higher ping times over slow links (though still much lower than you would get without the inflight algorithm). In such cases, you may wish to try reducing this parameter to 15, 10, or 5; and may also have to reduce net.inet.tcp.inflight.min (for example, to 3500) to get the desired effect. Reducing these parameters should be done as a last resort only. Virtual Memory <varname>kern.maxvnodes</varname> A vnode is the internal representation of a file or directory. So increasing the number of vnodes available to the operating system cuts down on disk I/O. Normally this is handled by the operating system and does not need to be changed. In some cases where disk I/O is a bottleneck and the system is running out of vnodes, this setting will need to be increased. The amount of inactive and free RAM will need to be taken into account. To see the current number of vnodes in use: &prompt.root; sysctl vfs.numvnodes vfs.numvnodes: 91349 To see the maximum vnodes: &prompt.root; sysctl kern.maxvnodes kern.maxvnodes: 100000 If the current vnode usage is near the maximum, increasing kern.maxvnodes by a value of 1,000 is probably a good idea. Keep an eye on the number of vfs.numvnodes. If it climbs up to the maximum again, kern.maxvnodes will need to be increased further. A shift in your memory usage as reported by &man.top.1; should be visible. More memory should be active. Adding Swap Space No matter how well you plan, sometimes a system does not run as you expect. If you find you need more swap space, it is simple enough to add. You have three ways to increase swap space: adding a new hard drive, enabling swap over NFS, and creating a swap file on an existing partition. For information on how to encrypt swap space, what options for this task exist and why it should be done, please refer to of the Handbook. Swap on a New Hard Drive The best way to add swap, of course, is to use this as an excuse to add another hard drive. You can always use another hard drive, after all. If you can do this, go reread the discussion of swap space in of the Handbook for some suggestions on how to best arrange your swap. Swapping over NFS Swapping over NFS is only recommended if you do not have a local hard disk to swap to; NFS swapping will be limited by the available network bandwidth and puts an additional burden on the NFS server. Swapfiles You can create a file of a specified size to use as a swap file. In our example here we will use a 64MB file called /usr/swap0. You can use any name you want, of course. Creating a Swapfile on &os; Be certain that your kernel configuration includes the memory disk driver (&man.md.4;). It is default in GENERIC kernel. device md # Memory "disks" Create a swapfile (/usr/swap0): &prompt.root; dd if=/dev/zero of=/usr/swap0 bs=1024k count=64 Set proper permissions on (/usr/swap0): &prompt.root; chmod 0600 /usr/swap0 Enable the swap file in /etc/rc.conf: swapfile="/usr/swap0" # Set to name of swapfile if aux swapfile desired. Reboot the machine or to enable the swap file immediately, type: &prompt.root; mdconfig -a -t vnode -f /usr/swap0 -u 0 && swapon /dev/md0 Hiten Pandya Written by Tom Rhodes Power and Resource Management It is very important to utilize hardware resources in an efficient manner. Before ACPI was introduced, it was very difficult and inflexible for operating systems to manage the power usage and thermal properties of a system. The hardware was controlled by some sort of BIOS embedded interface, such as Plug and Play BIOS (PNPBIOS), or Advanced Power Management (APM) and so on. Power and Resource Management is one of the key components of a modern operating system. For example, you may want an operating system to monitor system limits (and possibly alert you) in case your system temperature increased unexpectedly. In this section of the &os; Handbook, we will provide comprehensive information about ACPI. References will be provided for further reading at the end. What Is ACPI? ACPI APM Advanced Configuration and Power Interface (ACPI) is a standard written by an alliance of vendors to provide a standard interface for hardware resources and power management (hence the name). It is a key element in Operating System-directed configuration and Power Management, i.e.: it provides more control and flexibility to the operating system (OS). Modern systems stretched the limits of the current Plug and Play interfaces prior to the introduction of ACPI. ACPI is the direct successor to APM (Advanced Power Management). Shortcomings of Advanced Power Management (APM) The Advanced Power Management (APM) facility controls the power usage of a system based on its activity. The APM BIOS is supplied by the (system) vendor and it is specific to the hardware platform. An APM driver in the OS mediates access to the APM Software Interface, which allows management of power levels. There are four major problems in APM. Firstly, power management is done by the (vendor-specific) BIOS, and the OS does not have any knowledge of it. One example of this, is when the user sets idle-time values for a hard drive in the APM BIOS, that when exceeded, it (BIOS) would spin down the hard drive, without the consent of the OS. Secondly, the APM logic is embedded in the BIOS, and it operates outside the scope of the OS. This means users can only fix problems in their APM BIOS by flashing a new one into the ROM; which is a very dangerous procedure with the potential to leave the system in an unrecoverable state if it fails. Thirdly, APM is a vendor-specific technology, which means that there is a lot of parity (duplication of efforts) and bugs found in one vendor's BIOS, may not be solved in others. Last but not the least, the APM BIOS did not have enough room to implement a sophisticated power policy, or one that can adapt very well to the purpose of the machine. Plug and Play BIOS (PNPBIOS) was unreliable in many situations. PNPBIOS is 16-bit technology, so the OS has to use 16-bit emulation in order to interface with PNPBIOS methods. The &os; APM driver is documented in the &man.apm.4; manual page. Configuring <acronym>ACPI</acronym> The acpi.ko driver is loaded by default at start up by the &man.loader.8; and should not be compiled into the kernel. The reasoning behind this is that modules are easier to work with, say if switching to another acpi.ko without doing a kernel rebuild. This has the advantage of making testing easier. Another reason is that starting ACPI after a system has been brought up is not too useful, and in some cases can be fatal. In doubt, just disable ACPI all together. This driver should not and can not be unloaded because the system bus uses it for various hardware interactions. ACPI can be disabled with the &man.acpiconf.8; utility. In fact most of the interaction with ACPI can be done via &man.acpiconf.8;. Basically this means, if anything about ACPI is in the &man.dmesg.8; output, then most likely it is already running. ACPI and APM cannot coexist and should be used separately. The last one to load will terminate if the driver notices the other running. In the simplest form, ACPI can be used to put the system into a sleep mode with &man.acpiconf.8;, the flag, and a 1-5 option. Most users will only need 1. Option 5 will do a soft-off which is the same action as: &prompt.root; halt -p The other options are available. Check out the &man.acpiconf.8; manual page for more information. Nate Lawson Written by Peter Schultz With contributions from Tom Rhodes Using and Debugging &os; <acronym>ACPI</acronym> ACPI problems ACPI is a fundamentally new way of discovering devices, managing power usage, and providing standardized access to various hardware previously managed by the BIOS. Progress is being made toward ACPI working on all systems, but bugs in some motherboards' ACPI Machine Language (AML) bytecode, incompleteness in &os;'s kernel subsystems, and bugs in the &intel; ACPI-CA interpreter continue to appear. This document is intended to help you assist the &os; ACPI maintainers in identifying the root cause of problems you observe and debugging and developing a solution. Thanks for reading this and we hope we can solve your system's problems. Submitting Debugging Information Before submitting a problem, be sure you are running the latest BIOS version and, if available, embedded controller firmware version. For those of you that want to submit a problem right away, please send the following information to freebsd-acpi@FreeBSD.org: Description of the buggy behavior, including system type and model and anything that causes the bug to appear. Also, please note as accurately as possible when the bug began occurring if it is new for you. The &man.dmesg.8; output after boot -v, including any error messages generated by you exercising the bug. The &man.dmesg.8; output from boot -v with ACPI disabled, if disabling it helps fix the problem. Output from sysctl hw.acpi. This is also a good way of figuring out what features your system offers. URL where your ACPI Source Language (ASL) can be found. Do not send the ASL directly to the list as it can be very large. Generate a copy of your ASL by running this command: &prompt.root; acpidump -t -d > name-system.asl (Substitute your login name for name and manufacturer/model for system. Example: njl-FooCo6000.asl) Most of the developers watch the &a.current; but please submit problems to &a.acpi.name; to be sure it is seen. Please be patient, all of us have full-time jobs elsewhere. If your bug is not immediately apparent, we will probably ask you to submit a PR via &man.send-pr.1;. When entering a PR, please include the same information as requested above. This will help us track the problem and resolve it. Do not send a PR without emailing &a.acpi.name; first as we use PRs as reminders of existing problems, not a reporting mechanism. It is likely that your problem has been reported by someone before. Background ACPI ACPI is present in all modern computers that conform to the ia32 (x86), ia64 (Itanium), and amd64 (AMD) architectures. The full standard has many features including CPU performance management, power planes control, thermal zones, various battery systems, embedded controllers, and bus enumeration. Most systems implement less than the full standard. For instance, a desktop system usually only implements the bus enumeration parts while a laptop might have cooling and battery management support as well. Laptops also have suspend and resume, with their own associated complexity. An ACPI-compliant system has various components. The BIOS and chipset vendors provide various fixed tables (e.g., FADT) in memory that specify things like the APIC map (used for SMP), config registers, and simple configuration values. Additionally, a table of bytecode (the Differentiated System Description Table DSDT) is provided that specifies a tree-like name space of devices and methods. The ACPI driver must parse the fixed tables, implement an interpreter for the bytecode, and modify device drivers and the kernel to accept information from the ACPI subsystem. For &os;, &intel; has provided an interpreter (ACPI-CA) that is shared with Linux and NetBSD. The path to the ACPI-CA source code is src/sys/contrib/dev/acpica. The glue code that allows ACPI-CA to work on &os; is in src/sys/dev/acpica/Osd. Finally, drivers that implement various ACPI devices are found in src/sys/dev/acpica. Common Problems ACPI problems For ACPI to work correctly, all the parts have to work correctly. Here are some common problems, in order of frequency of appearance, and some possible workarounds or fixes. Mouse Issues In some cases, resuming from a suspend operation will cause the mouse to fail. A known work around is to add hint.psm.0.flags="0x3000" to the /boot/loader.conf file. If this does not work then please consider sending a bug report as described above. Suspend/Resume ACPI has three suspend to RAM (STR) states, S1-S3, and one suspend to disk state (STD), called S4. S5 is soft off and is the normal state your system is in when plugged in but not powered up. S4 can actually be implemented two separate ways. S4BIOS is a BIOS-assisted suspend to disk. S4OS is implemented entirely by the operating system. Start by checking sysctl hw.acpi for the suspend-related items. Here are the results for a Thinkpad: hw.acpi.supported_sleep_state: S3 S4 S5 hw.acpi.s4bios: 0 This means that we can use acpiconf -s to test S3, S4OS, and S5. If was one (1), we would have S4BIOS support instead of S4 OS. When testing suspend/resume, start with S1, if supported. This state is most likely to work since it does not require much driver support. No one has implemented S2 but if you have it, it is similar to S1. The next thing to try is S3. This is the deepest STR state and requires a lot of driver support to properly reinitialize your hardware. If you have problems resuming, feel free to email the &a.acpi.name; list but do not expect the problem to be resolved since there are a lot of drivers/hardware that need more testing and work. To help isolate the problem, remove as many drivers from your kernel as possible. If it works, you can narrow down which driver is the problem by loading drivers until it fails again. Typically binary drivers like nvidia.ko, X11 display drivers, and USB will have the most problems while Ethernet interfaces usually work fine. If you can properly load/unload the drivers, you can automate this by putting the appropriate commands in /etc/rc.suspend and /etc/rc.resume. There is a commented-out example for unloading and loading a driver. Try setting to zero (0) if your display is messed up after resume. Try setting longer or shorter values for to see if that helps. Another thing to try is load a recent Linux distribution with ACPI support and test their suspend/resume support on the same hardware. If it works on Linux, it is likely a &os; driver problem and narrowing down which driver causes the problems will help us fix the problem. Note that the ACPI maintainers do not usually maintain other drivers (e.g sound, ATA, etc.) so any work done on tracking down a driver problem should probably eventually be posted to the &a.current.name; list and mailed to the driver maintainer. If you are feeling adventurous, go ahead and start putting some debugging &man.printf.3;s in a problematic driver to track down where in its resume function it hangs. Finally, try disabling ACPI and enabling APM instead. If suspend/resume works with APM, you may be better off sticking with APM, especially on older hardware (pre-2000). It took vendors a while to get ACPI support correct and older hardware is more likely to have BIOS problems with ACPI. System Hangs (temporary or permanent) Most system hangs are a result of lost interrupts or an interrupt storm. Chipsets have a lot of problems based on how the BIOS configures interrupts before boot, correctness of the APIC (MADT) table, and routing of the System Control Interrupt (SCI). interrupt storms Interrupt storms can be distinguished from lost interrupts by checking the output of vmstat -i and looking at the line that has acpi0. If the counter is increasing at more than a couple per second, you have an interrupt storm. If the system appears hung, try breaking to DDB (CTRL ALTESC on console) and type show interrupts. APIC disabling Your best hope when dealing with interrupt problems is to try disabling APIC support with hint.apic.0.disabled="1" in loader.conf. Panics Panics are relatively rare for ACPI and are the top priority to be fixed. The first step is to isolate the steps to reproduce the panic (if possible) and get a backtrace. Follow the advice for enabling options DDB and setting up a serial console (see ) or setting up a &man.dump.8; partition. You can get a backtrace in DDB with tr. If you have to handwrite the backtrace, be sure to at least get the lowest five (5) and top five (5) lines in the trace. Then, try to isolate the problem by booting with ACPI disabled. If that works, you can isolate the ACPI subsystem by using various values of . See the &man.acpi.4; manual page for some examples. System Powers Up After Suspend or Shutdown First, try setting hw.acpi.disable_on_poweroff="0" in &man.loader.conf.5;. This keeps ACPI from disabling various events during the shutdown process. Some systems need this value set to 1 (the default) for the same reason. This usually fixes the problem of a system powering up spontaneously after a suspend or poweroff. Other Problems If you have other problems with ACPI (working with a docking station, devices not detected, etc.), please email a description to the mailing list as well; however, some of these issues may be related to unfinished parts of the ACPI subsystem so they might take a while to be implemented. Please be patient and prepared to test patches we may send you. <acronym>ASL</acronym>, <command>acpidump</command>, and <acronym>IASL</acronym> ACPI ASL The most common problem is the BIOS vendors providing incorrect (or outright buggy!) bytecode. This is usually manifested by kernel console messages like this: ACPI-1287: *** Error: Method execution failed [\\_SB_.PCI0.LPC0.FIGD._STA] \\ (Node 0xc3f6d160), AE_NOT_FOUND Often, you can resolve these problems by updating your BIOS to the latest revision. Most console messages are harmless but if you have other problems like battery status not working, they are a good place to start looking for problems in the AML. The bytecode, known as AML, is compiled from a source language called ASL. The AML is found in the table known as the DSDT. To get a copy of your ASL, use &man.acpidump.8;. You should use both the (show contents of the fixed tables) and (disassemble AML to ASL) options. See the Submitting Debugging Information section for an example syntax. The simplest first check you can do is to recompile your ASL to check for errors. Warnings can usually be ignored but errors are bugs that will usually prevent ACPI from working correctly. To recompile your ASL, issue the following command: &prompt.root; iasl your.asl Fixing Your <acronym>ASL</acronym> ACPI ASL In the long run, our goal is for almost everyone to have ACPI work without any user intervention. At this point, however, we are still developing workarounds for common mistakes made by the BIOS vendors. The µsoft; interpreter (acpi.sys and acpiec.sys) does not strictly check for adherence to the standard, and thus many BIOS vendors who only test ACPI under &windows; never fix their ASL. We hope to continue to identify and document exactly what non-standard behavior is allowed by µsoft;'s interpreter and replicate it so &os; can work without forcing users to fix the ASL. As a workaround and to help us identify behavior, you can fix the ASL manually. If this works for you, please send a &man.diff.1; of the old and new ASL so we can possibly work around the buggy behavior in ACPI-CA and thus make your fix unnecessary. ACPI error messages Here is a list of common error messages, their cause, and how to fix them: _OS dependencies Some AML assumes the world consists of various &windows; versions. You can tell &os; to claim it is any OS to see if this fixes problems you may have. An easy way to override this is to set hw.acpi.osname="Windows 2001" in /boot/loader.conf or other similar strings you find in the ASL. Missing Return statements Some methods do not explicitly return a value as the standard requires. While ACPI-CA does not handle this, &os; has a workaround that allows it to return the value implicitly. You can also add explicit Return statements where required if you know what value should be returned. To force iasl to compile the ASL, use the flag. Overriding the Default <acronym>AML</acronym> After you customize your.asl, you will want to compile it, run: &prompt.root; iasl your.asl You can add the flag to force creation of the AML, even if there are errors during compilation. Remember that some errors (e.g., missing Return statements) are automatically worked around by the interpreter. DSDT.aml is the default output filename for iasl. You can load this instead of your BIOS's buggy copy (which is still present in flash memory) by editing /boot/loader.conf as follows: acpi_dsdt_load="YES" acpi_dsdt_name="/boot/DSDT.aml" Be sure to copy your DSDT.aml to the /boot directory. Getting Debugging Output From <acronym>ACPI</acronym> ACPI problems ACPI debugging The ACPI driver has a very flexible debugging facility. It allows you to specify a set of subsystems as well as the level of verbosity. The subsystems you wish to debug are specified as layers and are broken down into ACPI-CA components (ACPI_ALL_COMPONENTS) and ACPI hardware support (ACPI_ALL_DRIVERS). The verbosity of debugging output is specified as the level and ranges from ACPI_LV_ERROR (just report errors) to ACPI_LV_VERBOSE (everything). The level is a bitmask so multiple options can be set at once, separated by spaces. In practice, you will want to use a serial console to log the output if it is so long it flushes the console message buffer. A full list of the individual layers and levels is found in the &man.acpi.4; manual page. Debugging output is not enabled by default. To enable it, add options ACPI_DEBUG to your kernel configuration file if ACPI is compiled into the kernel. You can add ACPI_DEBUG=1 to your /etc/make.conf to enable it globally. If it is a module, you can recompile just your acpi.ko module as follows: &prompt.root; cd /sys/modules/acpi/acpi && make clean && make ACPI_DEBUG=1 Install acpi.ko in /boot/kernel and add your desired level and layer to loader.conf. This example enables debug messages for all ACPI-CA components and all ACPI hardware drivers (CPU, LID, etc.) It will only output error messages, the least verbose level. debug.acpi.layer="ACPI_ALL_COMPONENTS ACPI_ALL_DRIVERS" debug.acpi.level="ACPI_LV_ERROR" If the information you want is triggered by a specific event (say, a suspend and then resume), you can leave out changes to loader.conf and instead use sysctl to specify the layer and level after booting and preparing your system for the specific event. The sysctls are named the same as the tunables in loader.conf. References More information about ACPI may be found in the following locations: The &a.acpi; The ACPI Mailing List Archives The old ACPI Mailing List Archives The ACPI 2.0 Specification &os; Manual pages: &man.acpi.4;, &man.acpi.thermal.4;, &man.acpidump.8;, &man.iasl.8;, &man.acpidb.8; DSDT debugging resource. (Uses Compaq as an example but generally useful.) diff --git a/zh_TW.Big5/books/handbook/introduction/chapter.sgml b/zh_TW.Big5/books/handbook/introduction/chapter.sgml index 060e0df5dd..e92bcf7ddf 100644 --- a/zh_TW.Big5/books/handbook/introduction/chapter.sgml +++ b/zh_TW.Big5/books/handbook/introduction/chapter.sgml @@ -1,795 +1,795 @@ Jim Mock Restructured, reorganized, and parts rewritten by 簡介 概述 非常感謝您對 FreeBSD 感興趣!以下章節涵蓋 FreeBSD 計劃的各方面:比如它的歷史、目標、開發模式等等。 讀完這章,您將了解︰ FreeBSD 與其他 OS 之間的關係; FreeBSD 計劃的歷史源流; FreeBSD 計劃的目標; FreeBSD open-source 開發模式的基礎概念; - 當然囉,還有 FreeBSD 這名字的緣故。 + 當然囉,還有 FreeBSD 這名字的由來。 Welcome to FreeBSD! 4.4BSD-Lite FreeBSD 是一個從 4.4BSD-Lite 衍生出而能在以 Intel (x86 and &itanium;), AMD64, Alpha, Sun &ultrasparc; 為基礎的電腦上執行的作業系統。同時,移植到其他平台的工作也在進行中。 對於本計劃歷史的介紹,請看 FreeBSD 歷史源流, 對於 FreeBSD 的最新版本介紹,請看 current release 。若打算對於 FreeBSD 計劃有所貢獻的話(像是程式碼硬體設備,資金), 請看 如何對 FreeBSD 有貢獻 FreeBSD 能做什麼? FreeBSD 提供給你許多先進功能。這些功能包括: 先佔式多工(preemptive multitasking) 動態優先權調整的『先佔式多工』能夠確保,即使在系統負擔很重的情況下, 程式執行平順並且應用程式與使用者公平地共享資源。 支援多人共用 『多人共用(multi-user)』代表著許多人可以同時使用一個 FreeBSD 系統來處理各自的事務。 系統的硬體周邊(如印表機及磁帶機)也可以讓所有的使用者適當地分享。 也可以針對各別使用者或一群使用者的系統資源,予以設限, 以保護系統不致被過度使用。 TCP/IP 網路功能 好用的『TCP/IP 網路功能』可支援許多業界標準,比如: SCTP、DHCP、NFS、NIS、PPP、SLIP 的支援,也就是說 FreeBSD 可以容易地跟其他作業系統透過網路共同運作,或是當作企業的伺服器用途 ,例如提供遠端檔案共享(NFS)及電子郵件(email)等服務, 或是讓您的企業連上網際網路(Internet)並提供 WWW、FTP、 路由(routing)、及防火牆(firewall、security) 等必備服務。 記憶體保護 『記憶體保護(Memory protection)』能確保程式(或是使用者)不會互相干擾, 即使任何程式有不正常的運作,都不會影響其他程式的執行。 FreeBSD 是『32位元(32-bit)』的作業系統 (在 Alpha、&itanium;、 AMD64 及 &ultrasparc; 上則是『64位元(64-bit)』) — 打從一開始便是這樣設計的。 X Window System XFree86 業界標準的『X Window 系統』(X11R6)可以在常見的便宜 VGA 顯示卡/螢幕, 提供了圖形化的使用者介面(GUI),並且包括了完整的原始程式碼。 binary compatibility Linux binary compatibility SCO binary compatibility SVR4 binary compatibility BSD/OS binary compatibility NetBSD 能『直接執行』許多其他作業系統(比如: Linux、SCO、SVR4、BSDI 和 NetBSD) 的可執行檔。 數以萬計的立即可以執行的應用程式,這些都可透過 FreeBSD 的『ports』及『packages』軟體管理機制來取得。 不再需要費心到網路上到處搜尋所需要的軟體。 此外,網路上尚有可非常容易移植的數以萬計應用程式。 FreeBSD 的原始程式碼與許多常見的商業版 &unix; 系統都相容, 所以大部分的程式都只需要很少的修改(或根本不用修改) ,就可以編譯執行。 virtual memory 需要時才置換(demand paged) virtual memorymerged VM/buffer cache 的設計, 這點在系統中有用去大量記憶體的程式執行時,仍然有不錯的效率表現。 Symmetric Multi-Processing (SMP) 支援 CPU 的對稱多工處理(SMP):可以支援多 CPU 的電腦系統。 compilers C compilers C++ compilers FORTRAN 完全相容的 CC++ 以及 Fortran 的環境和其他開發工具。 以及其他許多可供進階研發的程式語言也收集在 ports 和 packages。 source code 整個系統都有『原始程式碼』, 這讓你對作業環境擁有最完全的掌握度。 既然能擁有完全開放的系統,何苦被特定封閉軟體所約束,任廠商擺佈呢? 廣泛且豐富的『線上文件』。 當然囉,還不止如此! 4.4BSD-Lite Computer Systems Research Group (CSRG) U.C. Berkeley FreeBSD 系統乃是基於美國加州大學柏克萊分校的電腦系統研究群 (Computer Systems Research Group 也就是 CSRG) 所發行的 4.4BSD-Lite,以及基於 BSD 系統開發的優良傳統。 除了由 CSRG 所提供的高品質的成果, 為了提供可處理真正具負荷的工作, FreeBSD 計劃也投入了數千小時以上的細部調整, 以能獲得最好的執行效率以及系統的穩定度。 正當許多商業上的巨人正努力地希望能提供效能及穩定時, FreeBSD 已經具備這樣的特質 -- 就是現在 FreeBSD 的運用範圍無限,其實完全限制在你的想像力上。 從軟體的開發到工廠自動化,或是人造衛星上面的天線的方位角度的遠端控制; 這些功能若可以用商用的 Unix 產品來達成, 那麼極有可能使用 FreeBSD 也能辦到! FreeBSD 也受益於來自於全球各研究中心及大學所開發的數千個高品質的軟體 ,這些通常只需要花費很少的費用或根本就是免費的。 當然也有商業軟體,而且出現的數目是與日俱增。 由於每個人都可以取得 FreeBSD 的原始程式碼, 這個系統可以被調整而能執行任何原本完全無法想像的功能或計劃, 而對於從各廠商取得的作業系統通常沒有辦法這樣地被修改。 以下提供一些人們使用 FreeBSD 的例子: 網路服務: FreeBSD 內建強勁的網路功能使它成為網路服務(如下例)的理想平台: FTP servers 檔案伺服器(FTP servers) web servers 全球資訊網伺服器(WWW servers) (標準的或更安全的 SSL 連線) firewall IP masquerading 防火牆以及 NAT (IP masquerading) gateways。 electronic mail 電子郵件伺服器(Electronic Mail servers) USENET 網路新聞伺服器(USENET News) 或是電子佈告欄系統(BBS) 還有更多... 有了 FreeBSD,您可以容易地先用便宜的 386 PC, 再逐步升級您的機器到四個 CPU 的 Xeon 並使用磁碟陣列(RAID)來滿足您企業運用上的需求。 教育: 如果你是資訊或相關工程領域的學生,再也沒有比使用 FreeBSD 能學到更多作業系統、計算機結構、及網路的方法了。 另外如果你想利用電腦來處理一些其他的 工作,還有一些如 CAD、 數學運算以及圖形處理軟體等可以免費地取得使用。 研究:有了完整的原始程式碼,FreeBSD 是研究作業系統及電腦科學的極佳環境。 具有免費且自由取得特性的 FreeBSD 也使得一個分置兩地的合作計劃,不必擔心版權及系統開放性的問題, 而能自在的交流。 router DNS Server 網路: 你如果需要 router、Name Server (DNS) 或安全的防火牆(Firewall), FreeBSD 可以輕易的將你沒有用到的 386 或 486 PC 變身成為絕佳的伺服器,甚至具有過濾封包(packet-filter) 的功能。 X Window System XFree86 X Window System Accelerated-X X 視窗工作站: FreeBSD 是 X 終端機的良策,你可以使用免費的 X11 Server。 FreeBSD 不但可以充當遠端 X 程式終端機, 也可以執行本地的 X 程式而減輕大型工作站的負荷。 如果有一台中央伺服器的話,FreeBSD 甚至可以經由網路開機 (不需硬碟,也就是diskless) ,而變成更便宜且易於管理的工作站。 GNU Compiler Collection 軟體開發: 基本安裝的 FreeBSD 就包含了完整的程式開發工具,如 GNU C/C++ 編譯器及除錯器。 你可以經由燒錄 CDROM、DVD 或是從 FTP 站上抓回 FreeBSD -- 包括立即可執行的系統以及系統的完整程式碼。 詳情請參閱 取得 FreeBSD。 誰在用 FreeBSD? users large sites running FreeBSD 許多 Internet 上的大型網站都是以 FreeBSD 作為它的作業系統,例如: Yahoo! Yahoo! Apache Apache Blue Mountain Arts Blue Mountain Arts Pair Networks Pair Networks Sony Japan Sony Japan Netcraft Netcraft Weathernews Weathernews Supervalu Supervalu TELEHOUSE America TELEHOUSE America Sophos Anti-Virus Sophos Anti-Virus JMA Wired JMA Wired 以及許多其他的網站。 關於 FreeBSD 計劃 接下來講的是 FreeBSD 計劃的背景,包含歷史源流的簡介、計劃的目標,以及開發的模式。 Jordan Hubbard Contributed by FreeBSD 歷史源流的簡介 386BSD Patchkit Hubbard, Jordan Williams, Nate Grimes, Rod FreeBSD Project history FreeBSD 計畫的想法是在 1993 年初所形成的, 那是源自於維護一組 『非官方 386BSD 的 patchkit(修正工具)』計劃的三個協調維護人 Nate Williams,Rod Grimes 和我(Jordan Hubbard)。 386BSD 我們最初的目標是做出一份 386BSD 綜合修正的 snapshot 版,以便修正當時一堆 patchkit 都不容易解決的問題。有些人可能還記得早期的計劃名稱叫做 386BSD 0.5386BSD Interim 就是這個原因。 Jolitz, Bill 386BSD 是 Bill Jolitz 的作業系統,在當時就已有約一年的分裂討論。 當該修正工具 (patchkit) 日漸龐雜得令人不舒服,我們無異議地同意要作一些事了, 並決定提供一份臨時性的 淨化版(cleanup) 來幫助 Bill。 然而,由於 Bill Jolitz 忽然決定取消其對該計劃的認可,且沒有明確指出未來的打算, 所以該計劃便突然面臨斷炊危機。 Greenman, David Walnut Creek CDROM 不久我們便決定在即使沒有 Bill 的支持下,讓該計劃仍然繼續下去, 最後我們採用 David Greenman 丟銅板決定的名字,也就是『FreeBSD』。 在詢問了當時的一些使用者意見之後,就開始決定了最初的目標, 當該計劃開始實施一切就要成真時,一切就變得更清楚了。 我跟 Walnut Creek CDROM 討論發行 CDROM 這樣子不便上網的人就可以用比較簡單的方式取得 FreeBSD。 Walnut Creek CDROM 不只贊成以 CDROM 來發行 FreeBSD 的想法,同時提供了一台機器以及快速的網際網路的頻寬。 如果不是 Walnut Creek CDROM 幾乎是空前的信任這個剛開始還是完全默默無聞的計劃, 那麼很可能 FreeBSD 不會如此快速的成長到今日這樣的規模。 4.3BSD-Lite Net/2 U.C. Berkeley 386BSD Free Software Foundation 第一張以 CDROM (及網路)發行的 FreeBSD 1.0 是在 1993 年十二月。 該版本是基於由 U.C. Berkeley 以磁帶方式發行的 4.3BSD-Lite (Net/2)以及許多來自於 386BSD 和自由軟體基金會的軟體。對於第一次發行而言還算成功, 我們又接著於 1994 年 5 月發行了相當成功的 FreeBSD 1.1。 Novell U.C. Berkeley Net/2 AT&T 然而此後不久,另一個意外的風暴在 Novell 和 U.C. Berkeley 關於 Berkeley Net/2 磁帶之法律地位的訴訟確定之後形成。 U.C. Berkeley 接受大部份的 Net/2 的程式碼都是『侵佔來的』且是屬於 Novell 的財產 -- 事實上是當時不久前從 AT&T 取得的。 Berkeley 得到的是 Novell 對於 4.4BSD-Lite 的『祝福』,最後當 4.4BSD-Lite 終於發行之後,便不再是侵佔行為。 而所有現有 Net/2 使用者都被強烈建議更換新版本,這包括了 FreeBSD。 於是,我們被要求於 1994 年 6 月底前停止散佈基於 Net/2 的產品。在此前提之下,本計劃被允許在期限以前作最後一次發行,也就是 FreeBSD 1.1.5.1。 FreeBSD 便開始了這宛如『重新發明輪子』的艱鉅工作 -- 從全新的且不完整的 4.4BSD-Lite 重新整合。 這個 Lite 版本是不完整的,因為 Berkeley 的 CSRG 已經刪除了大量在建立一個可以開機執行的系統所需要的程式碼 (基於若干法律上的要求),且該版本在 Intel 平台的移植是非常不完整的。 直到 1994 年 11 月本計劃才完成了這個轉移, 同時在該年 12 月底以 CDROM 以及網路的形式發行了 FreeBSD 2.0。 雖然該份版本在當時有點匆促粗糙,但仍是富有意義的成功。 隨之於 1995 年 6 月又發行了更容易安裝,更好的 FreeBSD 2.0.5。 我們在 1996 年 8 月發行了 FreeBSD 2.1.5,在 ISP 和商業團體中非常流行。 隨後, 2.1-STABLE 分支的另一個版本應運而生,它就是在 1997 年 2 月發行 FreeBSD 2.1.7.1 ,同時也是 2.1-STABLE 分支的最後版。之後此分支便進入維護狀態, 僅僅提供安全性的加強和其他嚴重錯誤修補的維護(RELENG_2_1_0)。 1996 年 11 月 FreeBSD 2.2 從開發主軸分支 (-CURRENT) 出來成為 RELENG_2_2 分支。它的第一個完整版(2.2.1)於 1997 年 4 月發行。 2.2 分支的延續版本在 97 年夏秋之間發行的,其最後版是在 1998 年 11 月發行的 2.2.8 版。 第一個正式的 3.0 版本在 1998 年 10 月發行,亦即宣告 2.2 分支的落幕。 1999/01/20 日再度分支,這產生了 4.0-CURRENT 以及 3.X-STABLE 兩個分支。 3.X-STABLE 方面,3.1 發行於 1999/02/15,3.2 發行於1999/05/15,3.3 發行於 1999/09/16, 3.4 發行於 1999/12/20,3.5 發行於 2000/06/24 ,接下來幾天後發佈了一些的修補檔(對 Kerberos 安全性方面的修正),就升級至 3.5.1 ,這是 3.X 分支最後一個發行版本。 在 2000/03/13 又有了一個新的分支, 也就是 4.X-STABLE 。這個分支之後發佈了許多的發行版本︰ 4.0-RELEASE 在 2000 年 3 月發行, 而最後的 4.11-RELEASE 則在 2005 年 1 月發行。4-STABLE 分支的支援會持續到 2007/01/31 ,但主要焦點在於安全方面的漏洞、臭蟲及其他嚴重問題的修補。 期待已久的 5.0-RELEASE 在 2003/01/19 正式發行。這是將近開發三年的巔峰之作,同時 也開始加強多顆CPU(SMPng)的支援、kernel thread(KSE) 的支援、檔案系統採用 UFS2 以及支援 snapshot 等, 並支援 &ultrasparc; 和 ia64 平台、支援藍牙、32 bit 的 PCMCIA 等。之後於 2003 年 6 月發行了 5.1。 而 -CURRENT 這個發展主軸分支的最後 5.X 版本是在 2004 年 2 月正式發行的 5.2.1-RELEASE,在 5.X 系列進入 -STABLE (RELENG_5分支)之後,-CURRENT 就轉移為 6.X 系列。 RELENG_5 分支於 2004 年 8 月正式開跑,之後是 5.3-RELEASE ,它是 5-STABLE 分支的第一個發行版本。&rel2.current;-RELEASE 的最新發表是在 &rel2.current.date; 發行的 &rel2.current;-RELEASE,照往例 RELENG_5 分支還將有後續的發行版。 RELENG_6 分支於 2005 年 7 月開跑,而 6.X 分支的第一個 release(6.0-RELEASE) 是在 2005 年 11 月出的。 最新的 &rel.current;-RELEASE 是在 &rel.current.date; 發行。當然囉,RELENG_6 分支還將有後續的發行版。 目前,長期的開發計畫繼續在 7.X-CURRENT (trunk) 分支中進行,而 7.X 的 CDROM (當然,也可以用網路抓) snapshot 版本可以在 FreeBSD snapshot server 取得。 Jordan Hubbard Contributed by FreeBSD 計劃的目標 FreeBSD Project goals FreeBSD 計劃的目標在於提供可作任意用途的軟體而不附帶任何限制條文。 我們之中許多人對程式碼 (以及計畫本身) 都有非常大的投入, 因此,當然不介意偶爾有一些資金上的補償,但我們並沒打算堅決地要求得到這類資助。 我們認為我們的首要『使命(mission)』是為任何人提供程式碼, 不管他們打算用這些程式碼做什麼, 因為這樣程式碼將能夠被更廣泛地使用,從而發揮其價值。 我認為這是自由軟體最基本的,同時也是我們所倡導的一個目標。 GNU General Public License (GPL) GNU Lesser General Public License (LGPL) BSD Copyright 我們程式碼樹中,有若干是以 GNU GPL 或者 LGPL 發佈的那些程式碼帶有少許的附加限制,還好只是強制性的要求開放程式碼而不是別的。 由於使用 GPL 的軟體在商業用途上會增加若干複雜性,因此,如果可以選擇的話, 我們會比較喜歡使用限制相對更寬鬆的 BSD 版權來發佈軟體。 Satoshi Asami Contributed by FreeBSD 的開發模式 FreeBSD Project development model FreeBSD 的開發是一個非常開放且具彈性的過程,就像從 貢獻者名單 所看到的,是由全世界成千上萬的貢獻者發展起來的。 FreeBSD 的開發基礎架構允許數以百計的開發者透過網際網路協同工作。 我們也經常關注著那些對我們的計畫感興趣的新開發者和新的創意, 那些有興趣更進一步參與計劃的人只需要在 &a.hackers; 連繫我們。 &a.announce; 對那些希望了解我們進度的人也是相當有用的。 無論是單獨開發者或者封閉式的團隊合作,多瞭解 FreeBSD 計劃和它的開發過程會是不錯的︰ The CVS repository CVS repository Concurrent Versions System CVS FreeBSD 的中央 source tree 是以 CVS (Concurrent Versions System) 來維護的,它是個自由軟體,可用來做為版本控制,一裝完 FreeBSD 內就有附了。 最主要的 CVS repository 是位於美國加州 Santa Clara 的某台機器上, 然後再 mirror 到世界上其他的許多機器上。CVS tree 內有兩個主分支:-CURRENT 以及 -STABLE ,這些都可輕鬆複製到自己機器上。 詳情請參閱 更新你的 source tree 一節。 The committers list committers 所謂的 committers 指的是對 CVS tree 有 write 權限, 並依不同授權部分,而有不同權限可修改 FreeBSD source。 (committer 這詞源自 &man.cvs.1; 中的 commit 指令,該指令是用來把新的修改提交給 CVS repository。) 而提交修改給 committer 們檢查的最好方式,就是用 &man.send-pr.1; 指令。 若提交 PR 的流程、系統上有壅塞現象的話,也可以改用寄信方式,寄信到 &a.committers; 即可。 The FreeBSD core team core team 如果把 FreeBSD 看成是一家公司的話,FreeBSD core team 就相當於『董事會(board of directors)』。 core team 的主要職責在於確保此計劃有良好的架構,以朝著正確的方向發展。 此外,邀請熱血且負責的軟體開發者加入 committers 行列,以在若干成員離去時得以補充新血。 目前的 core team 是在 2006 年 7 月 committers 候選人中選出來的,每兩年會舉辦一次選舉 有些 core team 成員還負責某些特定範圍,也就是說他們必須盡量確保一些子系統的穩定、效能。 關於 FreeBSD 開發者們以及各自責任範圍,請參閱 貢獻者名單 core team 大部分成員加入 FreeBSD 開發都是志工性質而已,並未從本計劃中獲得任何薪酬, 所以不該把 commitment 誤解為 guaranteed support 才對。 剛前面所講的『董事會』可能是不恰當的類推,或許我們應該說: 他們是一群自願放棄原本的優渥生活、個人其他領域成就,而選擇投入 FreeBSD 開發的熱血有為者才對! 其他的貢獻者 contributors 最後一點,但這點絕非最不重要的,最大的開發者團隊就是持續為我們提供回饋以及錯誤修正的使用者自己。 與 FreeBSD 非核心開發者互動的主要方式,便是透過訂閱 &a.hackers; 來進行溝通, 這方面可參考,請參閱 以瞭解各式不同的 FreeBSD 郵遞論壇(mailing lists)。 FreeBSD 貢獻者名單 相當長且不斷成長中,只要有貢獻就會被列入其中,要不要立即考慮貢獻 FreeBSD 一些回饋呢? 然而,提供原始碼並非為這個計劃做貢獻的唯一方式; 還需要大家投入的完整工作列表、說明,請參閱 FreeBSD 官網 簡單的說,我們的開發模式就像是一組沒有拘束的同心圓。 這種集中開發模式是以 給使用者方便 為主, 同時讓他們能很容易地共同維護軟體,而不會把潛在的貢獻者排除在外! 我們的目標是提供含有大量一致性的 應用軟體(ports/packages) ,以便讓使用者輕鬆安裝、使用的作業系統 —— 而這開發模式相當符合此一目標。 我們對於那些想要加入 FreeBSD 開發者的期待是:請保持如同前人一樣的投入,以確保繼續成功! 最新的 FreeBSD 發行版本 NetBSD OpenBSD 386BSD Free Software Foundation U.C. Berkeley Computer Systems Research Group (CSRG) FreeBSD 是免費使用且帶有完整原始程式碼的以 4.4BSD-Lite 為基礎的系統,可以在 Intel &i386;, &i486;, &pentium;, &pentium; Pro, &celeron;, &pentium; II, &pentium; III, &pentium; 4 (或者相容型號), &xeon;, DEC Alpha 和 Sun &ultrasparc; 為基礎的電腦上執行的作業系統。 它主要以加州大學巴爾克利分校 的 CSRG 研究小組的軟體為基礎,並加入了 NetBSD、OpenBSD、386BSD 以及自由軟體基金會的一些東西。 自從 1994 年末,我們發佈了 FreeBSD 2.0 之後,系統的執行效率、 功能、穩定性都有了令人注目的提升。 最大的改變就是我們將記憶體與檔案系統的 cache 機制結合在一起。 這不只使得系統的表現變得更好, 並且使得 FreeBSD 系統最少的記憶體需求減少到 5 MB。 其它的改進包括完整的 NIS cilent and server 功能支援, 支援 transaction TCP、PPP 撥接連線、整合的 DHCP 支援、 SCSI 子系統的改進、ISDN 的支援,ATM、FDDI 以及乙太網路 (Ethernet、包括 100 Mbit 和 Gigabit) 的支援,提升了最新的 Adaptec 控制卡驅動程式的改善,以及數以千計的 bug 修正。 除了最基本的系統軟體,FreeBSD 還提供了廣受歡迎的套件軟體管理機制: Ports Collection。 到本書付印時,已有超過 &os.numports; 個 ports,這範疇涵蓋從 http(WWW) 伺服器到遊戲、程式語言、編輯器以及您能想到的幾乎所有的東西。 完整的 Ports Collection 需要約 &ports.size; 的硬碟空間,除了 port 基本架構檔案外,都只儲存與該 port 軟體的原始碼有『須要變更』的部份。 如此一來,我們可以更容易更新這些 ports, 也大量的減少如舊的 1.0 版 Ports Collection 對於硬碟空間的需求。 要安裝一個 port 的話,只需要進入該 port 的目錄,輸入 make install ,這樣子系統就會幫你裝好了。您要編譯的每個程式的完整原始程式, 都可從 FTP 或 CDROM 中獲得,所以您只需準備足夠的硬碟空間來編譯你要的 port 軟體。 幾乎每一個 port 都有已事先編譯好的 package以方便安裝, 如果不想從編譯 port 的人,只要用個簡單指令(pkg_add)就可以安裝。 有關 packages 和 ports 的細節,可以參閱 FreeBSD 主機的 /usr/share/doc 目錄下找到許多有用的文件, 來幫助您安裝、使用 FreeBSD。也可以使用下面的網址,以瀏覽器來翻閱本機上安裝的手冊︰ FreeBSD 使用手冊 /usr/share/doc/handbook/index.html FreeBSD 常見問答集 /usr/share/doc/faq/index.html 此外,可在下列網址找到最新版 (也是更新最頻繁的版本): diff --git a/zh_TW.Big5/books/handbook/mail/chapter.sgml b/zh_TW.Big5/books/handbook/mail/chapter.sgml index b51cda2784..2937d5bacd 100644 --- a/zh_TW.Big5/books/handbook/mail/chapter.sgml +++ b/zh_TW.Big5/books/handbook/mail/chapter.sgml @@ -1,2324 +1,2324 @@ Bill Lloyd Original work by Jim Mock Rewritten by - Electronic Mail + 電子郵件 - Synopsis + 概述 email Electronic Mail, better known as email, is one of the most widely used forms of communication today. This chapter provides a basic introduction to running a mail server on &os;, as well as an introduction to sending and receiving email using &os;; however, it is not a complete reference and in fact many important considerations are omitted. For more complete coverage of the subject, the reader is referred to the many excellent books listed in . After reading this chapter, you will know: What software components are involved in sending and receiving electronic mail. Where basic sendmail configuration files are located in FreeBSD. The difference between remote and local mailboxes. How to block spammers from illegally using your mail server as a relay. How to install and configure an alternate Mail Transfer Agent on your system, replacing sendmail. How to troubleshoot common mail server problems. How to use SMTP with UUCP. How to set up the system to send mail only. How to use mail with a dialup connection. How to configure SMTP Authentication for added security. How to install and use a Mail User Agent, such as mutt to send and receive email. How to download your mail from a remote POP or IMAP server. How to automatically apply filters and rules to incoming email. Before reading this chapter, you should: Properly set up your network connection (). Properly set up the DNS information for your mail host (). Know how to install additional third-party software (). Using Electronic Mail POP IMAP DNS There are five major parts involved in an email exchange. They are: the user program, the server daemon, DNS, a remote or local mailbox, and of course, the mailhost itself. The User Program This includes command line programs such as mutt, pine, elm, and mail, and GUI programs such as balsa, xfmail to name a few, and something more sophisticated like a WWW browser. These programs simply pass off the email transactions to the local mailhost, either by calling one of the server daemons available, or delivering it over TCP. Mailhost Server Daemon mail server daemons sendmail mail server daemons postfix mail server daemons qmail mail server daemons exim &os; ships with sendmail by default, but also support numerous other mail server daemons, just some of which include: exim; postfix; qmail. The server daemon usually has two functions—it is responsible for receiving incoming mail as well as delivering outgoing mail. It is not responsible for the collection of mail using protocols such as POP or IMAP to read your email, nor does it allow connecting to local mbox or Maildir mailboxes. You may require an additional daemon for that. Older versions of sendmail have some serious security issues which may result in an attacker gaining local and/or remote access to your machine. Make sure that you are running a current version to avoid these problems. Optionally, install an alternative MTA from the &os; Ports Collection. Email and DNS The Domain Name System (DNS) and its daemon named play a large role in the delivery of email. In order to deliver mail from your site to another, the server daemon will look up the remote site in the DNS to determine the host that will receive mail for the destination. This process also occurs when mail is sent from a remote host to your mail server. MX record DNS is responsible for mapping hostnames to IP addresses, as well as for storing information specific to mail delivery, known as MX records. The MX (Mail eXchanger) record specifies which host, or hosts, will receive mail for a particular domain. If you do not have an MX record for your hostname or domain, the mail will be delivered directly to your host provided you have an A record pointing your hostname to your IP address. You may view the MX records for any domain by using the &man.host.1; command, as seen in the example below: &prompt.user; host -t mx FreeBSD.org FreeBSD.org mail is handled (pri=10) by mx1.FreeBSD.org Receiving Mail email receiving Receiving mail for your domain is done by the mail host. It will collect all mail sent to your domain and store it either in mbox (the default method for storing mail) or Maildir format, depending on your configuration. Once mail has been stored, it may either be read locally using applications such as &man.mail.1; or mutt, or remotely accessed and collected using protocols such as POP or IMAP. This means that should you only wish to read mail locally, you are not required to install a POP or IMAP server. Accessing remote mailboxes using <acronym>POP</acronym> and <acronym>IMAP</acronym> POP IMAP In order to access mailboxes remotely, you are required to have access to a POP or IMAP server. These protocols allow users to connect to their mailboxes from remote locations with ease. Though both POP and IMAP allow users to remotely access mailboxes, IMAP offers many advantages, some of which are: IMAP can store messages on a remote server as well as fetch them. IMAP supports concurrent updates. IMAP can be extremely useful over low-speed links as it allows users to fetch the structure of messages without downloading them; it can also perform tasks such as searching on the server in order to minimize data transfer between clients and servers. In order to install a POP or IMAP server, the following steps should be performed: Choose an IMAP or POP server that best suits your needs. The following POP and IMAP servers are well known and serve as some good examples: qpopper; teapop; imap-uw; courier-imap; Install the POP or IMAP daemon of your choosing from the ports collection. Where required, modify /etc/inetd.conf to load the POP or IMAP server. It should be noted that both POP and IMAP transmit information, including username and password credentials in clear-text. This means that if you wish to secure the transmission of information across these protocols, you should consider tunneling sessions over &man.ssh.1;. Tunneling sessions is described in . Accessing local mailboxes Mailboxes may be accessed locally by directly utilizing MUAs on the server on which the mailbox resides. This can be done using applications such as mutt or &man.mail.1;. The Mail Host mail host The mail host is the name given to a server that is responsible for delivering and receiving mail for your host, and possibly your network. Christopher Shumway Contributed by <application>sendmail</application> Configuration sendmail &man.sendmail.8; is the default Mail Transfer Agent (MTA) in FreeBSD. sendmail's job is to accept mail from Mail User Agents (MUA) and deliver it to the appropriate mailer as defined by its configuration file. sendmail can also accept network connections and deliver mail to local mailboxes or deliver it to another program. sendmail uses the following configuration files: /etc/mail/access /etc/mail/aliases /etc/mail/local-host-names /etc/mail/mailer.conf /etc/mail/mailertable /etc/mail/sendmail.cf /etc/mail/virtusertable Filename Function /etc/mail/access sendmail access database file /etc/mail/aliases Mailbox aliases /etc/mail/local-host-names Lists of hosts sendmail accepts mail for /etc/mail/mailer.conf Mailer program configuration /etc/mail/mailertable Mailer delivery table /etc/mail/sendmail.cf sendmail master configuration file /etc/mail/virtusertable Virtual users and domain tables <filename>/etc/mail/access</filename> The access database defines what host(s) or IP addresses have access to the local mail server and what kind of access they have. Hosts can be listed as , , or simply passed to sendmail's error handling routine with a given mailer error. Hosts that are listed as , which is the default, are allowed to send mail to this host as long as the mail's final destination is the local machine. Hosts that are listed as are rejected for all mail connections. Hosts that have the option for their hostname are allowed to send mail for any destination through this mail server. Configuring the <application>sendmail</application> Access Database cyberspammer.com 550 We do not accept mail from spammers FREE.STEALTH.MAILER@ 550 We do not accept mail from spammers another.source.of.spam REJECT okay.cyberspammer.com OK 128.32 RELAY In this example we have five entries. Mail senders that match the left hand side of the table are affected by the action on the right side of the table. The first two examples give an error code to sendmail's error handling routine. The message is printed to the remote host when a mail matches the left hand side of the table. The next entry rejects mail from a specific host on the Internet, another.source.of.spam. The next entry accepts mail connections from a host okay.cyberspammer.com, which is more exact than the cyberspammer.com line above. More specific matches override less exact matches. The last entry allows relaying of electronic mail from hosts with an IP address that begins with 128.32. These hosts would be able to send mail through this mail server that are destined for other mail servers. When this file is updated, you need to run make in /etc/mail/ to update the database. <filename>/etc/mail/aliases</filename> The aliases database contains a list of virtual mailboxes that are expanded to other user(s), files, programs or other aliases. Here are a few examples that can be used in /etc/mail/aliases: Mail Aliases root: localuser ftp-bugs: joe,eric,paul bit.bucket: /dev/null procmail: "|/usr/local/bin/procmail" The file format is simple; the mailbox name on the left side of the colon is expanded to the target(s) on the right. The first example simply expands the mailbox root to the mailbox localuser, which is then looked up again in the aliases database. If no match is found, then the message is delivered to the local user localuser. The next example shows a mail list. Mail to the mailbox ftp-bugs is expanded to the three local mailboxes joe, eric, and paul. Note that a remote mailbox could be specified as user@example.com. The next example shows writing mail to a file, in this case /dev/null. The last example shows sending mail to a program, in this case the mail message is written to the standard input of /usr/local/bin/procmail through a &unix; pipe. When this file is updated, you need to run make in /etc/mail/ to update the database. <filename>/etc/mail/local-host-names</filename> This is a list of hostnames &man.sendmail.8; is to accept as the local host name. Place any domains or hosts that sendmail is to be receiving mail for. For example, if this mail server was to accept mail for the domain example.com and the host mail.example.com, its local-host-names might look something like this: example.com mail.example.com When this file is updated, &man.sendmail.8; needs to be restarted to read the changes. <filename>/etc/mail/sendmail.cf</filename> sendmail's master configuration file, sendmail.cf controls the overall behavior of sendmail, including everything from rewriting e-mail addresses to printing rejection messages to remote mail servers. Naturally, with such a diverse role, this configuration file is quite complex and its details are a bit out of the scope of this section. Fortunately, this file rarely needs to be changed for standard mail servers. The master sendmail configuration file can be built from &man.m4.1; macros that define the features and behavior of sendmail. Please see /usr/src/contrib/sendmail/cf/README for some of the details. When changes to this file are made, sendmail needs to be restarted for the changes to take effect. <filename>/etc/mail/virtusertable</filename> The virtusertable maps mail addresses for virtual domains and mailboxes to real mailboxes. These mailboxes can be local, remote, aliases defined in /etc/mail/aliases or files. Example Virtual Domain Mail Map root@example.com root postmaster@example.com postmaster@noc.example.net @example.com joe In the above example, we have a mapping for a domain example.com. This file is processed in a first match order down the file. The first item maps root@example.com to the local mailbox root. The next entry maps postmaster@example.com to the mailbox postmaster on the host noc.example.net. Finally, if nothing from example.com has matched so far, it will match the last mapping, which matches every other mail message addressed to someone at example.com. This will be mapped to the local mailbox joe. Andrew Boothman Written by Gregory Neil Shapiro Information taken from e-mails written by Changing Your Mail Transfer Agent email change mta As already mentioned, FreeBSD comes with sendmail already installed as your MTA (Mail Transfer Agent). Therefore by default it is in charge of your outgoing and incoming mail. However, for a variety of reasons, some system administrators want to change their system's MTA. These reasons range from simply wanting to try out another MTA to needing a specific feature or package which relies on another mailer. Fortunately, whatever the reason, FreeBSD makes it easy to make the change. Install a New MTA You have a wide choice of MTAs available. A good starting point is the FreeBSD Ports Collection where you will be able to find many. Of course you are free to use any MTA you want from any location, as long as you can make it run under FreeBSD. Start by installing your new MTA. Once it is installed it gives you a chance to decide if it really fulfills your needs, and also gives you the opportunity to configure your new software before getting it to take over from sendmail. When doing this, you should be sure that installing the new software will not attempt to overwrite system binaries such as /usr/bin/sendmail. Otherwise, your new mail software has essentially been put into service before you have configured it. Please refer to your chosen MTA's documentation for information on how to configure the software you have chosen. Disable <application>sendmail</application> The procedure used to start sendmail changed significantly between 4.5-RELEASE, 4.6-RELEASE, and later releases. Therefore, the procedure used to disable it is subtly different. If you disable sendmail's outgoing mail service, it is important that you replace it with an alternative mail delivery system. If you choose not to, system functions such as &man.periodic.8; will be unable to deliver their results by e-mail as they would normally expect to. Many parts of your system may expect to have a functional sendmail-compatible system. If applications continue to use sendmail's binaries to try to send e-mail after you have disabled them, mail could go into an inactive sendmail queue, and never be delivered. FreeBSD 4.5-STABLE before 2002/4/4 and Earlier (Including 4.5-RELEASE and Earlier) Enter: sendmail_enable="NO" into /etc/rc.conf. This will disable sendmail's incoming mail service, but if /etc/mail/mailer.conf (see below) is not changed, sendmail will still be used to send e-mail. FreeBSD 4.5-STABLE after 2002/4/4 (Including 4.6-RELEASE and Later) In order to completely disable sendmail, including the outgoing mail service, you must use sendmail_enable="NONE" in /etc/rc.conf. If you only want to disable sendmail's incoming mail service, you should set sendmail_enable="NO" in /etc/rc.conf. However, if incoming mail is disabled, local delivery will still function. More information on sendmail's startup options is available from the &man.rc.sendmail.8; manual page. FreeBSD 5.0-STABLE and Later In order to completely disable sendmail, including the outgoing mail service, you must use sendmail_enable="NO" sendmail_submit_enable="NO" sendmail_outbound_enable="NO" sendmail_msp_queue_enable="NO" in /etc/rc.conf. If you only want to disable sendmail's incoming mail service, you should set sendmail_enable="NO" in /etc/rc.conf. More information on sendmail's startup options is available from the &man.rc.sendmail.8; manual page. Running Your New MTA on Boot You may have a choice of two methods for running your new MTA on boot, again depending on what version of FreeBSD you are running. FreeBSD 4.5-STABLE before 2002/4/11 (Including 4.5-RELEASE and Earlier) Add a script to /usr/local/etc/rc.d/ that ends in .sh and is executable by root. The script should accept start and stop parameters. At startup time the system scripts will execute the command /usr/local/etc/rc.d/supermailer.sh start which you can also use to manually start the server. At shutdown time, the system scripts will use the stop option, running the command /usr/local/etc/rc.d/supermailer.sh stop which you can also use to manually stop the server while the system is running. FreeBSD 4.5-STABLE after 2002/4/11 (Including 4.6-RELEASE and Later) With later versions of FreeBSD, you can use the above method or you can set mta_start_script="filename" in /etc/rc.conf, where filename is the name of some script that you want executed at boot to start your MTA. Replacing <application>sendmail</application> as the System's Default Mailer The program sendmail is so ubiquitous as standard software on &unix; systems that some software just assumes it is already installed and configured. For this reason, many alternative MTA's provide their own compatible implementations of the sendmail command-line interface; this facilitates using them as drop-in replacements for sendmail. Therefore, if you are using an alternative mailer, you will need to make sure that software trying to execute standard sendmail binaries such as /usr/bin/sendmail actually executes your chosen mailer instead. Fortunately, FreeBSD provides a system called &man.mailwrapper.8; that does this job for you. When sendmail is operating as installed, you will find something like the following in /etc/mail/mailer.conf: sendmail /usr/libexec/sendmail/sendmail send-mail /usr/libexec/sendmail/sendmail mailq /usr/libexec/sendmail/sendmail newaliases /usr/libexec/sendmail/sendmail hoststat /usr/libexec/sendmail/sendmail purgestat /usr/libexec/sendmail/sendmail This means that when any of these common commands (such as sendmail itself) are run, the system actually invokes a copy of mailwrapper named sendmail, which checks mailer.conf and executes /usr/libexec/sendmail/sendmail instead. This system makes it easy to change what binaries are actually executed when these default sendmail functions are invoked. Therefore if you wanted /usr/local/supermailer/bin/sendmail-compat to be run instead of sendmail, you could change /etc/mail/mailer.conf to read: sendmail /usr/local/supermailer/bin/sendmail-compat send-mail /usr/local/supermailer/bin/sendmail-compat mailq /usr/local/supermailer/bin/mailq-compat newaliases /usr/local/supermailer/bin/newaliases-compat hoststat /usr/local/supermailer/bin/hoststat-compat purgestat /usr/local/supermailer/bin/purgestat-compat Finishing Once you have everything configured the way you want it, you should either kill the sendmail processes that you no longer need and start the processes belonging to your new software, or simply reboot. Rebooting will also give you the opportunity to ensure that you have correctly configured your system to start your new MTA automatically on boot. Troubleshooting email troubleshooting Why do I have to use the FQDN for hosts on my site? You will probably find that the host is actually in a different domain; for example, if you are in foo.bar.edu and you wish to reach a host called mumble in the bar.edu domain, you will have to refer to it by the fully-qualified domain name, mumble.bar.edu, instead of just mumble. BIND Traditionally, this was allowed by BSD BIND resolvers. However the current version of BIND that ships with FreeBSD no longer provides default abbreviations for non-fully qualified domain names other than the domain you are in. So an unqualified host mumble must either be found as mumble.foo.bar.edu, or it will be searched for in the root domain. This is different from the previous behavior, where the search continued across mumble.bar.edu, and mumble.edu. Have a look at RFC 1535 for why this was considered bad practice, or even a security hole. As a good workaround, you can place the line: search foo.bar.edu bar.edu instead of the previous: domain foo.bar.edu into your /etc/resolv.conf. However, make sure that the search order does not go beyond the boundary between local and public administration, as RFC 1535 calls it. MX record sendmail says mail loops back to myself This is answered in the sendmail FAQ as follows: I'm getting these error messages: 553 MX list for domain.net points back to relay.domain.net 554 <user@domain.net>... Local configuration error How can I solve this problem? You have asked mail to the domain (e.g., domain.net) to be forwarded to a specific host (in this case, relay.domain.net) by using an MX record, but the relay machine does not recognize itself as domain.net. Add domain.net to /etc/mail/local-host-names [known as /etc/sendmail.cw prior to version 8.10] (if you are using FEATURE(use_cw_file)) or add Cw domain.net to /etc/mail/sendmail.cf. The sendmail FAQ can be found at and is recommended reading if you want to do any tweaking of your mail setup. PPP How can I run a mail server on a dial-up PPP host? You want to connect a FreeBSD box on a LAN to the Internet. The FreeBSD box will be a mail gateway for the LAN. The PPP connection is non-dedicated. UUCP MX record There are at least two ways to do this. One way is to use UUCP. Another way is to get a full-time Internet server to provide secondary MX services for your domain. For example, if your company's domain is example.com and your Internet service provider has set example.net up to provide secondary MX services to your domain: example.com. MX 10 example.com. MX 20 example.net. Only one host should be specified as the final recipient (add Cw example.com in /etc/mail/sendmail.cf on example.com). When the sending sendmail is trying to deliver the mail it will try to connect to you (example.com) over the modem link. It will most likely time out because you are not online. The program sendmail will automatically deliver it to the secondary MX site, i.e. your Internet provider (example.net). The secondary MX site will then periodically try to connect to your host and deliver the mail to the primary MX host (example.com). You might want to use something like this as a login script: #!/bin/sh # Put me in /usr/local/bin/pppmyisp ( sleep 60 ; /usr/sbin/sendmail -q ) & /usr/sbin/ppp -direct pppmyisp If you are going to create a separate login script for a user you could use sendmail -qRexample.com instead in the script above. This will force all mail in your queue for example.com to be processed immediately. A further refinement of the situation is as follows: Message stolen from the &a.isp;. > we provide the secondary MX for a customer. The customer connects to > our services several times a day automatically to get the mails to > his primary MX (We do not call his site when a mail for his domains > arrived). Our sendmail sends the mailqueue every 30 minutes. At the > moment he has to stay 30 minutes online to be sure that all mail is > gone to the primary MX. > > Is there a command that would initiate sendmail to send all the mails > now? The user has not root-privileges on our machine of course. In the privacy flags section of sendmail.cf, there is a definition Opgoaway,restrictqrun Remove restrictqrun to allow non-root users to start the queue processing. You might also like to rearrange the MXs. We are the 1st MX for our customers like this, and we have defined: # If we are the best MX for a host, try directly instead of generating # local config error. OwTrue That way a remote site will deliver straight to you, without trying the customer connection. You then send to your customer. Only works for hosts, so you need to get your customer to name their mail machine customer.com as well as hostname.customer.com in the DNS. Just put an A record in the DNS for customer.com. Why do I keep getting Relaying Denied errors when sending mail from other hosts? In default FreeBSD installations, sendmail is configured to only send mail from the host it is running on. For example, if a POP server is available, then users will be able to check mail from school, work, or other remote locations but they still will not be able to send outgoing emails from outside locations. Typically, a few moments after the attempt, an email will be sent from MAILER-DAEMON with a 5.7 Relaying Denied error message. There are several ways to get around this. The most straightforward solution is to put your ISP's address in a relay-domains file at /etc/mail/relay-domains. A quick way to do this would be: &prompt.root; echo "your.isp.example.com" > /etc/mail/relay-domains After creating or editing this file you must restart sendmail. This works great if you are a server administrator and do not wish to send mail locally, or would like to use a point and click client/system on another machine or even another ISP. It is also very useful if you only have one or two email accounts set up. If there is a large number of addresses to add, you can simply open this file in your favorite text editor and then add the domains, one per line: your.isp.example.com other.isp.example.net users-isp.example.org www.example.org Now any mail sent through your system, by any host in this list (provided the user has an account on your system), will succeed. This is a very nice way to allow users to send mail from your system remotely without allowing people to send SPAM through your system. Advanced Topics The following section covers more involved topics such as mail configuration and setting up mail for your entire domain. Basic Configuration email configuration Out of the box, you should be able to send email to external hosts as long as you have set up /etc/resolv.conf or are running your own name server. If you would like to have mail for your host delivered to the MTA (e.g., sendmail) on your own FreeBSD host, there are two methods: Run your own name server and have your own domain. For example, FreeBSD.org Get mail delivered directly to your host. This is done by delivering mail directly to the current DNS name for your machine. For example, example.FreeBSD.org. SMTP Regardless of which of the above you choose, in order to have mail delivered directly to your host, it must have a permanent static IP address (not a dynamic address, as with most PPP dial-up configurations). If you are behind a firewall, it must pass SMTP traffic on to you. If you want to receive mail directly at your host, you need to be sure of either of two things: MX record Make sure that the (lowest-numbered) MX record in your DNS points to your host's IP address. Make sure there is no MX entry in your DNS for your host. Either of the above will allow you to receive mail directly at your host. Try this: &prompt.root; hostname example.FreeBSD.org &prompt.root; host example.FreeBSD.org example.FreeBSD.org has address 204.216.27.XX If that is what you see, mail directly to yourlogin@example.FreeBSD.org should work without problems (assuming sendmail is running correctly on example.FreeBSD.org). If instead you see something like this: &prompt.root; host example.FreeBSD.org example.FreeBSD.org has address 204.216.27.XX example.FreeBSD.org mail is handled (pri=10) by hub.FreeBSD.org All mail sent to your host (example.FreeBSD.org) will end up being collected on hub under the same username instead of being sent directly to your host. The above information is handled by your DNS server. The DNS record that carries mail routing information is the Mail eXchange entry. If no MX record exists, mail will be delivered directly to the host by way of its IP address. The MX entry for freefall.FreeBSD.org at one time looked like this: freefall MX 30 mail.crl.net freefall MX 40 agora.rdrop.com freefall MX 10 freefall.FreeBSD.org freefall MX 20 who.cdrom.com As you can see, freefall had many MX entries. The lowest MX number is the host that receives mail directly if available; if it is not accessible for some reason, the others (sometimes called backup MXes) accept messages temporarily, and pass it along when a lower-numbered host becomes available, eventually to the lowest-numbered host. Alternate MX sites should have separate Internet connections from your own in order to be most useful. Your ISP or another friendly site should have no problem providing this service for you. Mail for Your Domain In order to set up a mailhost (a.k.a. mail server) you need to have any mail sent to various workstations directed to it. Basically, you want to claim any mail for any hostname in your domain (in this case *.FreeBSD.org) and divert it to your mail server so your users can receive their mail on the master mail server. DNS To make life easiest, a user account with the same username should exist on both machines. Use &man.adduser.8; to do this. The mailhost you will be using must be the designated mail exchanger for each workstation on the network. This is done in your DNS configuration like so: example.FreeBSD.org A 204.216.27.XX ; Workstation MX 10 hub.FreeBSD.org ; Mailhost This will redirect mail for the workstation to the mailhost no matter where the A record points. The mail is sent to the MX host. You cannot do this yourself unless you are running a DNS server. If you are not, or cannot run your own DNS server, talk to your ISP or whoever provides your DNS. If you are doing virtual email hosting, the following information will come in handy. For this example, we will assume you have a customer with his own domain, in this case customer1.org, and you want all the mail for customer1.org sent to your mailhost, mail.myhost.com. The entry in your DNS should look like this: customer1.org MX 10 mail.myhost.com You do not need an A record for customer1.org if you only want to handle email for that domain. Be aware that pinging customer1.org will not work unless an A record exists for it. The last thing that you must do is tell sendmail on your mailhost what domains and/or hostnames it should be accepting mail for. There are a few different ways this can be done. Either of the following will work: Add the hosts to your /etc/mail/local-host-names file if you are using the FEATURE(use_cw_file). If you are using a version of sendmail earlier than 8.10, the file is /etc/sendmail.cw. Add a Cwyour.host.com line to your /etc/sendmail.cf or /etc/mail/sendmail.cf if you are using sendmail 8.10 or higher. SMTP with UUCP The sendmail configuration that ships with FreeBSD is designed for sites that connect directly to the Internet. Sites that wish to exchange their mail via UUCP must install another sendmail configuration file. Tweaking /etc/mail/sendmail.cf manually is an advanced topic. sendmail version 8 generates config files via &man.m4.1; preprocessing, where the actual configuration occurs on a higher abstraction level. The &man.m4.1; configuration files can be found under /usr/src/usr.sbin/sendmail/cf. If you did not install your system with full sources, the sendmail configuration set has been broken out into a separate source distribution tarball. Assuming you have your FreeBSD source code CDROM mounted, do: &prompt.root; cd /cdrom/src &prompt.root; cat scontrib.?? | tar xzf - -C /usr/src/contrib/sendmail This extracts to only a few hundred kilobytes. The file README in the cf directory can serve as a basic introduction to &man.m4.1; configuration. The best way to support UUCP delivery is to use the mailertable feature. This creates a database that sendmail can use to make routing decisions. First, you have to create your .mc file. The directory /usr/src/usr.sbin/sendmail/cf/cf contains a few examples. Assuming you have named your file foo.mc, all you need to do in order to convert it into a valid sendmail.cf is: &prompt.root; cd /usr/src/usr.sbin/sendmail/cf/cf &prompt.root; make foo.cf &prompt.root; cp foo.cf /etc/mail/sendmail.cf A typical .mc file might look like: VERSIONID(`Your version number') OSTYPE(bsd4.4) FEATURE(accept_unresolvable_domains) FEATURE(nocanonify) FEATURE(mailertable, `hash -o /etc/mail/mailertable') define(`UUCP_RELAY', your.uucp.relay) define(`UUCP_MAX_SIZE', 200000) define(`confDONT_PROBE_INTERFACES') MAILER(local) MAILER(smtp) MAILER(uucp) Cw your.alias.host.name Cw youruucpnodename.UUCP The lines containing accept_unresolvable_domains, nocanonify, and confDONT_PROBE_INTERFACES features will prevent any usage of the DNS during mail delivery. The UUCP_RELAY clause is needed to support UUCP delivery. Simply put an Internet hostname there that is able to handle .UUCP pseudo-domain addresses; most likely, you will enter the mail relay of your ISP there. Once you have this, you need an /etc/mail/mailertable file. If you have only one link to the outside that is used for all your mails, the following file will suffice: # # makemap hash /etc/mail/mailertable.db < /etc/mail/mailertable . uucp-dom:your.uucp.relay A more complex example might look like this: # # makemap hash /etc/mail/mailertable.db < /etc/mail/mailertable # horus.interface-business.de uucp-dom:horus .interface-business.de uucp-dom:if-bus interface-business.de uucp-dom:if-bus .heep.sax.de smtp8:%1 horus.UUCP uucp-dom:horus if-bus.UUCP uucp-dom:if-bus . uucp-dom: The first three lines handle special cases where domain-addressed mail should not be sent out to the default route, but instead to some UUCP neighbor in order to shortcut the delivery path. The next line handles mail to the local Ethernet domain that can be delivered using SMTP. Finally, the UUCP neighbors are mentioned in the .UUCP pseudo-domain notation, to allow for a uucp-neighbor !recipient override of the default rules. The last line is always a single dot, matching everything else, with UUCP delivery to a UUCP neighbor that serves as your universal mail gateway to the world. All of the node names behind the uucp-dom: keyword must be valid UUCP neighbors, as you can verify using the command uuname. As a reminder that this file needs to be converted into a DBM database file before use. The command line to accomplish this is best placed as a comment at the top of the mailertable file. You always have to execute this command each time you change your mailertable file. Final hint: if you are uncertain whether some particular mail routing would work, remember the option to sendmail. It starts sendmail in address test mode; simply enter 3,0, followed by the address you wish to test for the mail routing. The last line tells you the used internal mail agent, the destination host this agent will be called with, and the (possibly translated) address. Leave this mode by typing CtrlD. &prompt.user; sendmail -bt ADDRESS TEST MODE (ruleset 3 NOT automatically invoked) Enter <ruleset> <address> > 3,0 foo@example.com canonify input: foo @ example . com ... parse returns: $# uucp-dom $@ your.uucp.relay $: foo < @ example . com . > > ^D Bill Moran Contributed by Setting Up to Send Only There are many instances where you may only want to send mail through a relay. Some examples are: Your computer is a desktop machine, but you want to use programs such as &man.send-pr.1;. To do so, you should use your ISP's mail relay. The computer is a server that does not handle mail locally, but needs to pass off all mail to a relay for processing. Just about any MTA is capable of filling this particular niche. Unfortunately, it can be very difficult to properly configure a full-featured MTA just to handle offloading mail. Programs such as sendmail and postfix are largely overkill for this use. Additionally, if you are using a typical Internet access service, your agreement may forbid you from running a mail server. The easiest way to fulfill those needs is to install the mail/ssmtp port. Execute the following commands as root: &prompt.root; cd /usr/ports/mail/ssmtp &prompt.root; make install replace clean Once installed, mail/ssmtp can be configured with a four-line file located at /usr/local/etc/ssmtp/ssmtp.conf: root=yourrealemail@example.com mailhub=mail.example.com rewriteDomain=example.com hostname=_HOSTNAME_ Make sure you use your real email address for root. Enter your ISP's outgoing mail relay in place of mail.example.com (some ISPs call this the outgoing mail server or SMTP server). Make sure you disable sendmail, including the outgoing mail service. See for details. mail/ssmtp has some other options available. See the example configuration file in /usr/local/etc/ssmtp or the manual page of ssmtp for some examples and more information. Setting up ssmtp in this manner will allow any software on your computer that needs to send mail to function properly, while not violating your ISP's usage policy or allowing your computer to be hijacked for spamming. Using Mail with a Dialup Connection If you have a static IP address, you should not need to adjust anything from the defaults. Set your host name to your assigned Internet name and sendmail will do the rest. If you have a dynamically assigned IP number and use a dialup PPP connection to the Internet, you will probably have a mailbox on your ISPs mail server. Let's assume your ISP's domain is example.net, and that your user name is user, you have called your machine bsd.home, and your ISP has told you that you may use relay.example.net as a mail relay. In order to retrieve mail from your mailbox, you must install a retrieval agent. The fetchmail utility is a good choice as it supports many different protocols. This program is available as a package or from the Ports Collection (mail/fetchmail). Usually, your ISP will provide POP. If you are using user PPP, you can automatically fetch your mail when an Internet connection is established with the following entry in /etc/ppp/ppp.linkup: MYADDR: !bg su user -c fetchmail If you are using sendmail (as shown below) to deliver mail to non-local accounts, you probably want to have sendmail process your mailqueue as soon as your Internet connection is established. To do this, put this command after the fetchmail command in /etc/ppp/ppp.linkup: !bg su user -c "sendmail -q" Assume that you have an account for user on bsd.home. In the home directory of user on bsd.home, create a .fetchmailrc file: poll example.net protocol pop3 fetchall pass MySecret This file should not be readable by anyone except user as it contains the password MySecret. In order to send mail with the correct from: header, you must tell sendmail to use user@example.net rather than user@bsd.home. You may also wish to tell sendmail to send all mail via relay.example.net, allowing quicker mail transmission. The following .mc file should suffice: VERSIONID(`bsd.home.mc version 1.0') OSTYPE(bsd4.4)dnl FEATURE(nouucp)dnl MAILER(local)dnl MAILER(smtp)dnl Cwlocalhost Cwbsd.home MASQUERADE_AS(`example.net')dnl FEATURE(allmasquerade)dnl FEATURE(masquerade_envelope)dnl FEATURE(nocanonify)dnl FEATURE(nodns)dnl define(`SMART_HOST', `relay.example.net') Dmbsd.home define(`confDOMAIN_NAME',`bsd.home')dnl define(`confDELIVERY_MODE',`deferred')dnl Refer to the previous section for details of how to turn this .mc file into a sendmail.cf file. Also, do not forget to restart sendmail after updating sendmail.cf. James Gorham Written by SMTP Authentication Having SMTP Authentication in place on your mail server has a number of benefits. SMTP Authentication can add another layer of security to sendmail, and has the benefit of giving mobile users who switch hosts the ability to use the same mail server without the need to reconfigure their mail client settings each time. Install security/cyrus-sasl from the ports. You can find this port in security/cyrus-sasl. security/cyrus-sasl has a number of compile time options to choose from and, for the method we will be using here, make sure to select the option. After installing security/cyrus-sasl, edit /usr/local/lib/sasl/Sendmail.conf (or create it if it does not exist) and add the following line: pwcheck_method: passwd This method will enable sendmail to authenticate against your FreeBSD passwd database. This saves the trouble of creating a new set of usernames and passwords for each user that needs to use SMTP authentication, and keeps the login and mail password the same. Now edit /etc/make.conf and add the following lines: SENDMAIL_CFLAGS=-I/usr/local/include/sasl1 -DSASL SENDMAIL_LDFLAGS=-L/usr/local/lib SENDMAIL_LDADD=-lsasl These lines will give sendmail the proper configuration options for linking to cyrus-sasl at compile time. Make sure that cyrus-sasl has been installed before recompiling sendmail. Recompile sendmail by executing the following commands: &prompt.root; cd /usr/src/usr.sbin/sendmail &prompt.root; make cleandir &prompt.root; make obj &prompt.root; make &prompt.root; make install The compile of sendmail should not have any problems if /usr/src has not been changed extensively and the shared libraries it needs are available. After sendmail has been compiled and reinstalled, edit your /etc/mail/freebsd.mc file (or whichever file you use as your .mc file. Many administrators choose to use the output from &man.hostname.1; as the .mc file for uniqueness). Add these lines to it: dnl set SASL options TRUST_AUTH_MECH(`GSSAPI DIGEST-MD5 CRAM-MD5 LOGIN')dnl define(`confAUTH_MECHANISMS', `GSSAPI DIGEST-MD5 CRAM-MD5 LOGIN')dnl define(`confDEF_AUTH_INFO', `/etc/mail/auth-info')dnl These options configure the different methods available to sendmail for authenticating users. If you would like to use a method other than pwcheck, please see the included documentation. Finally, run &man.make.1; while in /etc/mail. That will run your new .mc file and create a .cf file named freebsd.cf (or whatever name you have used for your .mc file). Then use the command make install restart, which will copy the file to sendmail.cf, and will properly restart sendmail. For more information about this process, you should refer to /etc/mail/Makefile. If all has gone correctly, you should be able to enter your login information into the mail client and send a test message. For further investigation, set the of sendmail to 13 and watch /var/log/maillog for any errors. You may wish to add the following line to /etc/rc.conf so this service will be available after every system boot: cyrus_pwcheck_enable="YES" This will ensure the initialization of SMTP_AUTH upon system boot. For more information, please see the sendmail page regarding SMTP authentication. Marc Silver Contributed by Mail User Agents Mail User Agents A Mail User Agent (MUA) is an application that is used to send and receive email. Furthermore, as email evolves and becomes more complex, MUA's are becoming increasingly powerful in the way they interact with email; this gives users increased functionality and flexibility. &os; contains support for numerous mail user agents, all of which can be easily installed using the FreeBSD Ports Collection. Users may choose between graphical email clients such as evolution or balsa, console based clients such as mutt, pine or mail, or the web interfaces used by some large organizations. mail &man.mail.1; is the default Mail User Agent (MUA) in &os;. It is a console based MUA that offers all the basic functionality required to send and receive text-based email, though it is limited in interaction abilities with attachments and can only support local mailboxes. Although mail does not natively support interaction with POP or IMAP servers, these mailboxes may be downloaded to a local mbox file using an application such as fetchmail, which will be discussed later in this chapter (). In order to send and receive email, simply invoke the mail command as per the following example: &prompt.user; mail The contents of the user mailbox in /var/mail are automatically read by the mail utility. Should the mailbox be empty, the utility exits with a message indicating that no mails could be found. Once the mailbox has been read, the application interface is started, and a list of messages will be displayed. Messages are automatically numbered, as can be seen in the following example: Mail version 8.1 6/6/93. Type ? for help. "/var/mail/marcs": 3 messages 3 new >N 1 root@localhost Mon Mar 8 14:05 14/510 "test" N 2 root@localhost Mon Mar 8 14:05 14/509 "user account" N 3 root@localhost Mon Mar 8 14:05 14/509 "sample" Messages can now be read by using the t mail command, suffixed by the message number that should be displayed. In this example, we will read the first email: & t 1 Message 1: From root@localhost Mon Mar 8 14:05:52 2004 X-Original-To: marcs@localhost Delivered-To: marcs@localhost To: marcs@localhost Subject: test Date: Mon, 8 Mar 2004 14:05:52 +0200 (SAST) From: root@localhost (Charlie Root) This is a test message, please reply if you receive it. As can be seen in the example above, the t key will cause the message to be displayed with full headers. To display the list of messages again, the h key should be used. If the email requires a response, you may use mail to reply, by using either the R or r mail keys. The R key instructs mail to reply only to the sender of the email, while r replies not only to the sender, but also to other recipients of the message. You may also suffix these commands with the mail number which you would like make a reply to. Once this has been done, the response should be entered, and the end of the message should be marked by a single . on a new line. An example can be seen below: & R 1 To: root@localhost Subject: Re: test Thank you, I did get your email. . EOT In order to send new email, the m key should be used, followed by the recipient email address. Multiple recipients may also be specified by separating each address with the , delimiter. The subject of the message may then be entered, followed by the message contents. The end of the message should be specified by putting a single . on a new line. & mail root@localhost Subject: I mastered mail Now I can send and receive email using mail ... :) . EOT While inside the mail utility, the ? command may be used to display help at any time, the &man.mail.1; manual page should also be consulted for more help with mail. As previously mentioned, the &man.mail.1; command was not originally designed to handle attachments, and thus deals with them very poorly. Newer MUAs such as mutt handle attachments in a much more intelligent way. But should you still wish to use the mail command, the converters/mpack port may be of considerable use. mutt mutt is a small yet very powerful Mail User Agent, with excellent features, just some of which include: The ability to thread messages; PGP support for digital signing and encryption of email; MIME Support; Maildir Support; Highly customizable. All of these features help to make mutt one of the most advanced mail user agents available. See for more information on mutt. The stable version of mutt may be installed using the mail/mutt port, while the current development version may be installed via the mail/mutt-devel port. After the port has been installed, mutt can be started by issuing the following command: &prompt.user; mutt mutt will automatically read the contents of the user mailbox in /var/mail and display the contents if applicable. If no mails are found in the user mailbox, then mutt will wait for commands from the user. The example below shows mutt displaying a list of messages: In order to read an email, simply select it using the cursor keys, and press the Enter key. An example of mutt displaying email can be seen below: As with the &man.mail.1; command, mutt allows users to reply only to the sender of the message as well as to all recipients. To reply only to the sender of the email, use the r keyboard shortcut. To send a group reply, which will be sent to the original sender as well as all the message recipients, use the g shortcut. mutt makes use of the &man.vi.1; command as an editor for creating and replying to emails. This may be customized by the user by creating or editing their own .muttrc file in their home directory and setting the editor variable. In order to compose a new mail message, press m. After a valid subject has been given, mutt will start &man.vi.1; and the mail can be written. Once the contents of the mail are complete, save and quit from vi and mutt will resume, displaying a summary screen of the mail that is to be delivered. In order to send the mail, press y. An example of the summary screen can be seen below: mutt also contains extensive help, which can be accessed from most of the menus by pressing the ? key. The top line also displays the keyboard shortcuts where appropriate. pine pine is aimed at a beginner user, but also includes some advanced features. The pine software has had several remote vulnerabilities discovered in the past, which allowed remote attackers to execute arbitrary code as users on the local system, by the action of sending a specially-prepared email. All such known problems have been fixed, but the pine code is written in a very insecure style and the &os; Security Officer believes there are likely to be other undiscovered vulnerabilities. You install pine at your own risk. The current version of pine may be installed using the mail/pine4 port. Once the port has installed, pine can be started by issuing the following command: &prompt.user; pine The first time that pine is run it displays a greeting page with a brief introduction, as well as a request from the pine development team to send an anonymous email message allowing them to judge how many users are using their client. To send this anonymous message, press Enter, or alternatively press E to exit the greeting without sending an anonymous message. An example of the greeting page can be seen below: Users are then presented with the main menu, which can be easily navigated using the cursor keys. This main menu provides shortcuts for the composing new mails, browsing of mail directories, and even the administration of address book entries. Below the main menu, relevant keyboard shortcuts to perform functions specific to the task at hand are shown. The default directory opened by pine is the inbox. To view the message index, press I, or select the MESSAGE INDEX option as seen below: The message index shows messages in the current directory, and can be navigated by using the cursor keys. Highlighted messages can be read by pressing the Enter key. In the screenshot below, a sample message is displayed by pine. Keyboard shortcuts are displayed as a reference at the bottom of the screen. An example of one of these shortcuts is the r key, which tells the MUA to reply to the current message being displayed. Replying to an email in pine is done using the pico editor, which is installed by default with pine. The pico utility makes it easy to navigate around the message and is slightly more forgiving on novice users than &man.vi.1; or &man.mail.1;. Once the reply is complete, the message can be sent by pressing CtrlX . The pine application will ask for confirmation. The pine application can be customized using the SETUP option from the main menu. Consult for more information. Marc Silver Contributed by Using fetchmail fetchmail fetchmail is a full-featured IMAP and POP client which allows users to automatically download mail from remote IMAP and POP servers and save it into local mailboxes; there it can be accessed more easily. fetchmail can be installed using the mail/fetchmail port, and offers various features, some of which include: Support of POP3, APOP, KPOP, IMAP, ETRN and ODMR protocols. Ability to forward mail using SMTP, which allows filtering, forwarding, and aliasing to function normally. May be run in daemon mode to check periodically for new messages. Can retrieve multiple mailboxes and forward them based on configuration, to different local users. While it is outside the scope of this document to explain all of fetchmail's features, some basic features will be explained. The fetchmail utility requires a configuration file known as .fetchmailrc, in order to run correctly. This file includes server information as well as login credentials. Due to the sensitive nature of the contents of this file, it is advisable to make it readable only by the owner, with the following command: &prompt.user; chmod 600 .fetchmailrc The following .fetchmailrc serves as an example for downloading a single user mailbox using POP. It tells fetchmail to connect to example.com using a username of joesoap and a password of XXX. This example assumes that the user joesoap is also a user on the local system. poll example.com protocol pop3 username "joesoap" password "XXX" The next example connects to multiple POP and IMAP servers and redirects to different local usernames where applicable: poll example.com proto pop3: user "joesoap", with password "XXX", is "jsoap" here; user "andrea", with password "XXXX"; poll example2.net proto imap: user "john", with password "XXXXX", is "myth" here; The fetchmail utility can be run in daemon mode by running it with the flag, followed by the interval (in seconds) that fetchmail should poll servers listed in the .fetchmailrc file. The following example would cause fetchmail to poll every 600 seconds: &prompt.user; fetchmail -d 600 More information on fetchmail can be found at . Marc Silver Contributed by Using procmail procmail The procmail utility is an incredibly powerful application used to filter incoming mail. It allows users to define rules which can be matched to incoming mails to perform specific functions or to reroute mail to alternative mailboxes and/or email addresses. procmail can be installed using the mail/procmail port. Once installed, it can be directly integrated into most MTAs; consult your MTA documentation for more information. Alternatively, procmail can be integrated by adding the following line to a .forward in the home directory of the user utilizing procmail features: "|exec /usr/local/bin/procmail || exit 75" The following section will display some basic procmail rules, as well as brief descriptions on what they do. These rules, and others must be inserted into a .procmailrc file, which must reside in the user's home directory. The majority of these rules can also be found in the &man.procmailex.5; manual page. Forward all mail from user@example.com to an external address of goodmail@example2.com: :0 * ^From.*user@example.com ! goodmail@example2.com Forward all mails shorter than 1000 bytes to an external address of goodmail@example2.com: :0 * < 1000 ! goodmail@example2.com Send all mail sent to alternate@example.com into a mailbox called alternate: :0 * ^TOalternate@example.com alternate Send all mail with a subject of Spam to /dev/null: :0 ^Subject:.*Spam /dev/null A useful recipe that parses incoming &os;.org mailing lists and places each list in its own mailbox: :0 * ^Sender:.owner-freebsd-\/[^@]+@FreeBSD.ORG { LISTNAME=${MATCH} :0 * LISTNAME??^\/[^@]+ FreeBSD-${MATCH} } diff --git a/zh_TW.Big5/books/handbook/printing/chapter.sgml b/zh_TW.Big5/books/handbook/printing/chapter.sgml index d54a94b620..1653805d08 100644 --- a/zh_TW.Big5/books/handbook/printing/chapter.sgml +++ b/zh_TW.Big5/books/handbook/printing/chapter.sgml @@ -1,4949 +1,4871 @@ Sean Kelly Contributed by Jim Mock Restructured and updated by - Printing + 列印 - Synopsis + 概述 LPD spooling system + LPD 緩衝系統 printing + 列印 - FreeBSD can be used to print with a wide variety of printers, from the - oldest impact printer to the latest laser printers, and everything in - between, allowing you to produce high-quality printed output from the - applications you run. - - FreeBSD can also be configured to act as a print server on a - network; in this capacity FreeBSD can receive print jobs from a variety - of other computers, including other FreeBSD computers, &windows; and &macos; - hosts. FreeBSD will ensure that one job at a time is printed, and can - keep statistics on which users and machines are doing the most printing, - produce banner pages showing who's printout is who's, and - more. + FreeBSD 可以和各式各樣的印表機搭配列印, + 從最老的撞針式印表機到最新的雷射印表機都沒問題, + 讓您的應用程式可以產生出高品質的文件列印輸出。 + + 也可以把 FreeBSD 設定成一台網路列印伺服器;這時候的 FreeBSD + 能接收其他電腦送來的列印工作,包括其他 FreeBSD 的電腦、&windows; + 的電腦以及 &macos; 的電腦。 FreeBSD + 會確保同時只有一件文件正在列印,而且可以統計哪個使用者及機器印得最多, + 還有就是印出接下來是誰的文件這類的標題頁等。 - After reading this chapter, you will know: + 讀完這章,您將了解: - How to configure the FreeBSD print spooler. + 如何設定 FreeBSD 的列印多工緩衝處理器。 - How to install print filters, to handle special print jobs - differently, including converting incoming documents to print - formats that your printers understand. + 如何安裝列印過濾器以分別處理特殊的列印工作, + 包括把收到的文件轉換成您的印表機看得懂的列印格式等。 - How to enable header, or banner pages on your printout. + 了解如何在您列印時順便印出頁首或標題。 - How to print with printers connected to other computers. + 如何利用別台電腦上的印表機列印。 - How to print with printers connected directly to the - network. + 如何利用直接接在網路上的印表機列印。 - How to control printer restrictions, including limiting the size - of print jobs, and preventing certain users from printing. + 如何控制印表機的權限,包括限制列印工作的檔案大小, + 以及不允許特定使用者列印等。 - How to keep printer statistics, and account for printer - usage. + 如何記下印表機的統計資料,以及各帳號的印表機使用量。 - How to troubleshoot printing problems. + 如何解決列印時遇到的問題。 - Before reading this chapter, you should: + 在開始閱讀這章之前,您需要︰ - Know how to configure and install a new kernel - (). + 要有設定、編譯 kernel 的基礎概念 + ()。 - Introduction + 介紹 - In order to use printers with FreeBSD, you may set - them up to work with the Berkeley line printer spooling system, - also known as the LPD spooling system, - or just LPD. - It is the standard printer control system in FreeBSD. This - chapter introduces LPD and - will guide you through its configuration. + 要在 FreeBSD 上使用印表機,您需要設定好 Berkeley + 行列式印表機列印緩衝系統,又稱為 LPD + 列印緩衝系統,或者就叫 LPD。 + 這是 FreeBSD 標準的印表機控制系統,本章會介紹並教您如何設定 + LPD - If you are already familiar with - LPD or another printer spooling - system, you may wish to skip to section Basic Setup. + 如果您已經對 LPD + 或是其他列印緩衝系統很熟悉了, + 您可以直接跳到基本設定。 + - LPD controls everything about a - host's printers. It is responsible for a number of things: + LPD 控制著主機上印表機的一切。 + 這些事情都是它在負責的: It controls access to attached printers and printers attached to other hosts on the network. print jobs It enables users to submit files to be printed; these submissions are known as jobs. It prevents multiple users from accessing a printer at the same time by maintaining a queue for each printer. It can print header pages (also known as banner or burst pages) so users can easily find jobs they have printed in a stack of printouts. It takes care of communications parameters for printers connected on serial ports. It can send jobs over the network to a LPD spooler on another host. It can run special filters to format jobs to be printed for various printer languages or printer capabilities. It can account for printer usage. Through a configuration file (/etc/printcap), and by providing the special filter programs, you can enable the LPD system to do all or some subset of the above for a great variety of printer hardware. Why You Should Use the Spooler If you are the sole user of your system, you may be wondering why you should bother with the spooler when you do not need access control, header pages, or printer accounting. While it is possible to enable direct access to a printer, you should use the spooler anyway since: LPD prints jobs in the background; you do not have to wait for data to be copied to the printer. &tex; LPD can conveniently run a job to be printed through filters to add date/time headers or convert a special file format (such as a &tex; DVI file) into a format the printer will understand. You will not have to do these steps manually. Many free and commercial programs that provide a print feature usually expect to talk to the spooler on your system. By setting up the spooling system, you will more easily support other software you may later add or already have. Basic Setup To use printers with the LPD spooling system, you will need to set up both your printer hardware and the LPD software. This document describes two levels of setup: See section Simple Printer Setup to learn how to connect a printer, tell LPD how to communicate with it, and print plain text files to the printer. See section Advanced Printer Setup to learn how to print a variety of special file formats, to print header pages, to print across a network, to control access to printers, and to do printer accounting. Simple Printer Setup This section tells how to configure printer hardware and the LPD software to use the printer. It teaches the basics: Section Hardware Setup gives some hints on connecting the printer to a port on your computer. Section Software Setup shows how to set up the LPD spooler configuration file (/etc/printcap). If you are setting up a printer that uses a network protocol to accept data to print instead of a computer's local interfaces, see Printers With Networked Data Stream Interfaces. Although this section is called Simple Printer Setup, it is actually fairly complex. Getting the printer to work with your computer and the LPD spooler is the hardest part. The advanced options like header pages and accounting are fairly easy once you get the printer working. Hardware Setup This section tells about the various ways you can connect a printer to your PC. It talks about the kinds of ports and cables, and also the kernel configuration you may need to enable FreeBSD to speak to the printer. If you have already connected your printer and have successfully printed with it under another operating system, you can probably skip to section Software Setup. Ports and Cables Printers sold for use on PC's today generally come with one or more of the following three interfaces: printers serial Serial interfaces, also known as RS-232 or COM ports, use a serial port on your computer to send data to the printer. Serial interfaces are common in the computer industry and cables are readily available and also easy to construct. Serial interfaces sometimes need special cables and might require you to configure somewhat complex communications options. Most PC serial ports have a maximum transmission rate of 115200 bps, which makes printing large graphic print jobs with them impractical. printers parallel Parallel interfaces use a parallel port on your computer to send data to the printer. Parallel interfaces are common in the PC market and are faster than RS-232 serial. Cables are readily available but more difficult to construct by hand. There are usually no communications options with parallel interfaces, making their configuration exceedingly simple. centronics parallel printers Parallel interfaces are sometimes known as Centronics interfaces, named after the connector type on the printer. printers USB USB interfaces, named for the Universal Serial Bus, can run at even faster speeds than parallel or RS-232 serial interfaces. Cables are simple and cheap. USB is superior to RS-232 Serial and to Parallel for printing, but it is not as well supported under &unix; systems. A way to avoid this problem is to purchase a printer that has both a USB interface and a Parallel interface, as many printers do. In general, Parallel interfaces usually offer just one-way communication (computer to printer) while serial and USB gives you two-way. Newer parallel ports (EPP and ECP) and printers can communicate in both directions under FreeBSD when a IEEE-1284-compliant cable is used. PostScript Two-way communication to the printer over a parallel port is generally done in one of two ways. The first method uses a custom-built printer driver for FreeBSD that speaks the proprietary language used by the printer. This is common with inkjet printers and can be used for reporting ink levels and other status information. The second method is used when the printer supports &postscript;. &postscript; jobs are actually programs sent to the printer; they need not produce paper at all and may return results directly to the computer. &postscript; also uses two-way communication to tell the computer about problems, such as errors in the &postscript; program or paper jams. Your users may be appreciative of such information. Furthermore, the best way to do effective accounting with a &postscript; printer requires two-way communication: you ask the printer for its page count (how many pages it has printed in its lifetime), then send the user's job, then ask again for its page count. Subtract the two values and you know how much paper to charge to the user. Parallel Ports To hook up a printer using a parallel interface, connect the Centronics cable between the printer and the computer. The instructions that came with the printer, the computer, or both should give you complete guidance. Remember which parallel port you used on the computer. The first parallel port is ppc0 to FreeBSD; the second is ppc1, and so on. The printer device name uses the same scheme: /dev/lpt0 for the printer on the first parallel ports etc. Serial Ports To hook up a printer using a serial interface, connect the proper serial cable between the printer and the computer. The instructions that came with the printer, the computer, or both should give you complete guidance. If you are unsure what the proper serial cable is, you may wish to try one of the following alternatives: A modem cable connects each pin of the connector on one end of the cable straight through to its corresponding pin of the connector on the other end. This type of cable is also known as a DTE-to-DCE cable. null-modem cable A null-modem cable connects some pins straight through, swaps others (send data to receive data, for example), and shorts some internally in each connector hood. This type of cable is also known as a DTE-to-DTE cable. A serial printer cable, required for some unusual printers, is like the null-modem cable, but sends some signals to their counterparts instead of being internally shorted. baud rate parity flow control protocol You should also set up the communications parameters for the printer, usually through front-panel controls or DIP switches on the printer. Choose the highest bps (bits per second, sometimes baud rate) that both your computer and the printer can support. Choose 7 or 8 data bits; none, even, or odd parity; and 1 or 2 stop bits. Also choose a flow control protocol: either none, or XON/XOFF (also known as in-band or software) flow control. Remember these settings for the software configuration that follows. Software Setup This section describes the software setup necessary to print with the LPD spooling system in FreeBSD. Here is an outline of the steps involved: Configure your kernel, if necessary, for the port you are using for the printer; section Kernel Configuration tells you what you need to do. Set the communications mode for the parallel port, if you are using a parallel port; section Setting the Communication Mode for the Parallel Port gives details. Test if the operating system can send data to the printer. Section Checking Printer Communications gives some suggestions on how to do this. Set up LPD for the printer by modifying the file /etc/printcap. You will find out how to do this later in this chapter. Kernel Configuration The operating system kernel is compiled to work with a specific set of devices. The serial or parallel interface for your printer is a part of that set. Therefore, it might be necessary to add support for an additional serial or parallel port if your kernel is not already configured for one. To find out if the kernel you are currently using supports a serial interface, type: &prompt.root; grep sioN /var/run/dmesg.boot Where N is the number of the serial port, starting from zero. If you see output similar to the following: sio2 at port 0x3e8-0x3ef irq 5 on isa sio2: type 16550A then the kernel supports the port. To find out if the kernel supports a parallel interface, type: &prompt.root; grep ppcN /var/run/dmesg.boot Where N is the number of the parallel port, starting from zero. If you see output similar to the following: ppc0: <Parallel port> at port 0x378-0x37f irq 7 on isa0 ppc0: SMC-like chipset (ECP/EPP/PS2/NIBBLE) in COMPATIBLE mode ppc0: FIFO with 16/16/8 bytes threshold then the kernel supports the port. You might have to reconfigure your kernel in order for the operating system to recognize and use the parallel or serial port you are using for the printer. To add support for a serial port, see the section on kernel configuration. To add support for a parallel port, see that section and the section that follows. - - - Adding <filename>/dev</filename> Entries for the - Ports - - FreeBSD 5.0 includes the devfs - filesystem which automatically creates device nodes as - needed. If you are running a version of FreeBSD with - devfs enabled then you can safely skip - this section. - - Even though the kernel may support communication along a - serial or parallel port, you will still need a software - interface through which programs running on the system can - send and receive data. That is what entries in the - /dev directory are for. - - To add a /dev entry for a - port: - - - - Become root with the &man.su.1; command. - Enter the root password when prompted. - - - - Change to the /dev - directory: - - &prompt.root; cd /dev - - - - Type: - - &prompt.root; ./MAKEDEV port - - Where port is the device - entry for the port you want to make. Use - lpt0 for the printer on the first parallel port, - lpt1 for the printer on the second port, and so on; use - ttyd0 for the first serial port, - ttyd1 for the second, and so on. - - - - Type: - - &prompt.root; ls -l port - - to make sure the device entry got created. - - - - + Setting the Communication Mode for the Parallel Port When you are using the parallel interface, you can choose whether FreeBSD should use interrupt-driven or polled communication with the printer. The generic printer - device driver (&man.lpt.4;) on FreeBSD 4.X and 5.X + device driver (&man.lpt.4;) on FreeBSD uses the &man.ppbus.4; system, which controls the port chipset with the &man.ppc.4; driver. The interrupt-driven method is the default with the GENERIC kernel. With this method, the operating system uses an IRQ line to determine when the printer is ready for data. The polled method directs the operating system to repeatedly ask the printer if it is ready for more data. When it responds ready, the kernel sends more data. The interrupt-driven method is usually somewhat faster but uses up a precious IRQ line. Some newer HP printers are claimed not to work correctly in interrupt mode, apparently due to some (not yet exactly understood) timing problem. These printers need polled mode. You should use whichever one works. Some printers will work in both modes, but are painfully slow in interrupt mode. You can set the communications mode in two ways: by configuring the kernel or by using the &man.lptcontrol.8; program. To set the communications mode by configuring the kernel: Edit your kernel configuration file. Look for an ppc0 entry. If you are setting up the second parallel port, use ppc1 instead. Use ppc2 for the third port, and so on. - If you want interrupt-driven mode, for FreeBSD 4.X add the - irq specifier: - - device ppc0 at isa? irq N - - Where N is the IRQ - number for your computer's parallel port. - - For FreeBSD 5.X, edit the following line: + If you want interrupt-driven mode, edit the following line: hint.ppc.0.irq="N" in the /boot/device.hints file and replace N with the right IRQ number. The kernel configuration file must also contain the &man.ppc.4; driver: device ppc - If you want polled mode, do not add the - irq specifier: - - For FreeBSD 4.X, use the following line in - your kernel configuration file: - - device ppc0 at isa? - - For FreeBSD 5.X, simply remove in your + If you want polled mode, remove in your /boot/device.hints file, the following line: hint.ppc.0.irq="N" In some cases, this is not enough to put the - port in polled mode under FreeBSD 5.X. Most of + port in polled mode under FreeBSD. Most of time it comes from &man.acpi.4; driver, this latter is able to probe and attach devices, and therefore, control the access mode to the printer port. You should check your &man.acpi.4; configuration to correct this problem. Save the file. Then configure, build, and install the kernel, then reboot. See kernel configuration for more details. To set the communications mode with &man.lptcontrol.8;: Type: &prompt.root; lptcontrol -i -d /dev/lptN to set interrupt-driven mode for lptN. Type: &prompt.root; lptcontrol -p -d /dev/lptN to set polled-mode for lptN. You could put these commands in your /etc/rc.local file to set the mode each time your system boots. See &man.lptcontrol.8; for more information. - + - + Checking Printer Communications Before proceeding to configure the spooling system, you should make sure the operating system can successfully send data to your printer. It is a lot easier to debug printer communication and the spooling system separately. To test the printer, we will send some text to it. For printers that can immediately print characters sent to them, the program &man.lptest.1; is perfect: it generates all 96 printable ASCII characters in 96 lines. PostScript For a &postscript; (or other language-based) printer, we will need a more sophisticated test. A small &postscript; program, such as the following, will suffice: %!PS 100 100 moveto 300 300 lineto stroke 310 310 moveto /Helvetica findfont 12 scalefont setfont (Is this thing working?) show showpage The above &postscript; code can be placed into a file and used as shown in the examples appearing in the following sections. PCL When this document refers to a printer language, it is assuming a language like &postscript;, and not Hewlett Packard's PCL. Although PCL has great functionality, you can intermingle plain text with its escape sequences. &postscript; cannot directly print plain text, and that is the kind of printer language for which we must make special accommodations. - + Checking a Parallel Printer printers parallel This section tells you how to check if FreeBSD can communicate with a printer connected to a parallel port. To test a printer on a parallel port: Become root with &man.su.1;. Send data to the printer. If the printer can print plain text, then use &man.lptest.1;. Type: &prompt.root; lptest > /dev/lptN Where N is the number of the parallel port, starting from zero. If the printer understands &postscript; or other printer language, then send a small program to the printer. Type: &prompt.root; cat > /dev/lptN Then, line by line, type the program carefully as you cannot edit a line once you have pressed RETURN or ENTER. When you have finished entering the program, press CONTROL+D, or whatever your end of file key is. Alternatively, you can put the program in a file and type: &prompt.root; cat file > /dev/lptN Where file is the name of the file containing the program you want to send to the printer. You should see something print. Do not worry if the text does not look right; we will fix such things later. - + - + Checking a Serial Printer printers serial This section tells you how to check if FreeBSD can communicate with a printer on a serial port. To test a printer on a serial port: Become root with &man.su.1;. Edit the file /etc/remote. Add the following entry: printer:dv=/dev/port:br#bps-rate:pa=parity bits-per-second serial port parity Where port is the device entry for the serial port (ttyd0, ttyd1, etc.), bps-rate is the bits-per-second rate at which the printer communicates, and parity is the parity required by the printer (either even, odd, none, or zero). Here is a sample entry for a printer connected via a serial line to the third serial port at 19200 bps with no parity: printer:dv=/dev/ttyd2:br#19200:pa=none Connect to the printer with &man.tip.1;. Type: &prompt.root; tip printer If this step does not work, edit the file /etc/remote again and try using /dev/cuaaN instead of /dev/ttydN. Send data to the printer. If the printer can print plain text, then use &man.lptest.1;. Type: &prompt.user; $lptest If the printer understands &postscript; or other printer language, then send a small program to the printer. Type the program, line by line, very carefully as backspacing or other editing keys may be significant to the printer. You may also need to type a special end-of-file key for the printer so it knows it received the whole program. For &postscript; printers, press CONTROL+D. Alternatively, you can put the program in a file and type: &prompt.user; >file Where file is the name of the file containing the program. After &man.tip.1; sends the file, press any required end-of-file key. You should see something print. Do not worry if the text does not look right; we will fix that later. - - - + + Enabling the Spooler: the <filename>/etc/printcap</filename> File At this point, your printer should be hooked up, your kernel configured to communicate with it (if necessary), and you have been able to send some simple data to the printer. Now, we are ready to configure LPD to control access to your printer. You configure LPD by editing the file /etc/printcap. The LPD spooling system reads this file each time the spooler is used, so updates to the file take immediate effect. printers capabilities The format of the &man.printcap.5; file is straightforward. Use your favorite text editor to make changes to /etc/printcap. The format is identical to other capability files like /usr/share/misc/termcap and /etc/remote. For complete information about the format, see the &man.cgetent.3;. The simple spooler configuration consists of the following steps: Pick a name (and a few convenient aliases) for the printer, and put them in the /etc/printcap file; see the Naming the Printer section for more information on naming. header pages Turn off header pages (which are on by default) by inserting the sh capability; see the Suppressing Header Pages section for more information. Make a spooling directory, and specify its location with the sd capability; see the Making the Spooling Directory section for more information. Set the /dev entry to use for the printer, and note it in /etc/printcap with the lp capability; see the Identifying the Printer Device for more information. Also, if the printer is on a serial port, set up the communication parameters with the ms# capability which is discussed in the Configuring Spooler Communications Parameters section. Install a plain text input filter; see the Installing the Text Filter section for details. Test the setup by printing something with the &man.lpr.1; command. More details are available in the Trying It Out and Troubleshooting sections. Language-based printers, such as &postscript; printers, cannot directly print plain text. The simple setup outlined above and described in the following sections assumes that if you are installing such a printer you will print only files that the printer can understand. Users often expect that they can print plain text to any of the printers installed on your system. Programs that interface to LPD to do their printing usually make the same assumption. If you are installing such a printer and want to be able to print jobs in the printer language and print plain text jobs, you are strongly urged to add an additional step to the simple setup outlined above: install an automatic plain-text-to-&postscript; (or other printer language) conversion program. The section entitled Accommodating Plain Text Jobs on &postscript; Printers tells how to do this. Naming the Printer The first (easy) step is to pick a name for your printer. It really does not matter whether you choose functional or whimsical names since you can also provide a number of aliases for the printer. At least one of the printers specified in the /etc/printcap should have the alias lp. This is the default printer's name. If users do not have the PRINTER environment variable nor specify a printer name on the command line of any of the LPD commands, then lp will be the default printer they get to use. Also, it is common practice to make the last alias for a printer be a full description of the printer, including make and model. Once you have picked a name and some common aliases, put them in the /etc/printcap file. The name of the printer should start in the leftmost column. Separate each alias with a vertical bar and put a colon after the last alias. In the following example, we start with a skeletal /etc/printcap that defines two printers (a Diablo 630 line printer and a Panasonic KX-P4455 &postscript; laser printer): # # /etc/printcap for host rose # rattan|line|diablo|lp|Diablo 630 Line Printer: bamboo|ps|PS|S|panasonic|Panasonic KX-P4455 PostScript v51.4: In this example, the first printer is named rattan and has as aliases line, diablo, lp, and Diablo 630 Line Printer. Since it has the alias lp, it is also the default printer. The second is named bamboo, and has as aliases ps, PS, S, panasonic, and Panasonic KX-P4455 PostScript v51.4. Suppressing Header Pages printing header pages The LPD spooling system will by default print a header page for each job. The header page contains the user name who requested the job, the host from which the job came, and the name of the job, in nice large letters. Unfortunately, all this extra text gets in the way of debugging the simple printer setup, so we will suppress header pages. To suppress header pages, add the sh capability to the entry for the printer in /etc/printcap. Here is an example /etc/printcap with sh added: # # /etc/printcap for host rose - no header pages anywhere # rattan|line|diablo|lp|Diablo 630 Line Printer:\ :sh: bamboo|ps|PS|S|panasonic|Panasonic KX-P4455 PostScript v51.4:\ :sh: Note how we used the correct format: the first line starts in the leftmost column, and subsequent lines are indented. Every line in an entry except the last ends in a backslash character. Making the Spooling Directory printer spool print jobs The next step in the simple spooler setup is to make a spooling directory, a directory where print jobs reside until they are printed, and where a number of other spooler support files live. Because of the variable nature of spooling directories, it is customary to put these directories under /var/spool. It is not necessary to backup the contents of spooling directories, either. Recreating them is as simple as running &man.mkdir.1;. It is also customary to make the directory with a name that is identical to the name of the printer, as shown below: &prompt.root; mkdir /var/spool/printer-name However, if you have a lot of printers on your network, you might want to put the spooling directories under a single directory that you reserve just for printing with LPD. We will do this for our two example printers rattan and bamboo: &prompt.root; mkdir /var/spool/lpd &prompt.root; mkdir /var/spool/lpd/rattan &prompt.root; mkdir /var/spool/lpd/bamboo If you are concerned about the privacy of jobs that users print, you might want to protect the spooling directory so it is not publicly accessible. Spooling directories should be owned and be readable, writable, and searchable by user daemon and group daemon, and no one else. We will do this for our example printers: &prompt.root; chown daemon:daemon /var/spool/lpd/rattan &prompt.root; chown daemon:daemon /var/spool/lpd/bamboo &prompt.root; chmod 770 /var/spool/lpd/rattan &prompt.root; chmod 770 /var/spool/lpd/bamboo Finally, you need to tell LPD about these directories using the /etc/printcap file. You specify the pathname of the spooling directory with the sd capability: # # /etc/printcap for host rose - added spooling directories # rattan|line|diablo|lp|Diablo 630 Line Printer:\ :sh:sd=/var/spool/lpd/rattan: bamboo|ps|PS|S|panasonic|Panasonic KX-P4455 PostScript v51.4:\ :sh:sd=/var/spool/lpd/bamboo: Note that the name of the printer starts in the first column but all other entries describing the printer should be indented and each line end escaped with a backslash. If you do not specify a spooling directory with sd, the spooling system will use /var/spool/lpd as a default. Identifying the Printer Device - In the Adding - /dev Entries for the Ports + In the + Entries for the Ports section, we identified which entry in the /dev directory FreeBSD will use to communicate with the printer. Now, we tell LPD that information. When the spooling system has a job to print, it will open the specified device on behalf of the filter program (which is responsible for passing data to the printer). List the /dev entry pathname in the /etc/printcap file using the lp capability. In our running example, let us assume that rattan is on the first parallel port, and bamboo is on a sixth serial port; here are the additions to /etc/printcap: # # /etc/printcap for host rose - identified what devices to use # rattan|line|diablo|lp|Diablo 630 Line Printer:\ :sh:sd=/var/spool/lpd/rattan:\ :lp=/dev/lpt0: bamboo|ps|PS|S|panasonic|Panasonic KX-P4455 PostScript v51.4:\ :sh:sd=/var/spool/lpd/bamboo:\ :lp=/dev/ttyd5: If you do not specify the lp capability for a printer in your /etc/printcap file, LPD uses /dev/lp as a default. /dev/lp currently does not exist in FreeBSD. If the printer you are installing is connected to a parallel port, skip to the section entitled, Installing the Text Filter. Otherwise, be sure to follow the instructions in the next section. Configuring Spooler Communication Parameters printers serial For printers on serial ports, LPD can set up the bps rate, parity, and other serial communication parameters on behalf of the filter program that sends data to the printer. This is advantageous since: It lets you try different communication parameters by simply editing the /etc/printcap file; you do not have to recompile the filter program. It enables the spooling system to use the same filter program for multiple printers which may have different serial communication settings. The following /etc/printcap capabilities control serial communication parameters of the device listed in the lp capability: br#bps-rate Sets the communications speed of the device to bps-rate, where bps-rate can be 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, 9600, 19200, 38400, 57600, or 115200 bits-per-second. ms#stty-mode Sets the options for the terminal device after opening the device. &man.stty.1; explains the available options. When LPD opens the device specified by the lp capability, it sets the characteristics of the device to those specified with the ms# capability. Of particular interest will be the parenb, parodd, cs5, cs6, cs7, cs8, cstopb, crtscts, and ixon modes, which are explained in the &man.stty.1; manual page. Let us add to our example printer on the sixth serial port. We will set the bps rate to 38400. For the mode, we will set no parity with -parenb, 8-bit characters with cs8, no modem control with clocal and hardware flow control with crtscts: bamboo|ps|PS|S|panasonic|Panasonic KX-P4455 PostScript v51.4:\ :sh:sd=/var/spool/lpd/bamboo:\ :lp=/dev/ttyd5:ms#-parenb cs8 clocal crtscts: Installing the Text Filter printing filters We are now ready to tell LPD what text filter to use to send jobs to the printer. A text filter, also known as an input filter, is a program that LPD runs when it has a job to print. When LPD runs the text filter for a printer, it sets the filter's standard input to the job to print, and its standard output to the printer device specified with the lp capability. The filter is expected to read the job from standard input, perform any necessary translation for the printer, and write the results to standard output, which will get printed. For more information on the text filter, see the Filters section. For our simple printer setup, the text filter can be a small shell script that just executes /bin/cat to send the job to the printer. FreeBSD comes with another filter called lpf that handles backspacing and underlining for printers that might not deal with such character streams well. And, of course, you can use any other filter program you want. The filter lpf is described in detail in section entitled lpf: a Text Filter. First, let us make the shell script /usr/local/libexec/if-simple be a simple text filter. Put the following text into that file with your favorite text editor: #!/bin/sh # # if-simple - Simple text input filter for lpd # Installed in /usr/local/libexec/if-simple # # Simply copies stdin to stdout. Ignores all filter arguments. /bin/cat && exit 0 exit 2 Make the file executable: &prompt.root; chmod 555 /usr/local/libexec/if-simple And then tell LPD to use it by specifying it with the if capability in /etc/printcap. We will add it to the two printers we have so far in the example /etc/printcap: # # /etc/printcap for host rose - added text filter # rattan|line|diablo|lp|Diablo 630 Line Printer:\ :sh:sd=/var/spool/lpd/rattan:\ :lp=/dev/lpt0:\ :if=/usr/local/libexec/if-simple: bamboo|ps|PS|S|panasonic|Panasonic KX-P4455 PostScript v51.4:\ :sh:sd=/var/spool/lpd/bamboo:\ :lp=/dev/ttyd5:ms#-parenb cs8 clocal crtscts:\ :if=/usr/local/libexec/if-simple: A copy of the if-simple script can be found in the /usr/share/examples/printing directory. Turn on <application>LPD</application> &man.lpd.8; is run from /etc/rc, controlled by the lpd_enable variable. This variable defaults to NO. If you have not done so already, add the line: lpd_enable="YES" to /etc/rc.conf, and then either restart your machine, or just run &man.lpd.8;. &prompt.root; lpd Trying It Out You have reached the end of the simple LPD setup. Unfortunately, congratulations are not quite yet in order, since we still have to test the setup and correct any problems. To test the setup, try printing something. To print with the LPD system, you use the command &man.lpr.1;, which submits a job for printing. You can combine &man.lpr.1; with the &man.lptest.1; program, introduced in section Checking Printer Communications to generate some test text. To test the simple LPD setup: Type: &prompt.root; lptest 20 5 | lpr -Pprinter-name Where printer-name is a the name of a printer (or an alias) specified in /etc/printcap. To test the default printer, type &man.lpr.1; without any argument. Again, if you are testing a printer that expects &postscript;, send a &postscript; program in that language instead of using &man.lptest.1;. You can do so by putting the program in a file and typing lpr file. For a &postscript; printer, you should get the results of the program. If you are using &man.lptest.1;, then your results should look like the following: !"#$%&'()*+,-./01234 "#$%&'()*+,-./012345 #$%&'()*+,-./0123456 $%&'()*+,-./01234567 %&'()*+,-./012345678 To further test the printer, try downloading larger programs (for language-based printers) or running &man.lptest.1; with different arguments. For example, lptest 80 60 will produce 60 lines of 80 characters each. If the printer did not work, see the Troubleshooting section. Advanced Printer Setup This section describes filters for printing specially formatted files, header pages, printing across networks, and restricting and accounting for printer usage. Filters printing filters Although LPD handles network protocols, queuing, access control, and other aspects of printing, most of the real work happens in the filters. Filters are programs that communicate with the printer and handle its device dependencies and special requirements. In the simple printer setup, we installed a plain text filter—an extremely simple one that should work with most printers (section Installing the Text Filter). However, in order to take advantage of format conversion, printer accounting, specific printer quirks, and so on, you should understand how filters work. It will ultimately be the filter's responsibility to handle these aspects. And the bad news is that most of the time you have to provide filters yourself. The good news is that many are generally available; when they are not, they are usually easy to write. Also, FreeBSD comes with one, /usr/libexec/lpr/lpf, that works with many printers that can print plain text. (It handles backspacing and tabs in the file, and does accounting, but that is about all it does.) There are also several filters and filter components in the FreeBSD Ports Collection. Here is what you will find in this section: Section How Filters Work, tries to give an overview of a filter's role in the printing process. You should read this section to get an understanding of what is happening under the hood when LPD uses filters. This knowledge could help you anticipate and debug problems you might encounter as you install more and more filters on each of your printers. LPD expects every printer to be able to print plain text by default. This presents a problem for &postscript; (or other language-based printers) which cannot directly print plain text. Section Accommodating Plain Text Jobs on &postscript; Printers tells you what you should do to overcome this problem. You should read this section if you have a &postscript; printer. &postscript; is a popular output format for many programs. Some people even write &postscript; code directly. Unfortunately, &postscript; printers are expensive. Section Simulating &postscript; on Non &postscript; Printers tells how you can further modify a printer's text filter to accept and print &postscript; data on a non &postscript; printer. You should read this section if you do not have a &postscript; printer. Section Conversion Filters tells about a way you can automate the conversion of specific file formats, such as graphic or typesetting data, into formats your printer can understand. After reading this section, you should be able to set up your printers such that users can type lpr -t to print troff data, or lpr -d to print &tex; DVI data, or lpr -v to print raster image data, and so forth. I recommend reading this section. Section Output Filters tells all about a not often used feature of LPD: output filters. Unless you are printing header pages (see Header Pages), you can probably skip that section altogether. Section lpf: a Text Filter describes lpf, a fairly complete if simple text filter for line printers (and laser printers that act like line printers) that comes with FreeBSD. If you need a quick way to get printer accounting working for plain text, or if you have a printer which emits smoke when it sees backspace characters, you should definitely consider lpf. A copy of the various scripts described below can be found in the /usr/share/examples/printing directory. How Filters Work As mentioned before, a filter is an executable program started by LPD to handle the device-dependent part of communicating with the printer. When LPD wants to print a file in a job, it starts a filter program. It sets the filter's standard input to the file to print, its standard output to the printer, and its standard error to the error logging file (specified in the lf capability in /etc/printcap, or /dev/console by default). troff Which filter LPD starts and the filter's arguments depend on what is listed in the /etc/printcap file and what arguments the user specified for the job on the &man.lpr.1; command line. For example, if the user typed lpr -t, LPD would start the troff filter, listed in the tf capability for the destination printer. If the user wanted to print plain text, it would start the if filter (this is mostly true: see Output Filters for details). There are three kinds of filters you can specify in /etc/printcap: The text filter, confusingly called the input filter in LPD documentation, handles regular text printing. Think of it as the default filter. LPD expects every printer to be able to print plain text by default, and it is the text filter's job to make sure backspaces, tabs, or other special characters do not confuse the printer. If you are in an environment where you have to account for printer usage, the text filter must also account for pages printed, usually by counting the number of lines printed and comparing that to the number of lines per page the printer supports. The text filter is started with the following argument list: filter-name -c -wwidth -llength -iindent -n login -h host acct-file where appears if the job is submitted with lpr -l width is the value from the pw (page width) capability specified in /etc/printcap, default 132 length is the value from the pl (page length) capability, default 66 indent is the amount of the indentation from lpr -i, default 0 login is the account name of the user printing the file host is the host name from which the job was submitted acct-file is the name of the accounting file from the af capability. printing filters A conversion filter converts a specific file format into one the printer can render onto paper. For example, ditroff typesetting data cannot be directly printed, but you can install a conversion filter for ditroff files to convert the ditroff data into a form the printer can digest and print. Section Conversion Filters tells all about them. Conversion filters also need to do accounting, if you need printer accounting. Conversion filters are started with the following arguments: filter-name -xpixel-width -ypixel-height -n login -h host acct-file where pixel-width is the value from the px capability (default 0) and pixel-height is the value from the py capability (default 0). The output filter is used only if there is no text filter, or if header pages are enabled. In my experience, output filters are rarely used. Section Output Filters describe them. There are only two arguments to an output filter: filter-name -wwidth -llength which are identical to the text filters and arguments. Filters should also exit with the following exit status: exit 0 If the filter printed the file successfully. exit 1 If the filter failed to print the file but wants LPD to try to print the file again. LPD will restart a filter if it exits with this status. exit 2 If the filter failed to print the file and does not want LPD to try again. LPD will throw out the file. The text filter that comes with the FreeBSD release, /usr/libexec/lpr/lpf, takes advantage of the page width and length arguments to determine when to send a form feed and how to account for printer usage. It uses the login, host, and accounting file arguments to make the accounting entries. If you are shopping for filters, see if they are LPD-compatible. If they are, they must support the argument lists described above. If you plan on writing filters for general use, then have them support the same argument lists and exit codes. Accommodating Plain Text Jobs on &postscript; Printers print jobs If you are the only user of your computer and &postscript; (or other language-based) printer, and you promise to never send plain text to your printer and to never use features of various programs that will want to send plain text to your printer, then you do not need to worry about this section at all. But, if you would like to send both &postscript; and plain text jobs to the printer, then you are urged to augment your printer setup. To do so, we have the text filter detect if the arriving job is plain text or &postscript;. All &postscript; jobs must start with %! (for other printer languages, see your printer documentation). If those are the first two characters in the job, we have &postscript;, and can pass the rest of the job directly. If those are not the first two characters in the file, then the filter will convert the text into &postscript; and print the result. How do we do this? printers serial If you have got a serial printer, a great way to do it is to install lprps. lprps is a &postscript; printer filter which performs two-way communication with the printer. It updates the printer's status file with verbose information from the printer, so users and administrators can see exactly what the state of the printer is (such as toner low or paper jam). But more importantly, it includes a program called psif which detects whether the incoming job is plain text and calls textps (another program that comes with lprps) to convert it to &postscript;. It then uses lprps to send the job to the printer. lprps is part of the FreeBSD Ports Collection (see The Ports Collection). You can fetch, build and install it yourself, of course. After installing lprps, just specify the pathname to the psif program that is part of lprps. If you installed lprps from the Ports Collection, use the following in the serial &postscript; printer's entry in /etc/printcap: :if=/usr/local/libexec/psif: You should also specify the rw capability; that tells LPD to open the printer in read-write mode. If you have a parallel &postscript; printer (and therefore cannot use two-way communication with the printer, which lprps needs), you can use the following shell script as the text filter: #!/bin/sh # # psif - Print PostScript or plain text on a PostScript printer # Script version; NOT the version that comes with lprps # Installed in /usr/local/libexec/psif # IFS="" read -r first_line first_two_chars=`expr "$first_line" : '\(..\)'` if [ "$first_two_chars" = "%!" ]; then # # PostScript job, print it. # echo "$first_line" && cat && printf "\004" && exit 0 exit 2 else # # Plain text, convert it, then print it. # ( echo "$first_line"; cat ) | /usr/local/bin/textps && printf "\004" && exit 0 exit 2 fi In the above script, textps is a program we installed separately to convert plain text to &postscript;. You can use any text-to-&postscript; program you wish. The FreeBSD Ports Collection (see The Ports Collection) includes a full featured text-to-&postscript; program called a2ps that you might want to investigate. Simulating &postscript; on Non &postscript; Printers PostScript emulating Ghostscript &postscript; is the de facto standard for high quality typesetting and printing. &postscript; is, however, an expensive standard. Thankfully, Aladdin Enterprises has a free &postscript; work-alike called Ghostscript that runs with FreeBSD. Ghostscript can read most &postscript; files and can render their pages onto a variety of devices, including many brands of non-PostScript printers. By installing Ghostscript and using a special text filter for your printer, you can make your non &postscript; printer act like a real &postscript; printer. Ghostscript is in the FreeBSD Ports Collection, if you would like to install it from there. You can fetch, build, and install it quite easily yourself, as well. To simulate &postscript;, we have the text filter detect if it is printing a &postscript; file. If it is not, then the filter will pass the file directly to the printer; otherwise, it will use Ghostscript to first convert the file into a format the printer will understand. Here is an example: the following script is a text filter for Hewlett Packard DeskJet 500 printers. For other printers, substitute the argument to the gs (Ghostscript) command. (Type gs -h to get a list of devices the current installation of Ghostscript supports.) #!/bin/sh # # ifhp - Print Ghostscript-simulated PostScript on a DeskJet 500 # Installed in /usr/local/libexec/ifhp # # Treat LF as CR+LF (to avoid the "staircase effect" on HP/PCL # printers): # printf "\033&k2G" || exit 2 # # Read first two characters of the file # IFS="" read -r first_line first_two_chars=`expr "$first_line" : '\(..\)'` if [ "$first_two_chars" = "%!" ]; then # # It is PostScript; use Ghostscript to scan-convert and print it. # /usr/local/bin/gs -dSAFER -dNOPAUSE -q -sDEVICE=djet500 \ -sOutputFile=- - && exit 0 else # # Plain text or HP/PCL, so just print it directly; print a form feed # at the end to eject the last page. # echo "$first_line" && cat && printf "\033&l0H" && exit 0 fi exit 2 Finally, you need to notify LPD of the filter via the if capability: :if=/usr/local/libexec/ifhp: That is it. You can type lpr plain.text and lpr whatever.ps and both should print successfully. Conversion Filters After completing the simple setup described in Simple Printer Setup, the first thing you will probably want to do is install conversion filters for your favorite file formats (besides plain ASCII text). Why Install Conversion Filters? &tex; printing DVI files Conversion filters make printing various kinds of files easy. As an example, suppose we do a lot of work with the &tex; typesetting system, and we have a &postscript; printer. Every time we generate a DVI file from &tex;, we cannot print it directly until we convert the DVI file into &postscript;. The command sequence goes like this: &prompt.user; dvips seaweed-analysis.dvi &prompt.user; lpr seaweed-analysis.ps By installing a conversion filter for DVI files, we can skip the hand conversion step each time by having LPD do it for us. Now, each time we get a DVI file, we are just one step away from printing it: &prompt.user; lpr -d seaweed-analysis.dvi We got LPD to do the DVI file conversion for us by specifying the option. Section Formatting and Conversion Options lists the conversion options. For each of the conversion options you want a printer to support, install a conversion filter and specify its pathname in /etc/printcap. A conversion filter is like the text filter for the simple printer setup (see section Installing the Text Filter) except that instead of printing plain text, the filter converts the file into a format the printer can understand. Which Conversion Filters Should I Install? You should install the conversion filters you expect to use. If you print a lot of DVI data, then a DVI conversion filter is in order. If you have got plenty of troff to print out, then you probably want a troff filter. The following table summarizes the filters that LPD works with, their capability entries for the /etc/printcap file, and how to invoke them with the lpr command: File type /etc/printcap capability lpr option cifplot cf DVI df plot gf ditroff nf FORTRAN text rf troff tf raster vf plain text if none, , or In our example, using lpr -d means the printer needs a df capability in its entry in /etc/printcap. FORTRAN Despite what others might contend, formats like FORTRAN text and plot are probably obsolete. At your site, you can give new meanings to these or any of the formatting options just by installing custom filters. For example, suppose you would like to directly print Printerleaf files (files from the Interleaf desktop publishing program), but will never print plot files. You could install a Printerleaf conversion filter under the gf capability and then educate your users that lpr -g mean print Printerleaf files. Installing Conversion Filters Since conversion filters are programs you install outside of the base FreeBSD installation, they should probably go under /usr/local. The directory /usr/local/libexec is a popular location, since they are specialized programs that only LPD will run; regular users should not ever need to run them. To enable a conversion filter, specify its pathname under the appropriate capability for the destination printer in /etc/printcap. In our example, we will add the DVI conversion filter to the entry for the printer named bamboo. Here is the example /etc/printcap file again, with the new df capability for the printer bamboo. # # /etc/printcap for host rose - added df filter for bamboo # rattan|line|diablo|lp|Diablo 630 Line Printer:\ :sh:sd=/var/spool/lpd/rattan:\ :lp=/dev/lpt0:\ :if=/usr/local/libexec/if-simple: bamboo|ps|PS|S|panasonic|Panasonic KX-P4455 PostScript v51.4:\ :sh:sd=/var/spool/lpd/bamboo:\ :lp=/dev/ttyd5:ms#-parenb cs8 clocal crtscts:rw:\ :if=/usr/local/libexec/psif:\ :df=/usr/local/libexec/psdf: The DVI filter is a shell script named /usr/local/libexec/psdf. Here is that script: #!/bin/sh # # psdf - DVI to PostScript printer filter # Installed in /usr/local/libexec/psdf # # Invoked by lpd when user runs lpr -d # exec /usr/local/bin/dvips -f | /usr/local/libexec/lprps "$@" This script runs dvips in filter mode (the argument) on standard input, which is the job to print. It then starts the &postscript; printer filter lprps (see section Accommodating Plain Text Jobs on &postscript; Printers) with the arguments LPD passed to this script. lprps will use those arguments to account for the pages printed. More Conversion Filter Examples Since there is no fixed set of steps to install conversion filters, let me instead provide more examples. Use these as guidance to making your own filters. Use them directly, if appropriate. This example script is a raster (well, GIF file, actually) conversion filter for a Hewlett Packard LaserJet III-Si printer: #!/bin/sh # # hpvf - Convert GIF files into HP/PCL, then print # Installed in /usr/local/libexec/hpvf PATH=/usr/X11R6/bin:$PATH; export PATH giftopnm | ppmtopgm | pgmtopbm | pbmtolj -resolution 300 \ && exit 0 \ || exit 2 It works by converting the GIF file into a portable anymap, converting that into a portable graymap, converting that into a portable bitmap, and converting that into LaserJet/PCL-compatible data. Here is the /etc/printcap file with an entry for a printer using the above filter: # # /etc/printcap for host orchid # teak|hp|laserjet|Hewlett Packard LaserJet 3Si:\ :lp=/dev/lpt0:sh:sd=/var/spool/lpd/teak:mx#0:\ :if=/usr/local/libexec/hpif:\ :vf=/usr/local/libexec/hpvf: The following script is a conversion filter for troff data from the groff typesetting system for the &postscript; printer named bamboo: #!/bin/sh # # pstf - Convert groff's troff data into PS, then print. # Installed in /usr/local/libexec/pstf # exec grops | /usr/local/libexec/lprps "$@" The above script makes use of lprps again to handle the communication with the printer. If the printer were on a parallel port, we would use this script instead: #!/bin/sh # # pstf - Convert groff's troff data into PS, then print. # Installed in /usr/local/libexec/pstf # exec grops That is it. Here is the entry we need to add to /etc/printcap to enable the filter: :tf=/usr/local/libexec/pstf: Here is an example that might make old hands at FORTRAN blush. It is a FORTRAN-text filter for any printer that can directly print plain text. We will install it for the printer teak: #!/bin/sh # # hprf - FORTRAN text filter for LaserJet 3si: # Installed in /usr/local/libexec/hprf # printf "\033&k2G" && fpr && printf "\033&l0H" && exit 0 exit 2 And we will add this line to the /etc/printcap for the printer teak to enable this filter: :rf=/usr/local/libexec/hprf: Here is one final, somewhat complex example. We will add a DVI filter to the LaserJet printer teak introduced earlier. First, the easy part: updating /etc/printcap with the location of the DVI filter: :df=/usr/local/libexec/hpdf: Now, for the hard part: making the filter. For that, we need a DVI-to-LaserJet/PCL conversion program. The FreeBSD Ports Collection (see The Ports Collection) has one: dvi2xx is the name of the package. Installing this package gives us the program we need, dvilj2p, which converts DVI into LaserJet IIp, LaserJet III, and LaserJet 2000 compatible codes. dvilj2p makes the filter hpdf quite complex since dvilj2p cannot read from standard input. It wants to work with a filename. What is worse, the filename has to end in .dvi so using /dev/fd/0 for standard input is problematic. We can get around that problem by linking (symbolically) a temporary file name (one that ends in .dvi) to /dev/fd/0, thereby forcing dvilj2p to read from standard input. The only other fly in the ointment is the fact that we cannot use /tmp for the temporary link. Symbolic links are owned by user and group bin. The filter runs as user daemon. And the /tmp directory has the sticky bit set. The filter can create the link, but it will not be able clean up when done and remove it since the link will belong to a different user. Instead, the filter will make the symbolic link in the current working directory, which is the spooling directory (specified by the sd capability in /etc/printcap). This is a perfect place for filters to do their work, especially since there is (sometimes) more free disk space in the spooling directory than under /tmp. Here, finally, is the filter: #!/bin/sh # # hpdf - Print DVI data on HP/PCL printer # Installed in /usr/local/libexec/hpdf PATH=/usr/local/bin:$PATH; export PATH # # Define a function to clean up our temporary files. These exist # in the current directory, which will be the spooling directory # for the printer. # cleanup() { rm -f hpdf$$.dvi } # # Define a function to handle fatal errors: print the given message # and exit 2. Exiting with 2 tells LPD to do not try to reprint the # job. # fatal() { echo "$@" 1>&2 cleanup exit 2 } # # If user removes the job, LPD will send SIGINT, so trap SIGINT # (and a few other signals) to clean up after ourselves. # trap cleanup 1 2 15 # # Make sure we are not colliding with any existing files. # cleanup # # Link the DVI input file to standard input (the file to print). # ln -s /dev/fd/0 hpdf$$.dvi || fatal "Cannot symlink /dev/fd/0" # # Make LF = CR+LF # printf "\033&k2G" || fatal "Cannot initialize printer" # # Convert and print. Return value from dvilj2p does not seem to be # reliable, so we ignore it. # dvilj2p -M1 -q -e- dfhp$$.dvi # # Clean up and exit # cleanup exit 0 Automated Conversion: an Alternative to Conversion Filters All these conversion filters accomplish a lot for your printing environment, but at the cost forcing the user to specify (on the &man.lpr.1; command line) which one to use. If your users are not particularly computer literate, having to specify a filter option will become annoying. What is worse, though, is that an incorrectly specified filter option may run a filter on the wrong type of file and cause your printer to spew out hundreds of sheets of paper. Rather than install conversion filters at all, you might want to try having the text filter (since it is the default filter) detect the type of file it has been asked to print and then automatically run the right conversion filter. Tools such as file can be of help here. Of course, it will be hard to determine the differences between some file types—and, of course, you can still provide conversion filters just for them. apsfilter printing filters apsfilter The FreeBSD Ports Collection has a text filter that performs automatic conversion called apsfilter. It can detect plain text, &postscript;, and DVI files, run the proper conversions, and print. Output Filters The LPD spooling system supports one other type of filter that we have not yet explored: an output filter. An output filter is intended for printing plain text only, like the text filter, but with many simplifications. If you are using an output filter but no text filter, then: LPD starts an output filter once for the entire job instead of once for each file in the job. LPD does not make any provision to identify the start or the end of files within the job for the output filter. LPD does not pass the user's login or host to the filter, so it is not intended to do accounting. In fact, it gets only two arguments: filter-name -wwidth -llength Where width is from the pw capability and length is from the pl capability for the printer in question. Do not be seduced by an output filter's simplicity. If you would like each file in a job to start on a different page an output filter will not work. Use a text filter (also known as an input filter); see section Installing the Text Filter. Furthermore, an output filter is actually more complex in that it has to examine the byte stream being sent to it for special flag characters and must send signals to itself on behalf of LPD. However, an output filter is necessary if you want header pages and need to send escape sequences or other initialization strings to be able to print the header page. (But it is also futile if you want to charge header pages to the requesting user's account, since LPD does not give any user or host information to the output filter.) On a single printer, LPD allows both an output filter and text or other filters. In such cases, LPD will start the output filter to print the header page (see section Header Pages) only. LPD then expects the output filter to stop itself by sending two bytes to the filter: ASCII 031 followed by ASCII 001. When an output filter sees these two bytes (031, 001), it should stop by sending SIGSTOP to itself. When LPD's done running other filters, it will restart the output filter by sending SIGCONT to it. If there is an output filter but no text filter and LPD is working on a plain text job, LPD uses the output filter to do the job. As stated before, the output filter will print each file of the job in sequence with no intervening form feeds or other paper advancement, and this is probably not what you want. In almost all cases, you need a text filter. The program lpf, which we introduced earlier as a text filter, can also run as an output filter. If you need a quick-and-dirty output filter but do not want to write the byte detection and signal sending code, try lpf. You can also wrap lpf in a shell script to handle any initialization codes the printer might require. <command>lpf</command>: a Text Filter The program /usr/libexec/lpr/lpf that comes with FreeBSD binary distribution is a text filter (input filter) that can indent output (job submitted with lpr -i), allow literal characters to pass (job submitted with lpr -l), adjust the printing position for backspaces and tabs in the job, and account for pages printed. It can also act like an output filter. lpf is suitable for many printing environments. And although it has no capability to send initialization sequences to a printer, it is easy to write a shell script to do the needed initialization and then execute lpf. page accounting accounting printer In order for lpf to do page accounting correctly, it needs correct values filled in for the pw and pl capabilities in the /etc/printcap file. It uses these values to determine how much text can fit on a page and how many pages were in a user's job. For more information on printer accounting, see Accounting for Printer Usage. Header Pages If you have lots of users, all of them using various printers, then you probably want to consider header pages as a necessary evil. banner pages header pages header pages Header pages, also known as banner or burst pages identify to whom jobs belong after they are printed. They are usually printed in large, bold letters, perhaps with decorative borders, so that in a stack of printouts they stand out from the real documents that comprise users' jobs. They enable users to locate their jobs quickly. The obvious drawback to a header page is that it is yet one more sheet that has to be printed for every job, their ephemeral usefulness lasting not more than a few minutes, ultimately finding themselves in a recycling bin or rubbish heap. (Note that header pages go with each job, not each file in a job, so the paper waste might not be that bad.) The LPD system can provide header pages automatically for your printouts if your printer can directly print plain text. If you have a &postscript; printer, you will need an external program to generate the header page; see Header Pages on &postscript; Printers. Enabling Header Pages In the Simple Printer Setup section, we turned off header pages by specifying sh (meaning suppress header) in the /etc/printcap file. To enable header pages for a printer, just remove the sh capability. Sounds too easy, right? You are right. You might have to provide an output filter to send initialization strings to the printer. Here is an example output filter for Hewlett Packard PCL-compatible printers: #!/bin/sh # # hpof - Output filter for Hewlett Packard PCL-compatible printers # Installed in /usr/local/libexec/hpof printf "\033&k2G" || exit 2 exec /usr/libexec/lpr/lpf Specify the path to the output filter in the of capability. See the Output Filters section for more information. Here is an example /etc/printcap file for the printer teak that we introduced earlier; we enabled header pages and added the above output filter: # # /etc/printcap for host orchid # teak|hp|laserjet|Hewlett Packard LaserJet 3Si:\ :lp=/dev/lpt0:sd=/var/spool/lpd/teak:mx#0:\ :if=/usr/local/libexec/hpif:\ :vf=/usr/local/libexec/hpvf:\ :of=/usr/local/libexec/hpof: Now, when users print jobs to teak, they get a header page with each job. If users want to spend time searching for their printouts, they can suppress header pages by submitting the job with lpr -h; see the Header Page Options section for more &man.lpr.1; options. LPD prints a form feed character after the header page. If your printer uses a different character or sequence of characters to eject a page, specify them with the ff capability in /etc/printcap. Controlling Header Pages By enabling header pages, LPD will produce a long header, a full page of large letters identifying the user, host, and job. Here is an example (kelly printed the job named outline from host rose): k ll ll k l l k l l k k eeee l l y y k k e e l l y y k k eeeeee l l y y kk k e l l y y k k e e l l y yy k k eeee lll lll yyy y y y y yyyy ll t l i t l oooo u u ttttt l ii n nnn eeee o o u u t l i nn n e e o o u u t l i n n eeeeee o o u u t l i n n e o o u uu t t l i n n e e oooo uuu u tt lll iii n n eeee r rrr oooo ssss eeee rr r o o s s e e r o o ss eeeeee r o o ss e r o o s s e e r oooo ssss eeee Job: outline Date: Sun Sep 17 11:04:58 1995 LPD appends a form feed after this text so the job starts on a new page (unless you have sf (suppress form feeds) in the destination printer's entry in /etc/printcap). If you prefer, LPD can make a short header; specify sb (short banner) in the /etc/printcap file. The header page will look like this: rose:kelly Job: outline Date: Sun Sep 17 11:07:51 1995 Also by default, LPD prints the header page first, then the job. To reverse that, specify hl (header last) in /etc/printcap. Accounting for Header Pages Using LPD's built-in header pages enforces a particular paradigm when it comes to printer accounting: header pages must be free of charge. Why? Because the output filter is the only external program that will have control when the header page is printed that could do accounting, and it is not provided with any user or host information or an accounting file, so it has no idea whom to charge for printer use. It is also not enough to just add one page to the text filter or any of the conversion filters (which do have user and host information) since users can suppress header pages with lpr -h. They could still be charged for header pages they did not print. Basically, lpr -h will be the preferred option of environmentally-minded users, but you cannot offer any incentive to use it. It is still not enough to have each of the filters generate their own header pages (thereby being able to charge for them). If users wanted the option of suppressing the header pages with lpr -h, they will still get them and be charged for them since LPD does not pass any knowledge of the option to any of the filters. So, what are your options? You can: Accept LPD's paradigm and make header pages free. Install an alternative to LPD, such as LPRng. Section Alternatives to the Standard Spooler tells more about other spooling software you can substitute for LPD. Write a smart output filter. Normally, an output filter is not meant to do anything more than initialize a printer or do some simple character conversion. It is suited for header pages and plain text jobs (when there is no text (input) filter). But, if there is a text filter for the plain text jobs, then LPD will start the output filter only for the header pages. And the output filter can parse the header page text that LPD generates to determine what user and host to charge for the header page. The only other problem with this method is that the output filter still does not know what accounting file to use (it is not passed the name of the file from the af capability), but if you have a well-known accounting file, you can hard-code that into the output filter. To facilitate the parsing step, use the sh (short header) capability in /etc/printcap. Then again, all that might be too much trouble, and users will certainly appreciate the more generous system administrator who makes header pages free. Header Pages on &postscript; Printers As described above, LPD can generate a plain text header page suitable for many printers. Of course, &postscript; cannot directly print plain text, so the header page feature of LPD is useless—or mostly so. One obvious way to get header pages is to have every conversion filter and the text filter generate the header page. The filters should use the user and host arguments to generate a suitable header page. The drawback of this method is that users will always get a header page, even if they submit jobs with lpr -h. Let us explore this method. The following script takes three arguments (user login name, host name, and job name) and makes a simple &postscript; header page: #!/bin/sh # # make-ps-header - make a PostScript header page on stdout # Installed in /usr/local/libexec/make-ps-header # # # These are PostScript units (72 to the inch). Modify for A4 or # whatever size paper you are using: # page_width=612 page_height=792 border=72 # # Check arguments # if [ $# -ne 3 ]; then echo "Usage: `basename $0` <user> <host> <job>" 1>&2 exit 1 fi # # Save these, mostly for readability in the PostScript, below. # user=$1 host=$2 job=$3 date=`date` # # Send the PostScript code to stdout. # exec cat <<EOF %!PS % % Make sure we do not interfere with user's job that will follow % save % % Make a thick, unpleasant border around the edge of the paper. % $border $border moveto $page_width $border 2 mul sub 0 rlineto 0 $page_height $border 2 mul sub rlineto currentscreen 3 -1 roll pop 100 3 1 roll setscreen $border 2 mul $page_width sub 0 rlineto closepath 0.8 setgray 10 setlinewidth stroke 0 setgray % % Display user's login name, nice and large and prominent % /Helvetica-Bold findfont 64 scalefont setfont $page_width ($user) stringwidth pop sub 2 div $page_height 200 sub moveto ($user) show % % Now show the boring particulars % /Helvetica findfont 14 scalefont setfont /y 200 def [ (Job:) (Host:) (Date:) ] { 200 y moveto show /y y 18 sub def } forall /Helvetica-Bold findfont 14 scalefont setfont /y 200 def [ ($job) ($host) ($date) ] { 270 y moveto show /y y 18 sub def } forall % % That is it % restore showpage EOF Now, each of the conversion filters and the text filter can call this script to first generate the header page, and then print the user's job. Here is the DVI conversion filter from earlier in this document, modified to make a header page: #!/bin/sh # # psdf - DVI to PostScript printer filter # Installed in /usr/local/libexec/psdf # # Invoked by lpd when user runs lpr -d # orig_args="$@" fail() { echo "$@" 1>&2 exit 2 } while getopts "x:y:n:h:" option; do case $option in x|y) ;; # Ignore n) login=$OPTARG ;; h) host=$OPTARG ;; *) echo "LPD started `basename $0` wrong." 1>&2 exit 2 ;; esac done [ "$login" ] || fail "No login name" [ "$host" ] || fail "No host name" ( /usr/local/libexec/make-ps-header $login $host "DVI File" /usr/local/bin/dvips -f ) | eval /usr/local/libexec/lprps $orig_args Notice how the filter has to parse the argument list in order to determine the user and host name. The parsing for the other conversion filters is identical. The text filter takes a slightly different set of arguments, though (see section How Filters Work). As we have mentioned before, the above scheme, though fairly simple, disables the suppress header page option (the option) to lpr. If users wanted to save a tree (or a few pennies, if you charge for header pages), they would not be able to do so, since every filter's going to print a header page with every job. To allow users to shut off header pages on a per-job basis, you will need to use the trick introduced in section Accounting for Header Pages: write an output filter that parses the LPD-generated header page and produces a &postscript; version. If the user submits the job with lpr -h, then LPD will not generate a header page, and neither will your output filter. Otherwise, your output filter will read the text from LPD and send the appropriate header page &postscript; code to the printer. If you have a &postscript; printer on a serial line, you can make use of lprps, which comes with an output filter, psof, which does the above. Note that psof does not charge for header pages. Networked Printing printers network network printing FreeBSD supports networked printing: sending jobs to remote printers. Networked printing generally refers to two different things: Accessing a printer attached to a remote host. You install a printer that has a conventional serial or parallel interface on one host. Then, you set up LPD to enable access to the printer from other hosts on the network. Section Printers Installed on Remote Hosts tells how to do this. Accessing a printer attached directly to a network. The printer has a network interface in addition (or in place of) a more conventional serial or parallel interface. Such a printer might work as follows: It might understand the LPD protocol and can even queue jobs from remote hosts. In this case, it acts just like a regular host running LPD. Follow the same procedure in section Printers Installed on Remote Hosts to set up such a printer. It might support a data stream network connection. In this case, you attach the printer to one host on the network by making that host responsible for spooling jobs and sending them to the printer. Section Printers with Networked Data Stream Interfaces gives some suggestions on installing such printers. Printers Installed on Remote Hosts The LPD spooling system has built-in support for sending jobs to other hosts also running LPD (or are compatible with LPD). This feature enables you to install a printer on one host and make it accessible from other hosts. It also works with printers that have network interfaces that understand the LPD protocol. To enable this kind of remote printing, first install a printer on one host, the printer host, using the simple printer setup described in the Simple Printer Setup section. Do any advanced setup in Advanced Printer Setup that you need. Make sure to test the printer and see if it works with the features of LPD you have enabled. Also ensure that the local host has authorization to use the LPD service in the remote host (see Restricting Jobs from Remote Printers). printers network network printing If you are using a printer with a network interface that is compatible with LPD, then the printer host in the discussion below is the printer itself, and the printer name is the name you configured for the printer. See the documentation that accompanied your printer and/or printer-network interface. If you are using a Hewlett Packard Laserjet then the printer name text will automatically perform the LF to CRLF conversion for you, so you will not require the hpif script. Then, on the other hosts you want to have access to the printer, make an entry in their /etc/printcap files with the following: Name the entry anything you want. For simplicity, though, you probably want to use the same name and aliases as on the printer host. Leave the lp capability blank, explicitly (:lp=:). Make a spooling directory and specify its location in the sd capability. LPD will store jobs here before they get sent to the printer host. Place the name of the printer host in the rm capability. Place the printer name on the printer host in the rp capability. That is it. You do not need to list conversion filters, page dimensions, or anything else in the /etc/printcap file. Here is an example. The host rose has two printers, bamboo and rattan. We will enable users on the host orchid to print to those printers. Here is the /etc/printcap file for orchid (back from section Enabling Header Pages). It already had the entry for the printer teak; we have added entries for the two printers on the host rose: # # /etc/printcap for host orchid - added (remote) printers on rose # # # teak is local; it is connected directly to orchid: # teak|hp|laserjet|Hewlett Packard LaserJet 3Si:\ :lp=/dev/lpt0:sd=/var/spool/lpd/teak:mx#0:\ :if=/usr/local/libexec/ifhp:\ :vf=/usr/local/libexec/vfhp:\ :of=/usr/local/libexec/ofhp: # # rattan is connected to rose; send jobs for rattan to rose: # rattan|line|diablo|lp|Diablo 630 Line Printer:\ :lp=:rm=rose:rp=rattan:sd=/var/spool/lpd/rattan: # # bamboo is connected to rose as well: # bamboo|ps|PS|S|panasonic|Panasonic KX-P4455 PostScript v51.4:\ :lp=:rm=rose:rp=bamboo:sd=/var/spool/lpd/bamboo: Then, we just need to make spooling directories on orchid: &prompt.root; mkdir -p /var/spool/lpd/rattan /var/spool/lpd/bamboo &prompt.root; chmod 770 /var/spool/lpd/rattan /var/spool/lpd/bamboo &prompt.root; chown daemon:daemon /var/spool/lpd/rattan /var/spool/lpd/bamboo Now, users on orchid can print to rattan and bamboo. If, for example, a user on orchid typed &prompt.user; lpr -P bamboo -d sushi-review.dvi the LPD system on orchid would copy the job to the spooling directory /var/spool/lpd/bamboo and note that it was a DVI job. As soon as the host rose has room in its bamboo spooling directory, the two LPDs would transfer the file to rose. The file would wait in rose's queue until it was finally printed. It would be converted from DVI to &postscript; (since bamboo is a &postscript; printer) on rose. Printers with Networked Data Stream Interfaces Often, when you buy a network interface card for a printer, you can get two versions: one which emulates a spooler (the more expensive version), or one which just lets you send data to it as if you were using a serial or parallel port (the cheaper version). This section tells how to use the cheaper version. For the more expensive one, see the previous section Printers Installed on Remote Hosts. The format of the /etc/printcap file lets you specify what serial or parallel interface to use, and (if you are using a serial interface), what baud rate, whether to use flow control, delays for tabs, conversion of newlines, and more. But there is no way to specify a connection to a printer that is listening on a TCP/IP or other network port. To send data to a networked printer, you need to develop a communications program that can be called by the text and conversion filters. Here is one such example: the script netprint takes all data on standard input and sends it to a network-attached printer. We specify the hostname of the printer as the first argument and the port number to which to connect as the second argument to netprint. Note that this supports one-way communication only (FreeBSD to printer); many network printers support two-way communication, and you might want to take advantage of that (to get printer status, perform accounting, etc.). #!/usr/bin/perl # # netprint - Text filter for printer attached to network # Installed in /usr/local/libexec/netprint # $#ARGV eq 1 || die "Usage: $0 <printer-hostname> <port-number>"; $printer_host = $ARGV[0]; $printer_port = $ARGV[1]; require 'sys/socket.ph'; ($ignore, $ignore, $protocol) = getprotobyname('tcp'); ($ignore, $ignore, $ignore, $ignore, $address) = gethostbyname($printer_host); $sockaddr = pack('S n a4 x8', &AF_INET, $printer_port, $address); socket(PRINTER, &PF_INET, &SOCK_STREAM, $protocol) || die "Can't create TCP/IP stream socket: $!"; connect(PRINTER, $sockaddr) || die "Can't contact $printer_host: $!"; while (<STDIN>) { print PRINTER; } exit 0; We can then use this script in various filters. Suppose we had a Diablo 750-N line printer connected to the network. The printer accepts data to print on port number 5100. The host name of the printer is scrivener. Here is the text filter for the printer: #!/bin/sh # # diablo-if-net - Text filter for Diablo printer `scrivener' listening # on port 5100. Installed in /usr/local/libexec/diablo-if-net # exec /usr/libexec/lpr/lpf "$@" | /usr/local/libexec/netprint scrivener 5100 Restricting Printer Usage printers restricting access to This section gives information on restricting printer usage. The LPD system lets you control who can access a printer, both locally or remotely, whether they can print multiple copies, how large their jobs can be, and how large the printer queues can get. Restricting Multiple Copies The LPD system makes it easy for users to print multiple copies of a file. Users can print jobs with lpr -#5 (for example) and get five copies of each file in the job. Whether this is a good thing is up to you. If you feel multiple copies cause unnecessary wear and tear on your printers, you can disable the option to &man.lpr.1; by adding the sc capability to the /etc/printcap file. When users submit jobs with the option, they will see: lpr: multiple copies are not allowed Note that if you have set up access to a printer remotely (see section Printers Installed on Remote Hosts), you need the sc capability on the remote /etc/printcap files as well, or else users will still be able to submit multiple-copy jobs by using another host. Here is an example. This is the /etc/printcap file for the host rose. The printer rattan is quite hearty, so we will allow multiple copies, but the laser printer bamboo is a bit more delicate, so we will disable multiple copies by adding the sc capability: # # /etc/printcap for host rose - restrict multiple copies on bamboo # rattan|line|diablo|lp|Diablo 630 Line Printer:\ :sh:sd=/var/spool/lpd/rattan:\ :lp=/dev/lpt0:\ :if=/usr/local/libexec/if-simple: bamboo|ps|PS|S|panasonic|Panasonic KX-P4455 PostScript v51.4:\ :sh:sd=/var/spool/lpd/bamboo:sc:\ :lp=/dev/ttyd5:ms#-parenb cs8 clocal crtscts:rw:\ :if=/usr/local/libexec/psif:\ :df=/usr/local/libexec/psdf: Now, we also need to add the sc capability on the host orchid's /etc/printcap (and while we are at it, let us disable multiple copies for the printer teak): # # /etc/printcap for host orchid - no multiple copies for local # printer teak or remote printer bamboo teak|hp|laserjet|Hewlett Packard LaserJet 3Si:\ :lp=/dev/lpt0:sd=/var/spool/lpd/teak:mx#0:sc:\ :if=/usr/local/libexec/ifhp:\ :vf=/usr/local/libexec/vfhp:\ :of=/usr/local/libexec/ofhp: rattan|line|diablo|lp|Diablo 630 Line Printer:\ :lp=:rm=rose:rp=rattan:sd=/var/spool/lpd/rattan: bamboo|ps|PS|S|panasonic|Panasonic KX-P4455 PostScript v51.4:\ :lp=:rm=rose:rp=bamboo:sd=/var/spool/lpd/bamboo:sc: By using the sc capability, we prevent the use of lpr -#, but that still does not prevent users from running &man.lpr.1; multiple times, or from submitting the same file multiple times in one job like this: &prompt.user; lpr forsale.sign forsale.sign forsale.sign forsale.sign forsale.sign There are many ways to prevent this abuse (including ignoring it) which you are free to explore. Restricting Access to Printers You can control who can print to what printers by using the &unix; group mechanism and the rg capability in /etc/printcap. Just place the users you want to have access to a printer in a certain group, and then name that group in the rg capability. Users outside the group (including root) will be greeted with lpr: Not a member of the restricted group if they try to print to the controlled printer. As with the sc (suppress multiple copies) capability, you need to specify rg on remote hosts that also have access to your printers, if you feel it is appropriate (see section Printers Installed on Remote Hosts). For example, we will let anyone access the printer rattan, but only those in group artists can use bamboo. Here is the familiar /etc/printcap for host rose: # # /etc/printcap for host rose - restricted group for bamboo # rattan|line|diablo|lp|Diablo 630 Line Printer:\ :sh:sd=/var/spool/lpd/rattan:\ :lp=/dev/lpt0:\ :if=/usr/local/libexec/if-simple: bamboo|ps|PS|S|panasonic|Panasonic KX-P4455 PostScript v51.4:\ :sh:sd=/var/spool/lpd/bamboo:sc:rg=artists:\ :lp=/dev/ttyd5:ms#-parenb cs8 clocal crtscts:rw:\ :if=/usr/local/libexec/psif:\ :df=/usr/local/libexec/psdf: Let us leave the other example /etc/printcap file (for the host orchid) alone. Of course, anyone on orchid can print to bamboo. It might be the case that we only allow certain logins on orchid anyway, and want them to have access to the printer. Or not. There can be only one restricted group per printer. Controlling Sizes of Jobs Submitted print jobs If you have many users accessing the printers, you probably need to put an upper limit on the sizes of the files users can submit to print. After all, there is only so much free space on the filesystem that houses the spooling directories, and you also need to make sure there is room for the jobs of other users. print jobs controlling LPD enables you to limit the maximum byte size a file in a job can be with the mx capability. The units are in BUFSIZ blocks, which are 1024 bytes. If you put a zero for this capability, there will be no limit on file size; however, if no mx capability is specified, then a default limit of 1000 blocks will be used. The limit applies to files in a job, and not the total job size. LPD will not refuse a file that is larger than the limit you place on a printer. Instead, it will queue as much of the file up to the limit, which will then get printed. The rest will be discarded. Whether this is correct behavior is up for debate. Let us add limits to our example printers rattan and bamboo. Since those artists' &postscript; files tend to be large, we will limit them to five megabytes. We will put no limit on the plain text line printer: # # /etc/printcap for host rose # # # No limit on job size: # rattan|line|diablo|lp|Diablo 630 Line Printer:\ :sh:mx#0:sd=/var/spool/lpd/rattan:\ :lp=/dev/lpt0:\ :if=/usr/local/libexec/if-simple: # # Limit of five megabytes: # bamboo|ps|PS|S|panasonic|Panasonic KX-P4455 PostScript v51.4:\ :sh:sd=/var/spool/lpd/bamboo:sc:rg=artists:mx#5000:\ :lp=/dev/ttyd5:ms#-parenb cs8 clocal crtscts:rw:\ :if=/usr/local/libexec/psif:\ :df=/usr/local/libexec/psdf: Again, the limits apply to the local users only. If you have set up access to your printers remotely, remote users will not get those limits. You will need to specify the mx capability in the remote /etc/printcap files as well. See section Printers Installed on Remote Hosts for more information on remote printing. There is another specialized way to limit job sizes from remote printers; see section Restricting Jobs from Remote Printers. Restricting Jobs from Remote Printers The LPD spooling system provides several ways to restrict print jobs submitted from remote hosts: Host restrictions You can control from which remote hosts a local LPD accepts requests with the files /etc/hosts.equiv and /etc/hosts.lpd. LPD checks to see if an incoming request is from a host listed in either one of these files. If not, LPD refuses the request. The format of these files is simple: one host name per line. Note that the file /etc/hosts.equiv is also used by the &man.ruserok.3; protocol, and affects programs like &man.rsh.1; and &man.rcp.1;, so be careful. For example, here is the /etc/hosts.lpd file on the host rose: orchid violet madrigal.fishbaum.de This means rose will accept requests from the hosts orchid, violet, and madrigal.fishbaum.de. If any other host tries to access rose's LPD, the job will be refused. Size restrictions You can control how much free space there needs to remain on the filesystem where a spooling directory resides. Make a file called minfree in the spooling directory for the local printer. Insert in that file a number representing how many disk blocks (512 bytes) of free space there has to be for a remote job to be accepted. This lets you insure that remote users will not fill your filesystem. You can also use it to give a certain priority to local users: they will be able to queue jobs long after the free disk space has fallen below the amount specified in the minfree file. For example, let us add a minfree file for the printer bamboo. We examine /etc/printcap to find the spooling directory for this printer; here is bamboo's entry: bamboo|ps|PS|S|panasonic|Panasonic KX-P4455 PostScript v51.4:\ :sh:sd=/var/spool/lpd/bamboo:sc:rg=artists:mx#5000:\ :lp=/dev/ttyd5:ms#-parenb cs8 clocal crtscts:rw:mx#5000:\ :if=/usr/local/libexec/psif:\ :df=/usr/local/libexec/psdf: The spooling directory is given in the sd capability. We will make three megabytes (which is 6144 disk blocks) the amount of free disk space that must exist on the filesystem for LPD to accept remote jobs: &prompt.root; echo 6144 > /var/spool/lpd/bamboo/minfree User restrictions You can control which remote users can print to local printers by specifying the rs capability in /etc/printcap. When rs appears in the entry for a locally-attached printer, LPD will accept jobs from remote hosts if the user submitting the job also has an account of the same login name on the local host. Otherwise, LPD refuses the job. This capability is particularly useful in an environment where there are (for example) different departments sharing a network, and some users transcend departmental boundaries. By giving them accounts on your systems, they can use your printers from their own departmental systems. If you would rather allow them to use only your printers and not your computer resources, you can give them token accounts, with no home directory and a useless shell like /usr/bin/false. Accounting for Printer Usage accounting printer So, you need to charge for printouts. And why not? Paper and ink cost money. And then there are maintenance costs—printers are loaded with moving parts and tend to break down. You have examined your printers, usage patterns, and maintenance fees and have come up with a per-page (or per-foot, per-meter, or per-whatever) cost. Now, how do you actually start accounting for printouts? Well, the bad news is the LPD spooling system does not provide much help in this department. Accounting is highly dependent on the kind of printer in use, the formats being printed, and your requirements in charging for printer usage. To implement accounting, you have to modify a printer's text filter (to charge for plain text jobs) and the conversion filters (to charge for other file formats), to count pages or query the printer for pages printed. You cannot get away with using the simple output filter, since it cannot do accounting. See section Filters. Generally, there are two ways to do accounting: Periodic accounting is the more common way, possibly because it is easier. Whenever someone prints a job, the filter logs the user, host, and number of pages to an accounting file. Every month, semester, year, or whatever time period you prefer, you collect the accounting files for the various printers, tally up the pages printed by users, and charge for usage. Then you truncate all the logging files, starting with a clean slate for the next period. Timely accounting is less common, probably because it is more difficult. This method has the filters charge users for printouts as soon as they use the printers. Like disk quotas, the accounting is immediate. You can prevent users from printing when their account goes in the red, and might provide a way for users to check and adjust their print quotas. But this method requires some database code to track users and their quotas. The LPD spooling system supports both methods easily: since you have to provide the filters (well, most of the time), you also have to provide the accounting code. But there is a bright side: you have enormous flexibility in your accounting methods. For example, you choose whether to use periodic or timely accounting. You choose what information to log: user names, host names, job types, pages printed, square footage of paper used, how long the job took to print, and so forth. And you do so by modifying the filters to save this information. Quick and Dirty Printer Accounting FreeBSD comes with two programs that can get you set up with simple periodic accounting right away. They are the text filter lpf, described in section lpf: a Text Filter, and &man.pac.8;, a program to gather and total entries from printer accounting files. As mentioned in the section on filters (Filters), LPD starts the text and the conversion filters with the name of the accounting file to use on the filter command line. The filters can use this argument to know where to write an accounting file entry. The name of this file comes from the af capability in /etc/printcap, and if not specified as an absolute path, is relative to the spooling directory. LPD starts lpf with page width and length arguments (from the pw and pl capabilities). lpf uses these arguments to determine how much paper will be used. After sending the file to the printer, it then writes an accounting entry in the accounting file. The entries look like this: 2.00 rose:andy 3.00 rose:kelly 3.00 orchid:mary 5.00 orchid:mary 2.00 orchid:zhang You should use a separate accounting file for each printer, as lpf has no file locking logic built into it, and two lpfs might corrupt each other's entries if they were to write to the same file at the same time. An easy way to insure a separate accounting file for each printer is to use af=acct in /etc/printcap. Then, each accounting file will be in the spooling directory for a printer, in a file named acct. When you are ready to charge users for printouts, run the &man.pac.8; program. Just change to the spooling directory for the printer you want to collect on and type pac. You will get a dollar-centric summary like the following: Login pages/feet runs price orchid:kelly 5.00 1 $ 0.10 orchid:mary 31.00 3 $ 0.62 orchid:zhang 9.00 1 $ 0.18 rose:andy 2.00 1 $ 0.04 rose:kelly 177.00 104 $ 3.54 rose:mary 87.00 32 $ 1.74 rose:root 26.00 12 $ 0.52 total 337.00 154 $ 6.74 These are the arguments &man.pac.8; expects: Which printer to summarize. This option works only if there is an absolute path in the af capability in /etc/printcap. Sort the output by cost instead of alphabetically by user name. Ignore host name in the accounting files. With this option, user smith on host alpha is the same user smith on host gamma. Without, they are different users. Compute charges with price dollars per page or per foot instead of the price from the pc capability in /etc/printcap, or two cents (the default). You can specify price as a floating point number. Reverse the sort order. Make an accounting summary file and truncate the accounting file. name Print accounting information for the given user names only. In the default summary that &man.pac.8; produces, you see the number of pages printed by each user from various hosts. If, at your site, host does not matter (because users can use any host), run pac -m, to produce the following summary: Login pages/feet runs price andy 2.00 1 $ 0.04 kelly 182.00 105 $ 3.64 mary 118.00 35 $ 2.36 root 26.00 12 $ 0.52 zhang 9.00 1 $ 0.18 total 337.00 154 $ 6.74 To compute the dollar amount due, &man.pac.8; uses the pc capability in the /etc/printcap file (default of 200, or 2 cents per page). Specify, in hundredths of cents, the price per page or per foot you want to charge for printouts in this capability. You can override this value when you run &man.pac.8; with the option. The units for the option are in dollars, though, not hundredths of cents. For example, &prompt.root; pac -p1.50 makes each page cost one dollar and fifty cents. You can really rake in the profits by using this option. Finally, running pac -s will save the summary information in a summary accounting file, which is named the same as the printer's accounting file, but with _sum appended to the name. It then truncates the accounting file. When you run &man.pac.8; again, it rereads the summary file to get starting totals, then adds information from the regular accounting file. How Can You Count Pages Printed? In order to perform even remotely accurate accounting, you need to be able to determine how much paper a job uses. This is the essential problem of printer accounting. For plain text jobs, the problem is not that hard to solve: you count how many lines are in a job and compare it to how many lines per page your printer supports. Do not forget to take into account backspaces in the file which overprint lines, or long logical lines that wrap onto one or more additional physical lines. The text filter lpf (introduced in lpf: a Text Filter) takes into account these things when it does accounting. If you are writing a text filter which needs to do accounting, you might want to examine lpf's source code. How do you handle other file formats, though? Well, for DVI-to-LaserJet or DVI-to-&postscript; conversion, you can have your filter parse the diagnostic output of dvilj or dvips and look to see how many pages were converted. You might be able to do similar things with other file formats and conversion programs. But these methods suffer from the fact that the printer may not actually print all those pages. For example, it could jam, run out of toner, or explode—and the user would still get charged. So, what can you do? There is only one sure way to do accurate accounting. Get a printer that can tell you how much paper it uses, and attach it via a serial line or a network connection. Nearly all &postscript; printers support this notion. Other makes and models do as well (networked Imagen laser printers, for example). Modify the filters for these printers to get the page usage after they print each job and have them log accounting information based on that value only. There is no line counting nor error-prone file examination required. Of course, you can always be generous and make all printouts free. Using Printers printers usage This section tells you how to use printers you have set up with FreeBSD. Here is an overview of the user-level commands: &man.lpr.1; Print jobs &man.lpq.1; Check printer queues &man.lprm.1; Remove jobs from a printer's queue There is also an administrative command, &man.lpc.8;, described in the section Administering Printers, used to control printers and their queues. All three of the commands &man.lpr.1;, &man.lprm.1;, and &man.lpq.1; accept an option to specify on which printer/queue to operate, as listed in the /etc/printcap file. This enables you to submit, remove, and check on jobs for various printers. If you do not use the option, then these commands use the printer specified in the PRINTER environment variable. Finally, if you do not have a PRINTER environment variable, these commands default to the printer named lp. Hereafter, the terminology default printer means the printer named in the PRINTER environment variable, or the printer named lp when there is no PRINTER environment variable. Printing Jobs To print files, type: &prompt.user; lpr filename ... printing This prints each of the listed files to the default printer. If you list no files, &man.lpr.1; reads data to print from standard input. For example, this command prints some important system files: &prompt.user; lpr /etc/host.conf /etc/hosts.equiv To select a specific printer, type: &prompt.user; lpr -P printer-name filename ... This example prints a long listing of the current directory to the printer named rattan: &prompt.user; ls -l | lpr -P rattan Because no files were listed for the &man.lpr.1; command, lpr read the data to print from standard input, which was the output of the ls -l command. The &man.lpr.1; command can also accept a wide variety of options to control formatting, apply file conversions, generate multiple copies, and so forth. For more information, see the section Printing Options. Checking Jobs print jobs When you print with &man.lpr.1;, the data you wish to print is put together in a package called a print job, which is sent to the LPD spooling system. Each printer has a queue of jobs, and your job waits in that queue along with other jobs from yourself and from other users. The printer prints those jobs in a first-come, first-served order. To display the queue for the default printer, type &man.lpq.1;. For a specific printer, use the option. For example, the command &prompt.user; lpq -P bamboo shows the queue for the printer named bamboo. Here is an example of the output of the lpq command: bamboo is ready and printing Rank Owner Job Files Total Size active kelly 9 /etc/host.conf, /etc/hosts.equiv 88 bytes 2nd kelly 10 (standard input) 1635 bytes 3rd mary 11 ... 78519 bytes This shows three jobs in the queue for bamboo. The first job, submitted by user kelly, got assigned job number 9. Every job for a printer gets a unique job number. Most of the time you can ignore the job number, but you will need it if you want to cancel the job; see section Removing Jobs for details. Job number nine consists of two files; multiple files given on the &man.lpr.1; command line are treated as part of a single job. It is the currently active job (note the word active under the Rank column), which means the printer should be currently printing that job. The second job consists of data passed as the standard input to the &man.lpr.1; command. The third job came from user mary; it is a much larger job. The pathname of the file she is trying to print is too long to fit, so the &man.lpq.1; command just shows three dots. The very first line of the output from &man.lpq.1; is also useful: it tells what the printer is currently doing (or at least what LPD thinks the printer is doing). The &man.lpq.1; command also support a option to generate a detailed long listing. Here is an example of lpq -l: waiting for bamboo to become ready (offline ?) kelly: 1st [job 009rose] /etc/host.conf 73 bytes /etc/hosts.equiv 15 bytes kelly: 2nd [job 010rose] (standard input) 1635 bytes mary: 3rd [job 011rose] /home/orchid/mary/research/venus/alpha-regio/mapping 78519 bytes Removing Jobs If you change your mind about printing a job, you can remove the job from the queue with the &man.lprm.1; command. Often, you can even use &man.lprm.1; to remove an active job, but some or all of the job might still get printed. To remove a job from the default printer, first use &man.lpq.1; to find the job number. Then type: &prompt.user; lprm job-number To remove the job from a specific printer, add the option. The following command removes job number 10 from the queue for the printer bamboo: &prompt.user; lprm -P bamboo 10 The &man.lprm.1; command has a few shortcuts: lprm - Removes all jobs (for the default printer) belonging to you. lprm user Removes all jobs (for the default printer) belonging to user. The superuser can remove other users' jobs; you can remove only your own jobs. lprm With no job number, user name, or appearing on the command line, &man.lprm.1; removes the currently active job on the default printer, if it belongs to you. The superuser can remove any active job. Just use the option with the above shortcuts to operate on a specific printer instead of the default. For example, the following command removes all jobs for the current user in the queue for the printer named rattan: &prompt.user; lprm -P rattan - If you are working in a networked environment, &man.lprm.1; will let you remove jobs only from the host from which the jobs were submitted, even if the same printer is available from other hosts. The following command sequence demonstrates this: &prompt.user; lpr -P rattan myfile &prompt.user; rlogin orchid &prompt.user; lpq -P rattan Rank Owner Job Files Total Size active seeyan 12 ... 49123 bytes 2nd kelly 13 myfile 12 bytes &prompt.user; lprm -P rattan 13 rose: Permission denied &prompt.user; logout &prompt.user; lprm -P rattan 13 dfA013rose dequeued cfA013rose dequeued Beyond Plain Text: Printing Options The &man.lpr.1; command supports a number of options that control formatting text, converting graphic and other file formats, producing multiple copies, handling of the job, and more. This section describes the options. Formatting and Conversion Options The following &man.lpr.1; options control formatting of the files in the job. Use these options if the job does not contain plain text or if you want plain text formatted through the &man.pr.1; utility. &tex; For example, the following command prints a DVI file (from the &tex; typesetting system) named fish-report.dvi to the printer named bamboo: &prompt.user; lpr -P bamboo -d fish-report.dvi These options apply to every file in the job, so you cannot mix (say) DVI and ditroff files together in a job. Instead, submit the files as separate jobs, using a different conversion option for each job. All of these options except and require conversion filters installed for the destination printer. For example, the option requires the DVI conversion filter. Section Conversion Filters gives details. Print cifplot files. Print DVI files. Print FORTRAN text files. Print plot data. Indent the output by number columns; if you omit number, indent by 8 columns. This option works only with certain conversion filters. Do not put any space between the and the number. Print literal text data, including control characters. Print ditroff (device independent troff) data. -p Format plain text with &man.pr.1; before printing. See &man.pr.1; for more information. Use title on the &man.pr.1; header instead of the file name. This option has effect only when used with the option. Print troff data. Print raster data. Here is an example: this command prints a nicely formatted version of the &man.ls.1; manual page on the default printer: &prompt.user; zcat /usr/share/man/man1/ls.1.gz | troff -t -man | lpr -t The &man.zcat.1; command uncompresses the source of the &man.ls.1; manual page and passes it to the &man.troff.1; command, which formats that source and makes GNU troff output and passes it to &man.lpr.1;, which submits the job to the LPD spooler. Because we used the option to &man.lpr.1;, the spooler will convert the GNU troff output into a format the default printer can understand when it prints the job. Job Handling Options The following options to &man.lpr.1; tell LPD to handle the job specially: -# copies Produce a number of copies of each file in the job instead of just one copy. An administrator may disable this option to reduce printer wear-and-tear and encourage photocopier usage. See section Restricting Multiple Copies. This example prints three copies of parser.c followed by three copies of parser.h to the default printer: &prompt.user; lpr -#3 parser.c parser.h -m Send mail after completing the print job. With this option, the LPD system will send mail to your account when it finishes handling your job. In its message, it will tell you if the job completed successfully or if there was an error, and (often) what the error was. -s Do not copy the files to the spooling directory, but make symbolic links to them instead. If you are printing a large job, you probably want to use this option. It saves space in the spooling directory (your job might overflow the free space on the filesystem where the spooling directory resides). It saves time as well since LPD will not have to copy each and every byte of your job to the spooling directory. There is a drawback, though: since LPD will refer to the original files directly, you cannot modify or remove them until they have been printed. If you are printing to a remote printer, LPD will eventually have to copy files from the local host to the remote host, so the option will save space only on the local spooling directory, not the remote. It is still useful, though. -r Remove the files in the job after copying them to the spooling directory, or after printing them with the option. Be careful with this option! Header Page Options These options to &man.lpr.1; adjust the text that normally appears on a job's header page. If header pages are suppressed for the destination printer, these options have no effect. See section Header Pages for information about setting up header pages. -C text Replace the hostname on the header page with text. The hostname is normally the name of the host from which the job was submitted. -J text Replace the job name on the header page with text. The job name is normally the name of the first file of the job, or stdin if you are printing standard input. -h Do not print any header page. At some sites, this option may have no effect due to the way header pages are generated. See Header Pages for details. Administering Printers As an administrator for your printers, you have had to install, set up, and test them. Using the &man.lpc.8; command, you can interact with your printers in yet more ways. With &man.lpc.8;, you can Start and stop the printers Enable and disable their queues Rearrange the order of the jobs in each queue. First, a note about terminology: if a printer is stopped, it will not print anything in its queue. Users can still submit jobs, which will wait in the queue until the printer is started or the queue is cleared. If a queue is disabled, no user (except root) can submit jobs for the printer. An enabled queue allows jobs to be submitted. A printer can be started for a disabled queue, in which case it will continue to print jobs in the queue until the queue is empty. In general, you have to have root privileges to use the &man.lpc.8; command. Ordinary users can use the &man.lpc.8; command to get printer status and to restart a hung printer only. Here is a summary of the &man.lpc.8; commands. Most of the commands take a printer-name argument to tell on which printer to operate. You can use all for the printer-name to mean all printers listed in /etc/printcap. abort printer-name Cancel the current job and stop the printer. Users can still submit jobs if the queue is enabled. clean printer-name Remove old files from the printer's spooling directory. Occasionally, the files that make up a job are not properly removed by LPD, particularly if there have been errors during printing or a lot of administrative activity. This command finds files that do not belong in the spooling directory and removes them. disable printer-name Disable queuing of new jobs. If the printer is running, it will continue to print any jobs remaining in the queue. The superuser (root) can always submit jobs, even to a disabled queue. This command is useful while you are testing a new printer or filter installation: disable the queue and submit jobs as root. Other users will not be able to submit jobs until you complete your testing and re-enable the queue with the enable command. down printer-name message Take a printer down. Equivalent to disable followed by stop. The message appears as the printer's status whenever a user checks the printer's queue with &man.lpq.1; or status with lpc status. enable printer-name Enable the queue for a printer. Users can submit jobs but the printer will not print anything until it is started. help command-name Print help on the command command-name. With no command-name, print a summary of the commands available. restart printer-name Start the printer. Ordinary users can use this command if some extraordinary circumstance hangs LPD, but they cannot start a printer stopped with either the stop or down commands. The restart command is equivalent to abort followed by start. start printer-name Start the printer. The printer will print jobs in its queue. stop printer-name Stop the printer. The printer will finish the current job and will not print anything else in its queue. Even though the printer is stopped, users can still submit jobs to an enabled queue. topq printer-name job-or-username Rearrange the queue for printer-name by placing the jobs with the listed job numbers or the jobs belonging to username at the top of the queue. For this command, you cannot use all as the printer-name. up printer-name Bring a printer up; the opposite of the down command. Equivalent to start followed by enable. &man.lpc.8; accepts the above commands on the command line. If you do not enter any commands, &man.lpc.8; enters an interactive mode, where you can enter commands until you type exit, quit, or end-of-file. Alternatives to the Standard Spooler If you have been reading straight through this manual, by now you have learned just about everything there is to know about the LPD spooling system that comes with FreeBSD. You can probably appreciate many of its shortcomings, which naturally leads to the question: What other spooling systems are out there (and work with FreeBSD)? LPRng LPRng LPRng, which purportedly means LPR: the Next Generation is a complete rewrite of PLP. Patrick Powell and Justin Mason (the principal maintainer of PLP) collaborated to make LPRng. The main site for LPRng is . CUPS CUPS CUPS, the Common UNIX Printing System, provides a portable printing layer for &unix;-based operating systems. It has been developed by Easy Software Products to promote a standard printing solution for all &unix; vendors and users. CUPS uses the Internet Printing Protocol (IPP) as the basis for managing print jobs and queues. The Line Printer Daemon (LPD), Server Message Block (SMB), and AppSocket (a.k.a. JetDirect) protocols are also supported with reduced functionality. CUPS adds network printer browsing and PostScript Printer Description (PPD) based printing options to support real-world printing under &unix;. The main site for CUPS is . Troubleshooting After performing the simple test with &man.lptest.1;, you might have gotten one of the following results instead of the correct printout: It worked, after awhile; or, it did not eject a full sheet. The printer printed the above, but it sat for awhile and did nothing. In fact, you might have needed to press a PRINT REMAINING or FORM FEED button on the printer to get any results to appear. If this is the case, the printer was probably waiting to see if there was any more data for your job before it printed anything. To fix this problem, you can have the text filter send a FORM FEED character (or whatever is necessary) to the printer. This is usually sufficient to have the printer immediately print any text remaining in its internal buffer. It is also useful to make sure each print job ends on a full sheet, so the next job does not start somewhere on the middle of the last page of the previous job. The following replacement for the shell script /usr/local/libexec/if-simple prints a form feed after it sends the job to the printer: #!/bin/sh # # if-simple - Simple text input filter for lpd # Installed in /usr/local/libexec/if-simple # # Simply copies stdin to stdout. Ignores all filter arguments. # Writes a form feed character (\f) after printing job. /bin/cat && printf "\f" && exit 0 exit 2 It produced the staircase effect. You got the following on paper: !"#$%&'()*+,-./01234 "#$%&'()*+,-./012345 #$%&'()*+,-./0123456 MS-DOS OS/2 ASCII You have become another victim of the staircase effect, caused by conflicting interpretations of what characters should indicate a new line. &unix; style operating systems use a single character: ASCII code 10, the line feed (LF). &ms-dos;, &os2;, and others uses a pair of characters, ASCII code 10 and ASCII code 13 (the carriage return or CR). Many printers use the &ms-dos; convention for representing new-lines. When you print with FreeBSD, your text used just the line feed character. The printer, upon seeing a line feed character, advanced the paper one line, but maintained the same horizontal position on the page for the next character to print. That is what the carriage return is for: to move the location of the next character to print to the left edge of the paper. Here is what FreeBSD wants your printer to do: Printer received CR Printer prints CR Printer received LF Printer prints CR + LF Here are some ways to achieve this: Use the printer's configuration switches or control panel to alter its interpretation of these characters. Check your printer's manual to find out how to do this. If you boot your system into other operating systems besides FreeBSD, you may have to reconfigure the printer to use a an interpretation for CR and LF characters that those other operating systems use. You might prefer one of the other solutions, below. Have FreeBSD's serial line driver automatically convert LF to CR+LF. Of course, this works with printers on serial ports only. To enable this feature, use the ms# capability and set the onlcr mode in the /etc/printcap file for the printer. Send an escape code to the printer to have it temporarily treat LF characters differently. Consult your printer's manual for escape codes that your printer might support. When you find the proper escape code, modify the text filter to send the code first, then send the print job. PCL Here is an example text filter for printers that understand the Hewlett-Packard PCL escape codes. This filter makes the printer treat LF characters as a LF and CR; then it sends the job; then it sends a form feed to eject the last page of the job. It should work with nearly all Hewlett Packard printers. #!/bin/sh # # hpif - Simple text input filter for lpd for HP-PCL based printers # Installed in /usr/local/libexec/hpif # # Simply copies stdin to stdout. Ignores all filter arguments. # Tells printer to treat LF as CR+LF. Ejects the page when done. printf "\033&k2G" && cat && printf "\033&l0H" && exit 0 exit 2 Here is an example /etc/printcap from a host called orchid. It has a single printer attached to its first parallel port, a Hewlett Packard LaserJet 3Si named teak. It is using the above script as its text filter: # # /etc/printcap for host orchid # teak|hp|laserjet|Hewlett Packard LaserJet 3Si:\ :lp=/dev/lpt0:sh:sd=/var/spool/lpd/teak:mx#0:\ :if=/usr/local/libexec/hpif: It overprinted each line. The printer never advanced a line. All of the lines of text were printed on top of each other on one line. This problem is the opposite of the staircase effect, described above, and is much rarer. Somewhere, the LF characters that FreeBSD uses to end a line are being treated as CR characters to return the print location to the left edge of the paper, but not also down a line. Use the printer's configuration switches or control panel to enforce the following interpretation of LF and CR characters: Printer receives Printer prints CR CR LF CR + LF The printer lost characters. While printing, the printer did not print a few characters in each line. The problem might have gotten worse as the printer ran, losing more and more characters. The problem is that the printer cannot keep up with the speed at which the computer sends data over a serial line (this problem should not occur with printers on parallel ports). There are two ways to overcome the problem: If the printer supports XON/XOFF flow control, have FreeBSD use it by specifying the ixon mode in the ms# capability. If the printer supports carrier flow control, specify the crtscts mode in the ms# capability. Make sure the cable connecting the printer to the computer is correctly wired for carrier flow control. It printed garbage. The printer printed what appeared to be random garbage, but not the desired text. This is usually another symptom of incorrect communications parameters with a serial printer. Double-check the bps rate in the br capability, and the parity setting in the ms# capability; make sure the printer is using the same settings as specified in the /etc/printcap file. Nothing happened. If nothing happened, the problem is probably within FreeBSD and not the hardware. Add the log file (lf) capability to the entry for the printer you are debugging in the /etc/printcap file. For example, here is the entry for rattan, with the lf capability: rattan|line|diablo|lp|Diablo 630 Line Printer:\ :sh:sd=/var/spool/lpd/rattan:\ :lp=/dev/lpt0:\ :if=/usr/local/libexec/if-simple:\ :lf=/var/log/rattan.log Then, try printing again. Check the log file (in our example, /var/log/rattan.log) to see any error messages that might appear. Based on the messages you see, try to correct the problem. If you do not specify a lf capability, LPD uses /dev/console as a default. diff --git a/zh_TW.Big5/books/handbook/users/chapter.sgml b/zh_TW.Big5/books/handbook/users/chapter.sgml index 216229dc9e..59efb0be88 100644 --- a/zh_TW.Big5/books/handbook/users/chapter.sgml +++ b/zh_TW.Big5/books/handbook/users/chapter.sgml @@ -1,1112 +1,960 @@ Neil Blakey-Milner Contributed by 使用者與基本帳號管理 概述 - FreeBSD 允許多個使用者同時使用電腦。當然,這並不是很多人同時坐在同一台電腦前 + FreeBSD 允許多個使用者同時使用電腦。 當然, + 這並不是很多人同時坐在同一台電腦前 Well..除非您連接 multiple terminals,這種情況我們會在 講到。 ,而是其他使用者可以透過網路來使用同一台電腦以完成他們的工作。 要使用系統的話,那麼每個人都得有一個帳號。 讀完這章,您將了解: 在 FreeBSD 系統上不同帳號之間的區別。 如何增加帳號。 如何刪除帳號。 - 如何更改帳號的基本資料,像是帳號全名,或是使用的 shell 種類。 + 如何更改帳號的基本資料,像是帳號全名,或是使用的 shell + 種類。 - 如何針對帳號、群組來設限,比如:允許存取記憶體或 CPU 資源多寡等。 + 如何針對帳號、群組來設限,比如:允許存取記憶體或 CPU + 資源多寡等。 如何運用群組,來更容易地管理帳號。 - 在閱讀這章之前,您應當了解: + 在開始閱讀這章之前,您需要: - 瞭解 &unix; 及 FreeBSD (瞭解 &unix; 及 FreeBSD ()的基礎概念。 介紹 - 系統的所有存取是經由帳號來進行,而所有的程式 process 是由使用者來進行,所以 - 使用者及帳號管理,乃是 FreeBSD 系統上不可或缺的重點。 + 系統的所有存取是經由帳號來進行,而所有的程式 process + 是由使用者來進行,所以使用者及帳號的管理,乃是 FreeBSD + 系統上不可或缺的重點。 - Every account on a FreeBSD system has certain information associated - with it to identify the account. + 所有於 FreeBSD 系統中的帳號皆包含下列相關資訊用來辨識身份。 - User name + 使用者名稱 - The user name as it would be typed at the - login: prompt. User names must be unique across - the computer; you may not have two users with the same - user name. There are a number of rules for creating valid user - names, documented in &man.passwd.5;; you would typically use user - names that consist of eight or fewer all lower case - characters. + 使用者名稱要輸入在 login: 提示出現後。 + 使用者名稱必須是獨一無二, + 不能有重複的使用者名稱。 + 至於如何建立有效使用者名稱的規則,請參閱 &man.passwd.5; 說明, + 通常使用者名稱是以八個以內的小寫字母所組成。 - Password + 密碼 - Each account has a password associated with it. The password - may be blank, in which case no password will be required to access - the system. This is normally a very bad idea; every account - should have a password. + 每個帳號都可擁有一組密碼。 密碼也可以不設, + 如此就不需密碼即可登入系統,但通常這並非妙策, + 每個帳號都應設定一組密碼。 - User ID (UID) + 使用者代號 (User ID, UID) - The UID is a number, traditionally from 0 to 65535 - It is possible to use UID/GIDs as large as - 4294967295, but such IDs can cause serious problems - with software that makes assumptions about the values - of IDs. - , used to uniquely identify - the user to the system. Internally, FreeBSD uses the UID to - identify users—any FreeBSD commands that allow you to - specify a user name will convert it to the UID before working with - it. This means that you can have several accounts with different - user names but the same UID. As far as FreeBSD is concerned these - accounts are one user. It is unlikely you will ever need to do - this. + UID 是系統用來辨識使用者的數字,通常範圍是從 0 到 65535 + UID/GID 最大可使用至 4294967295,但這樣的 ID + 可能會對已假設範圍的軟體造成嚴重問題。 + 。 FreeBSD 內部是使用 UID 來辨識使用者 — + FreeBSD 在執行任何指定使用者的指令之前,都會先把使用者名稱轉換為 + UID。 也就是說,比如可以有數個不同的使用者名稱, + 但是都使用同一個 UID,對 FreeBSD 來說,這些帳號都只代表同一使用者。 + 不過,實際上需要這樣做的可能性不大。 - Group ID (GID) + 群組代號 (Group ID, GID) - The GID is a number, traditionally from 0 to 65535, used to uniquely identify - the primary group that the user belongs to. Groups are a - mechanism for controlling access to resources based on a user's - GID rather than their UID. This can significantly reduce the size - of some configuration files. A user may also be in more than one - group. + GID 是系統用來辨識使用者所屬群組的數字,通常範圍是從 0 到 65535 + 。 用群組來控制資源存取,可有效減少一些設定檔的大小。 + 此外,使用者還可以同時屬於多個不同的群組。 - Login class + 登入分類(Login classes) - Login classes are an extension to the group mechanism that - provide additional flexibility when tailoring the system to - different users. + + 登入分類是群組的延伸機制, + 提供了不同的使用者更彈性的。 - Password change time + 密碼變更期限 - By default FreeBSD does not force users to change their - passwords periodically. You can enforce this on a per-user basis, - forcing some or all of your users to change their passwords after - a certain amount of time has elapsed. + FreeBSD 預設並不要求使用者週期性的更改密碼。您可以強制某些或 + 全部的使用者在指定的期間過後必須更改密碼。 - Account expiry time + 帳號期限 + - By default FreeBSD does not expire accounts. If you are - creating accounts that you know have a limited lifespan, for - example, in a school where you have accounts for the students, - then you can specify when the account expires. After the expiry - time has elapsed the account cannot be used to log in to the - system, although the account's directories and files will - remain. + FreeBSD 的帳號沒有預設的期限,如果您已知道帳號的使用期限, + 例如,學校中提供學生使用的帳號,可在建立帳號時指定帳號的期限。 + 當帳號過期後會無法登入系統,但該帳號的目錄及檔案則會保留。 - User's full name + 使用者全名 - The user name uniquely identifies the account to FreeBSD, but - does not necessarily reflect the user's real name. This - information can be associated with the account. + FreeBSD 的帳號使用使用者名稱用來辨識,但使用者名稱並不一定代表 + 真實使用者的姓名。為帳號所需的相關資訊。 - Home directory + 家目錄 - The home directory is the full path to a directory on the - system in which the user will start when logging on to the - system. A common convention is to put all user home directories - under - /home/username - or /usr/home/username. - The user would store their personal files in their home directory, - and any directories they may create in there. + 家目錄為使用者登入系統時的所在目錄的完整路徑。 + 通常會將所有使用者的家目錄放置於 + /home/使用者名稱 + 或 /usr/home/使用者名稱。 + 使用者可以將其個人的資料放置於其家目錄之中,並可以在此目錄底下 + 建立新的目錄 - User shell + 使用者 Shell - The shell provides the default environment users use to - interact with the system. There are many different kinds of - shells, and experienced users will have their own preferences, - which can be reflected in their account settings. + Shell 提供預設的環境讓使用者與系統互動。 + Shell 擁有數種不同的種類, 可供進階使用者依使用習慣選擇。 - - There are three main types of accounts: the Superuser, system users, and user accounts. The Superuser - account, usually called root, is used to - manage the system with no limitations on privileges. System - users run services. Finally, user accounts are used by real - people, who log on, read mail, and so forth. + + 帳號主要分為下列三類: 系統管理者帳號, 系統帳號,及 使用者帳號。 系統管理者帳號的帳號 + 通常為 root,擁有最大的權限來管理系統。 + 系統帳號用來執行伺服器服務。最後,使用者帳號供真正的使用者使用, + 可登入、讀信等等。 - The Superuser Account + 系統管理者帳號 accounts superuser (root) The superuser account, usually called root, comes preconfigured to facilitate system administration, and should not be used for day-to-day tasks like sending and receiving mail, general exploration of the system, or programming. This is because the superuser, unlike normal user accounts, can operate without limits, and misuse of the superuser account may result in spectacular disasters. User accounts are unable to destroy the system by mistake, so it is generally best to use normal user accounts whenever possible, unless you especially need the extra privilege. You should always double and triple-check commands you issue as the superuser, since an extra space or missing character can mean irreparable data loss. So, the first thing you should do after reading this chapter is to create an unprivileged user account for yourself for general usage if you have not already. This applies equally whether you are running a multi-user or single-user machine. Later in this chapter, we discuss how to create additional accounts, and how to change between the normal user and superuser. - System Accounts + 系統帳號 accounts system System users are those used to run services such as DNS, mail, web servers, and so forth. The reason for this is security; if all services ran as the superuser, they could act without restriction. accounts daemon accounts operator Examples of system users are daemon, operator, bind (for the Domain Name Service), news, and www. accounts nobody nobody is the generic unprivileged system user. However, it is important to keep in mind that the more services that use nobody, the more files and processes that user will become associated with, and hence the more privileged that user becomes. - User Accounts + 使用者帳號 accounts user User accounts are the primary means of access for real people to the system, and these accounts insulate the user and the environment, preventing the users from damaging the system or other users, and allowing users to customize their environment without affecting others. Every person accessing your system should have a unique user account. This allows you to find out who is doing what, prevent people from clobbering each others' settings or reading each others' mail, and so forth. Each user can set up their own environment to accommodate their use of the system, by using alternate shells, editors, key bindings, and language. - Modifying Accounts + 更改帳號 accounts modifying - There are a variety of different commands available in the - &unix; environment to manipulate user accounts. The most common - commands are summarized below, followed by more detailed - examples of their usage. + 在 &unix; 的環境之中提供了各式不同的指令管理使用者帳號, + 以下為較常使用的指令摘要及更詳細的使用範例。 + - Command - Summary + 指令 + 摘要 &man.adduser.8; - The recommended command-line application for adding - new users. + 新增使用者。 &man.rmuser.8; - The recommended command-line application for - removing users. + 移除使用者。 &man.chpass.1; - A flexible tool to change user database information. + 更改使用者資料。 &man.passwd.1; - The simple command-line tool to change user - passwords. + 更改使用者密碼。 &man.pw.8; - A powerful and flexible tool to modify all aspects - of user accounts. + 修改使用者的各種資料。 <command>adduser</command> accounts adding adduser /usr/share/skel skeleton directory - &man.adduser.8; is a simple program for - adding new users. It creates entries in the system - passwd and group - files. It will also create a home directory for the new user, - copy in the default configuration files (dotfiles) from - /usr/share/skel, and can optionally mail - the new user a welcome message. - - In &os; 5.0, &man.adduser.8; was rewritten from a - Perl script to a shell script that acts as wrapper around - &man.pw.8;, so its usage is slightly different on &os; 4.X - and &os; 5.X. - - To create the initial configuration file, use - adduser -s -config_create. - - The makes &man.adduser.8; - default to - quiet. We use later when we want to - change defaults. - - Next, we configure &man.adduser.8; - defaults, and create our first user account, since using - root for normal usage is evil and - nasty. + &man.adduser.8; 是一支新增使用者的簡單程式。 + 它會建立資料於系統的 passwd 與 + group + 檔案之中。 同時也會建立使用者的家目錄,從 + /usr/share/skel 複製預設的組態檔(dotfiles), + 並可以選擇性的郵件通知新使用者歡迎訊息。 - Configuring <command>adduser</command> and adding a - user on &os; 4.X - - &prompt.root; adduser -v -Use option ``-silent'' if you don't want to see all warnings and questions. -Check /etc/shells -Check /etc/master.passwd -Check /etc/group -Enter your default shell: csh date no sh tcsh zsh [sh]: zsh -Your default shell is: zsh -> /usr/local/bin/zsh -Enter your default HOME partition: [/home]: -Copy dotfiles from: /usr/share/skel no [/usr/share/skel]: -Send message from file: /etc/adduser.message no -[/etc/adduser.message]: no -Do not send message -Use passwords (y/n) [y]: y - -Write your changes to /etc/adduser.conf? (y/n) [n]: y - -Ok, let's go. -Don't worry about mistakes. I will give you the chance later to correct any input. -Enter username [a-z0-9_-]: jru -Enter full name []: J. Random User -Enter shell csh date no sh tcsh zsh [zsh]: -Enter home directory (full path) [/home/jru]: -Uid [1001]: -Enter login class: default []: -Login group jru [jru]: -Login group is ``jru''. Invite jru into other groups: guest no -[no]: wheel -Enter password []: -Enter password again []: - -Name: jru -Password: **** -Fullname: J. Random User -Uid: 1001 -Gid: 1001 (jru) -Class: -Groups: jru wheel -HOME: /home/jru -Shell: /usr/local/bin/zsh -OK? (y/n) [y]: y -Added user ``jru'' -Copy files from /usr/share/skel to /home/jru -Add another user? (y/n) [y]: n -Goodbye! -&prompt.root; - - - In summary, we changed the default shell to - zsh (an additional shell found in - the Ports Collection), and turned off the sending of a welcome mail to - added users. We then saved the configuration, - created an account for jru, and made - sure jru is in wheel - group (so that she may assume the role of - root with the &man.su.1; - command.) - - - The password you type in is not echoed, nor are asterisks - displayed. Make sure that you do not mistype the password. - - - - - Just use &man.adduser.8; without arguments - from now on, and you will not have to go through changing the - defaults. If the program asks you to change the defaults, - exit the program, and try the - option. - - - - Adding a user on &os; 5.X + 在 &os; 內新增使用者 &prompt.root; adduser Username: jru Full name: J. Random User Uid (Leave empty for default): Login group [jru]: Login group is jru. Invite jru into other groups? []: wheel Login class [default]: Shell (sh csh tcsh zsh nologin) [sh]: zsh Home directory [/home/jru]: Use password-based authentication? [yes]: Use an empty password? (yes/no) [no]: Use a random password? (yes/no) [no]: Enter password: Enter password again: Lock out the account after creation? [no]: Username : jru Password : **** Full Name : J. Random User Uid : 1001 Class : Groups : jru wheel Home : /home/jru Shell : /usr/local/bin/zsh Locked : no OK? (yes/no): yes adduser: INFO: Successfully added (jru) to the user database. Add another user? (yes/no): no Goodbye! &prompt.root; + + + 您輸入的密碼並不會回應到螢幕,所以不會以星號顯示 + 。 請確定您所輸入的密碼無誤。 + <command>rmuser</command> rmuser accounts removing - You can use &man.rmuser.8; to - completely remove a user from the system. - &man.rmuser.8; performs the following - steps: + 您可以使用 &man.rmuser.8; 來將使用者從系統之中完全移除 + &man.rmuser.8; 會執行以下動作: - Removes the user's &man.crontab.1; entry (if - any). + 移除該使用者的 &man.crontab.1; 資料 (如果存在)。 - Removes any &man.at.1; jobs belonging to the - user. + 移除所有屬於該使用者的 &man.at.1; 工作。 - Kills all processes owned by the user. + 中止所有該使用者擁有的程序。 - Removes the user from the system's local password - file. + 移除系統本機密碼檔中該使用者的資料。 - Removes the user's home directory (if it is owned by - the user). + 移除該使用者的家目錄 (如果為該使用者所有)。 - Removes the incoming mail files belonging to the user - from /var/mail. + 移除 /var/mail 中屬於該使用者的郵件。 - Removes all files owned by the user from temporary - file storage areas such as /tmp. + 移除暫存空間 (如: /tmp) 中所有屬於該使用者的檔案。 - Finally, removes the username from all groups to which - it belongs in /etc/group. - + 最後,在 /etc/group 檔內移除該使用者帳號。 + + - If a group becomes empty and the group name is the - same as the username, the group is removed; this - complements the per-user unique groups created by - &man.adduser.8;. + 若該群組已無成員,或者是群組名稱與該使用者名稱相同時, + 則群組將會被移除; 此操作會與 &man.adduser.8; + 所建立的帳號群組相對應。 - - &man.rmuser.8; cannot be used to remove - superuser accounts, since that is almost always an indication - of massive destruction. + &man.rmuser.8; 無法移除系統管理者帳號帳號, + 因為這即代表嚴重的破壞行為。 - By default, an interactive mode is used, which attempts to - make sure you know what you are doing. + 為了確認您的操作,預設採互動模式。 - <command>rmuser</command> Interactive Account Removal + <command>rmuser</command> 帳號移除 &prompt.root; rmuser jru Matching password entry: jru:*:1001:1001::0:0:J. Random User:/home/jru:/usr/local/bin/zsh Is this the entry you wish to remove? y Remove user's home directory (/home/jru)? y Updating password file, updating databases, done. Updating group file: trusted (removing group jru -- personal group is empty) done. Removing user's incoming mail file /var/mail/jru: done. Removing files belonging to jru from /tmp: done. Removing files belonging to jru from /var/tmp: done. Removing files belonging to jru from /var/tmp/vi.recover: done. &prompt.root; <command>chpass</command> chpass - &man.chpass.1; changes user database - information such as passwords, shells, and personal - information. + &man.chpass.1; 可更改使用者資料如: 密碼、Shell及個人資訊。 - Only system administrators, as the superuser, may change - other users' information and passwords with - &man.chpass.1;. + 僅系統管理者即系統管理者帳號可利用 &man.chpass.1; 更改其他使用者的資訊及密碼 - When passed no options, aside from an optional username, - &man.chpass.1; displays an editor - containing user information. When the user exists from the - editor, the user database is updated with the new - information. + 除了指定使用者名稱,當不加參數時,&man.chpass.1; 會將使用者資訊顯示於編輯器當中。 + 並於使用者離開編輯器時更新使用者資訊。 - In &os; 5.X, you will be asked for your password - after exiting the editor if you are not the superuser. + 若您並非系統管理者帳號,在離開編輯器前會詢問您的密碼。 - Interactive <command>chpass</command> by Superuser + 系統管理者帳號 <command>chpass</command> #Changing user database information for jru. Login: jru Password: * Uid [#]: 1001 Gid [# or name]: 1001 Change [month day year]: Expire [month day year]: Class: Home directory: /home/jru Shell: /usr/local/bin/zsh Full Name: J. Random User Office Location: Office Phone: Home Phone: Other information: - The normal user can change only a small subset of this - information, and only for themselves. + 一般使用者僅可更改自己的少部份資訊。 - Interactive <command>chpass</command> by Normal User + 一般使用者 <command>chpass</command> #Changing user database information for jru. Shell: /usr/local/bin/zsh Full Name: J. Random User Office Location: Office Phone: Home Phone: Other information: - &man.chfn.1; and &man.chsh.1; are - just links to &man.chpass.1;, as - are &man.ypchpass.1;, - &man.ypchfn.1;, and - &man.ypchsh.1;. NIS support is automatic, so - specifying the yp before the command is - not necessary. If this is confusing to you, do not worry, NIS will - be covered in . + &man.chfn.1; 與 &man.chsh.1; 即為 &man.chpass.1;,也同 + &man.ypchpass.1;、&man.ypchfn.1; 與 &man.ypchsh.1;。 + NIS 支援是自動的,所以無需在指令前加上 yp。 + 若這會困擾您,請不必擔心, 將函蓋 NIS 的部份的說明。 <command>passwd</command> passwd accounts changing password - &man.passwd.1; is the usual way to - change your own password as a user, or another user's password - as the superuser. + &man.passwd.1; 是更改密碼常用的方式,除了超級管理者可更改其他使用者的密碼外 + 使用者僅能更改自己的密碼。 - To prevent accidental or unauthorized changes, the original - password must be entered before a new password can be set. + 為了避免意外或未經同意的修改,在更新密碼前需輸入原密碼。 - Changing Your Password + 更改您的密碼 &prompt.user; passwd Changing local password for jru. Old password: New password: Retype new password: passwd: updating the database... passwd: done - Changing Another User's Password as the Superuser + 以系統管理者帳號去更改其他使用者的密碼 &prompt.root; passwd jru Changing local password for jru. New password: Retype new password: passwd: updating the database... passwd: done - As with &man.chpass.1;, - &man.yppasswd.1; is just a link to - &man.passwd.1;, so NIS works with either - command. + &man.chpass.1;、 + &man.yppasswd.1; 即為 &man.passwd.1;,皆支援 NIS。 <command>pw</command> pw - &man.pw.8; is a command line utility to create, remove, - modify, and display users and groups. It functions as a front - end to the system user and group files. &man.pw.8; - has a very powerful set of command line options that make it - suitable for use in shell scripts, but new users may find it - more complicated than the other commands presented - here. + &man.pw.8; 用來建立、移除、修改及查詢使用者及群組。 + 其功能即為系統使用者及群組檔案的前端。&man.pw.8; 擁有大量的指令參數 + 較適合使用於 shell script 中,對新手來說會此指令較其他指令複雜許多。 + - 對帳號的資源運用作限制 + 使用者資源限制 limiting users accounts limiting - If you have users, the ability to limit their system use may - have come to mind. FreeBSD provides - several ways an administrator can limit the amount of system - resources an individual may use. These limits are - divided into two sections: disk quotas, and other resource - limits. + + + 若您擁有許多使用者,接下會想到該如何限制使用的資源。 + FreeBSD 提供管理者許多方法來限制系統的資源給每個人使用。 + 這些限制分為兩個部份: 磁碟限額,以及其他資源限制。 + quotas limiting users quotas disk quotas - Disk quotas limit disk usage to users, and - they - provide a way to quickly check that usage without - calculating it every time. Quotas are discussed in . + 磁碟限額可以限制使用者的磁碟用量, + 它提供了一種方法可以快速的檢查並計算用量 + 而不需每次重新計算, + 關於磁碟限額將於 會討論。 - The other resource limits include ways to limit the amount of - CPU, memory, and other resources a user may consume. These are - defined using login classes and are discussed here. + 其他資源限制包含了 CPU、記憶體、以及其他每個使用者可使用 + 的資源做限制,這些限制可使用 Login class 來定義並於在本章討論。 /etc/login.conf - Login classes are defined in - /etc/login.conf. The precise semantics are - beyond the scope of this section, but are described in detail in the - &man.login.conf.5; manual page. It is sufficient to say that each - user is assigned to a login class (default by - default), and that each login class has a set of login capabilities - associated with it. A login capability is a - name=value - pair, where name is a well-known - identifier and value is an arbitrary - string processed accordingly depending on the name. Setting up login - classes and capabilities is rather straight-forward and is also - described in &man.login.conf.5;. + Login class 定義於 + /etc/login.conf。 明確語意不會在本節說明 + 但詳細的描述會在 &man.login.conf.5; 文件中。 每使用者預設被 + 分配到一個 Login class 中 (預設為 default), + 而每個 Login class 都有其資源的限制(Login capabilitiy)。 + Login capabilitiy 以 名稱= 成對, + 名稱 代表資源的種類,而 + 為任意的字串,為對應名稱的參數。 設定 Login class 及 Login capability 相當簡單,並同樣在 + &man.login.conf.5; 中詳細說明。 - The system does not normally read the configuration in - /etc/login.conf directly, but reads the database - file /etc/login.conf.db which provides - faster lookups. - To generate /etc/login.conf.db from - /etc/login.conf, execute the following - command: + 系統不會直接讀取 /etc/login.conf 的組態 + 而是讀取提供查詢較快的 /etc/login.conf.db 資料庫檔。 + 要從 /etc/login.conf 產生 /etc/login.conf.db + 需要執行以下指令: &prompt.root; cap_mkdb /etc/login.conf - Resource limits are different from plain vanilla login - capabilities in two ways. First, for every limit, there is a soft - (current) and hard limit. A soft limit may be adjusted by the user - or application, but may be no higher than the hard limit. The latter - may be lowered by the user, but never raised. Second, most resource - limits apply per process to a specific user, not the user as a whole. - Note, however, that these differences are mandated by the specific - handling of the limits, not by the implementation of the login - capability framework (i.e., they are not really - a special case of login capabilities). - - And so, without further ado, below are the most commonly used - resource limits (the rest, along with all the other login - capabilities, may be found in &man.login.conf.5;). + 資源限制於一般的 Login capability 有兩點不同。 + 第一,每種限制分為軟性限制及硬性限制。 + 軟性限制可由使用者或應用程式調整,但不能高於硬性限制。 + 後者限制可被使用者降低,但無法再提高。 + 第二,多數資源限制是針對每個使用者的個別行程限制,而不是使用者的所有行程。 + 注意,這些差異是由指定的限制程式托管,並非實作於 Login capability 的架構 + (例如,這些不是 真正 登入容量的特例)。 + + 另外,為了避免麻煩,以下為幾個常用的資源限制 + (剩下及其他的 Login capability 可在 &man.login.conf.5; 中找到說明)。 coredumpsize coredumpsize limiting users coredumpsize The limit on the size of a core file generated by a program is, for obvious reasons, subordinate to other limits on disk usage (e.g., filesize, or disk quotas). Nevertheless, it is often used as a less-severe method of controlling disk space consumption: since users do not generate core files themselves, and often do not delete them, setting this may save them from running out of disk space should a large program (e.g., emacs) crash. cputime cputime limiting users cputime This is the maximum amount of CPU time a user's process may - consume. Offending processes will be killed by the kernel. + consume. Offending processes will be killed by the kernel. This is a limit on CPU time consumed, not percentage of the CPU as displayed in some fields by &man.top.1; and &man.ps.1;. A limit on the latter is, at the time of this writing, not possible, and would be rather useless: a compiler—probably a legitimate task—can easily use almost 100% of a CPU for some time. - filesize filesize limiting users filesize This is the maximum size of a file the user may possess. Unlike disk quotas, this limit is enforced on individual files, not the set of all files a user owns. maxproc maxproc limiting users maxproc This is the maximum number of processes a user may be running. This includes foreground and background processes alike. For obvious reasons, this may not be larger than the system limit specified by the kern.maxproc &man.sysctl.8;. Also note that setting this too small may hinder a user's productivity: it is often useful to be logged in multiple times or execute pipelines. Some tasks, such as compiling a large program, also spawn multiple processes (e.g., &man.make.1;, &man.cc.1;, and other intermediate preprocessors). memorylocked memorylocked limiting users memorylocked This is the maximum amount a memory a process may have requested to be locked into main memory (e.g., see &man.mlock.2;). Some system-critical programs, such as &man.amd.8;, lock into main memory such that in the event of being swapped out, they do not contribute to a system's trashing in time of trouble. memoryuse memoryuse limiting users memoryuse This is the maximum amount of memory a process may consume at any given time. It includes both core memory and swap usage. This is not a catch-all limit for restricting memory consumption, but it is a good start. openfiles openfiles limiting users openfiles This is the maximum amount of files a process may have open. In FreeBSD, files are also used to represent sockets and IPC channels; thus, be careful not to set this too low. The system-wide limit for this is defined by the kern.maxfiles &man.sysctl.8;. sbsize sbsize limiting users sbsize This is the limit on the amount of network memory, and thus mbufs, a user may consume. This originated as a response to an old DoS attack by creating a lot of sockets, but can be generally used to limit network communications. stacksize stacksize limiting users stacksize This is the maximum size a process' stack may grow to. This alone is not sufficient to limit the amount of memory a program may use; consequently, it should be used in conjunction with other limits. There are a few other things to remember when setting resource limits. Following are some general tips, suggestions, and miscellaneous comments. Processes started at system startup by /etc/rc are assigned to the daemon login class. Although the /etc/login.conf that comes with the system is a good source of reasonable values for most limits, only you, the administrator, can know what is appropriate for your system. Setting a limit too high may open your system up to abuse, while setting it too low may put a strain on productivity. Users of the X Window System (X11) should probably be granted more resources than other users. X11 by itself takes a lot of resources, but it also encourages users to run more programs simultaneously. Remember that many limits apply to individual processes, not the user as a whole. For example, setting openfiles to 50 means that each process the user runs may open up to 50 files. Thus, the gross amount of files a user may open is the value of openfiles multiplied by the value of maxproc. This also applies to memory consumption. For further information on resource limits and login classes and capabilities in general, please consult the relevant manual pages: &man.cap.mkdb.1;, &man.getrlimit.2;, &man.login.conf.5;. - Groups + 群組 groups /etc/groups accounts groups A group is simply a list of users. Groups are identified by their group name and GID (Group ID). In FreeBSD (and most other &unix; like systems), the two factors the kernel uses to decide whether a process is allowed to do something is its user ID and list of groups it belongs to. Unlike a user ID, a process has a list of groups associated with it. You may hear some things refer to the group ID of a user or process; most of the time, this just means the first group in the list. The group name to group ID map is in /etc/group. This is a plain text file with four colon-delimited fields. The first field is the group name, the second is the encrypted password, the third the group ID, and the fourth the comma-delimited list of members. It can safely be edited by hand (assuming, of course, that you do not make any syntax errors!). For a more complete description of the syntax, see the &man.group.5; manual page. If you do not want to edit /etc/group manually, you can use the &man.pw.8; command to add and edit groups. For example, to add a group called teamtwo and then confirm that it exists you can use: Adding a Group Using &man.pw.8; &prompt.root; pw groupadd teamtwo &prompt.root; pw groupshow teamtwo teamtwo:*:1100: The number 1100 above is the group ID of the group teamtwo. Right now, teamtwo has no members, and is thus rather useless. Let's change that by inviting jru to the teamtwo group. Adding Somebody to a Group Using &man.pw.8; &prompt.root; pw groupmod teamtwo -M jru &prompt.root; pw groupshow teamtwo teamtwo:*:1100:jru The argument to the option is a comma-delimited list of users who are members of the group. From the preceding sections, we know that the password file also contains a group for each user. The latter (the user) is automatically added to the group list by the system; the user will not show up as a member when using the command to &man.pw.8;, but will show up when the information is queried via &man.id.1; or similar tool. In other words, &man.pw.8; only manipulates the /etc/group file; it will never attempt to read additionally data from /etc/passwd. Using &man.id.1; to Determine Group Membership &prompt.user; id jru uid=1001(jru) gid=1001(jru) groups=1001(jru), 1100(teamtwo) As you can see, jru is a member of the groups jru and teamtwo. For more information about &man.pw.8;, see its manual page, and for more information on the format of /etc/group, consult the &man.group.5; manual page. diff --git a/zh_TW.Big5/books/porters-handbook/book.sgml b/zh_TW.Big5/books/porters-handbook/book.sgml index 1611137383..90cf5ca7b7 100644 --- a/zh_TW.Big5/books/porters-handbook/book.sgml +++ b/zh_TW.Big5/books/porters-handbook/book.sgml @@ -1,12426 +1,12422 @@ %books.ent; ]> FreeBSD Porter's Handbook FreeBSD 文件計劃 April 2000 2000 2001 2002 2003 2004 2005 2006 2007 FreeBSD 文件計劃 &bookinfo.trademarks; &bookinfo.legalnotice; 楔子 幾乎每個 FreeBSD 愛用者都是透過 FreeBSD Ports Collection 來裝各式應用程式("ports")。如同 FreeBSD 的其他部分一樣, 這些 ports 都主要來自許多志工的努力成果,所以在閱讀這份文件時, 請務必感恩在心。 在 FreeBSD 上面,每個人都可以提交新的 port, 或假如該 port 並沒有人維護的話,可以自願維護 — 這點並不需要任何 commit 的權限,就可以來做這件事情。 自行打造 port 那麼,開始對自行製作 port 或更新現有 port 有一些興趣了嗎?太好囉! 下面將介紹一些建立 port 時該注意的事項。如果是想升級現有的 port ,那麼也請參閱 說明。 因為這份文件可能講得不是十分詳細,可能需要參考 /usr/ports/Mk/bsd.port.mk 這檔是所有 port 的 Makefile 檔都會用到的。 就算你不是每天不斷 hacking Makefiles ,也都可以藉由它來對整個 port 機制、Makefile 更瞭解, 裡面的註釋相當詳細。 此外,若有其他特定 port 的問題,也可以到 &a.ports; 來獲得答案。 本文內所提及的環境變數 (VAR)部份, 只有一些可以替換(overridden)。大部份的環境變數(非全部)通常都會寫在 /usr/ports/Mk/bsd.port.mk 內,其他的也是差不多。 請注意:該檔並非使用一般的 tab 設定值,而是採用 1 個 tab 等於 4 個 space。 :EmacsVim 應該都會在載入該檔時順便讀取相關設定值。 &man.vi.1; 及 &man.ex.1; 這兩個程式也都可以打 :set tabstop=4 以修改設定值。 打造 Port 快速上手篇 本節主要介紹如何來快速打造 port,然而, 很多時候這些內容並不是很夠用,建議閱讀本文件中更深奧的地方。 首先取得該應用程式的原始程式碼壓縮檔(tarball),並把它放到 DISTDIR,預設路徑應該是 /usr/ports/distfiles 下面的例子,是假設並不需要再修改該應用程式的原始碼,就可以在 FreeBSD 上編譯成功的;假如還需要另外修改才能成功編譯的話, 那麼請參考下一章的說明。 編寫 <filename>Makefile</filename> 最簡單的 Makefile 大概是像這樣: # New ports collection makefile for: oneko # Date created: 5 December 1994 # Whom: asami # # $FreeBSD$ # PORTNAME= oneko PORTVERSION= 1.1b CATEGORIES= games MASTER_SITES= ftp://ftp.cs.columbia.edu/archives/X11R5/contrib/ MAINTAINER= asami@FreeBSD.org COMMENT= A cat chasing a mouse all over the screen MAN1= oneko.1 MANCOMPRESSED= yes USE_IMAKE= yes .include <bsd.port.mk> 嗯,大致就是這樣,看看你已經領略多少了呢? 看到 $FreeBSD$ 這一行的話,別想太多 ,它是 RCS ID 用途,當該 port 正式進入 port tree 時, CVS 就會自動轉換為相關字串囉。 有關這點的細節部份,可以參閱 sample Makefile 章節。 撰寫該軟體的說明檔 無論是否打算再加工做成 package,有 2 個檔案是任何實體 port (Slave port則不一定)都必須要具備的。 這 2 個檔分別是 pkg-descr 檔及 pkg-plist 檔。 這兩個檔案檔名前面都有 pkg- 以跟其他檔案做區別。 <filename>pkg-descr</filename> 這是此 port 的詳細說明檔,請用一段或幾段文字來說明該 port 的作用,並附上 WWW 網址(若有的話)。 請注意,這檔絕非「該軟體的說明手冊」或是「如何編譯、使用該 port 的說明」。 若是從該軟體的 README 或 manpage 直接複製過來的話,請注意,因為它們通常都寫得太詳細、 格式較特別(比如 manpage 會自動調整空白), 請儘量避免這些冗長贅詞或採用特殊格式。若該軟體有官方版首頁的話, 請在此列出來。 每個網址請用 WWW: 作為開頭, 這樣子相關工具程式就會自動處理完畢。 該 port 的 pkg-descr 內容,大致如下面例子 : This is a port of oneko, in which a cat chases a poor mouse all over the screen. : (etc.) WWW: http://www.oneko.org/ <filename>pkg-plist</filename> 這是該 port 所會裝的所有檔案清單,另外因為 package 會由這清單所產生,因此也被稱為『packing list (打包清單)』。 以 ${PREFIX} 為基準點, 而用相對路徑表示。(${PREFIX} 通常是 /usr/local/usr/X11R6) 但是如果該程式有安裝 man page 的話,則要以類似 MANn= 的方式寫在 Makefile 內,不能列在 pkg-plist 哦。 除了列出檔案以外,也要把該 port 所會建立的目錄也列進去, 方式有兩種:一種是寫在 pkg-plist 內的方式, 比如:@dirrm。 至於另外一種方式,則是寫在 Makefile 內,比如: PLIST_FILES= 之類的方式。 該 port 的 pkg-plist 內容, 大致如下面例子: bin/oneko lib/X11/app-defaults/Oneko lib/X11/oneko/cat1.xpm lib/X11/oneko/cat2.xpm lib/X11/oneko/mouse.xpm @dirrm lib/X11/oneko 關於 packing list 方面,可以參閱 &man.pkg.create.1; 會有詳解 。 建議清單內的檔名,依照字母順序作排序,那麼下次要升級時, 會比較清楚、方便來更新這份清單。 手動生這份清單實在太苦了。尤其若該 port 會裝一大堆檔案的話, 請多善用 自動產生 packing list 會比較省時省力唷。 只有在一種情況下可以省略不用生 pkg-plist 檔: 若安裝的 port 相當單純,只有裝一些檔案, 以及都在同一目錄下的話,那麼可以在 Makefile 內改用 PLIST_FILESPLIST_DIRS 來取代。 比如,可以在上述的 oneko port 內不必附上 pkg-plist ,而只需在 Makefile 內加入下列幾行: PLIST_FILES= bin/oneko \ lib/X11/app-defaults/Oneko \ lib/X11/oneko/cat1.xpm \ lib/X11/oneko/cat2.xpm \ lib/X11/oneko/mouse.xpm PLIST_DIRS= lib/X11/oneko 當然,若該 port 並無安裝自屬的目錄的話,就不必設 PLIST_DIRS 囉。 然而,使用 PLIST_FILESPLIST_DIRS 是必須付出代價: 不能使用 &man.pkg.create.1; 內所說的 command sequences。 因此,這招僅適用於較簡單的 port ,以及簡化該 port 的作法。 此外,這招還有一個好處:可以減少 ports collection 的整體檔案總數。 所以,在考慮是否一定要用 pkg-plist 之前, 可以先斟酌這個替代方案看看。 後面會介紹到如何運用 pkg-plistPLIST_FILES 這些技巧以因應 更複雜的狀況。 產生 checksum 用途的 distinfo 檔 只要打『make makesum』就好了, 接下來就會自動產生相對應的 distinfo 檔了唷 。 若抓下來的檔案,它的 checksum 會經常變更, 而你也很確認所抓的來源是正確無誤的話, (比如:來源是光碟或是每天自動產生的文件),那麼可以設定那些檔案為 IGNOREFILES 。 如此一來,在打 make makesum 的時候就不會計算那些檔案的 checksum ,而自動改為 IGNORE 囉。 檢驗 port 是否完整、可行 接下來,必須檢驗是否有符合 port 的遊戲規則,包括打包該 port 為 package。 以下有幾個需要確認的重要地方: 若該 port 沒裝的東西,不要列在 pkg-plist 內。 若該 port 有裝的東西,請務必列在 pkg-plist 內。 該 port 可以用 reinstall 來重新安裝。 該 port 在移除之後,確定都可 cleans up。 建議的測試步驟順序: make install make package make deinstall pkg_add package-name make deinstall make reinstall make package 確認在 packagedeinstall 這兩個階段都沒有任何錯誤訊息出現。 完成第三步驟之後,檢查一下是否所裝的檔案、目錄都有移除完畢。 此外, 第四步驟完成後,也檢查一下以 package 裝的該軟體,是否都能正常運作 。 最周密的自動方式就是透過裝 ports tinderbox。 它會建立 jails 並管理之,以便您可以測試上述所有步驟, 而不會真正影響您本身的作業系統。 詳情請參考 ports/ports-mgmt/tinderbox 以 <command>portlint</command> 來作檢驗 請用 portlint 來檢查該 port 是否有遵循上述遊戲規則。 說到這 ports-mgmt/portlint,它是 ports collection 的其中一個套件。 它主要可以用來檢驗 Makefile 內容是否正確以及 package 是否有正確命名。 提交(Submit) port 首先,請確認是否有瞭解 DOs and DON'Ts 該章部分。 現在你很高興終於打造出 port 來囉,唯一剩下要做的就是把它正式放到 FreeBSD ports tree 內,才能讓每個人都能分享使用這個 port。 請先拿掉 work 目錄或檔名像是 pkgname.tgz 的 package 可以砍掉。 接著, 只要用 shar `find port_dir` 來產生 shar 格式, 並配合 &man.send-pr.1; 程式以提交出去。(&man.send-pr.1; 的部分可以參閱 錯誤報告和意見發表) 記得在填寫 PR 時『分類(Category)』選 ports, 還有『種類(Class)』填 change-request (千萬別傻傻地把該 PR 的『Confidential(機密)』設為 yes!), 此外在『描述(Description)』 那邊寫上該程式的簡潔說明,而 shar 檔則附在『修正(Fix) 』欄位內。 若 Synopsis 欄清楚描述該 PR 重點的話,那麼會讓整個流程更為順暢。 new ports 的話,我們習慣用: New port: <category>/<portname> <該 port 的簡介> ,而更新 port 的話,則是 Update port: <category>/<portname> <本次 update 的簡介>。 若你也採用這樣的格式的話,那麼會被受理的機會就會越高囉。 再次強調一點:不必附上原始 source 的 distfile ,也就是 work 目錄。 同時,也不必附上 make package 時產生的 package 送出 port 之後,請耐心等候佳音。 有時候可能需要等個幾天或幾個月時間,才會在 FreeBSD ports tree 上正式出現。 此外,隨時可以查閱 等待 committed to FreeBSD 的 port 列表。 一旦我們開始處理你送來的 port 之後,如果有一些意見需要溝通的話, 那麼會先 feedback 給你, 之後確定都沒問題,就會放到 port tree 內囉! 你的大名會被記在 Additional FreeBSD Contributors 列表上,以及其他檔案。聽起來,挺不賴的不是嗎!? :-) Slow Porting Ok...事實上並不太可能這麼簡單,port 方面可能需要作些修改才能正常使用。 因此, 本節將一步一步來介紹如何修改上一章的樣本以正常使用。 How things work 首先,先介紹一下在你所作的 port 目錄內打 make 時,所會作哪些事情的順序吧。 你可以另開一窗來看 bsd.port.mk 內容,以便瞭解我們下面在講什麼。 但別太擔心是否完全看懂 bsd.port.mk 在做啥,很多人都還沒完全看完... :-> 首先,進行 fetch 階段。 fetch 是確認 tarball 檔有沒有已在 DISTDIR 內了?若 fetchDISTDIR 找不到的話,它會搜尋 Makefile 內的 MASTER_SITES URL ,或者是主 FTP 站專門放備份 distfiles 的目錄 。 假設都找不到的話,但是網路有接上 Internet 的話,它會試著用 FETCH 來抓所指定的檔案。 抓到之後,它會把檔案存到 DISTDIR 以便開始使用或日後運用。 其次,進行 extract 階段,它會從 DISTDIR 內找出該 port 所需的檔案(通常是 gzip 格式的 tarball),然後解壓縮到 WRKDIR 所設定的臨時目錄名稱(預設是 work 目錄)內。 之後,進行 patch 階段, 一開始會先套用 PATCHFILES 所指定的任何 patch 檔。 接著是 PATCHDIR(預設是 files 子目錄) 內的檔名為 patch-* 之類的檔案,會以字母順序而逐一套用 patch。 接著是 configure 階段,可以照 port 的類型來作各種不同設定以調整,比如: 若有放 scripts/configure 的話, 那麼就會跑裡面的設定。 若有設 HAS_CONFIGURE 或是 GNU_CONFIGURE 的話,那麼就會跑 WRKSRC/configure 若有設 USE_IMAKE 的話,那麼就會跑 XMKMF (預設是 xmkmf -a) 。 最後是 build 階段,它會在該 port 的 working directory(由 WRKSRC 所設定) 內開始編譯。 若有設 USE_GMAKE 的話, 那麼就會改用 GNU make 來編譯, 否則就用系統本身的 make 來編譯。 上面講的都是打 make 時的預設階段。 此外,還可以設定各階段之前、之後要作的事情:透過定義 pre-somethingpost-something, 或者把這些檔名的 script 丟到 scripts 子目錄去, 這樣子它們就會在各預設階段的之前、之後進行囉。 舉例來說,若在 Makefile 內設定 post-extract,而且在 scripts 子目錄內又有 pre-build 檔的話,那麼在作解壓縮之後,就會開始 post-extract 階段以進行解壓縮後的後續動作, 而在跑 build 階段之前,就會先執行 pre-build 這隻 script 作先期準備。 通常較簡單的修改動作,建議直接放在 Makefile 內就好了, 因為這樣會比較方便加上這些原本沒有的階段,同時也方便他人協助除錯 。 預設的各階段動作都是照 bsd.port.mk 內的 do-something 之類所定義的。 舉例:do-extract 就是定義怎麼把檔案解壓縮的。 若對預設方式覺得不妥的話,都可以在該 port 的 Makefile 重新定義。 The main targets (e.g., extract, configure, etc.) do nothing more than make sure all the stages up to that one are completed and call the real targets or scripts, and they are not intended to be changed. If you want to fix the extraction, fix do-extract, but never ever change the way extract operates! 現在,你已經知道打 make 到底會作些什麼事囉, 接下來會教你如何作更完美的 port。 取得原始的 source 檔 取得原始的 source 檔(通常檔名是 foo.tar.gzfoo.tar.Z 之類的壓縮檔),然後會把抓下來的檔案放在 DISTDIR 內。 記得:抓的時候,儘量使用『該軟體主要的正式網站』上面的來源檔 ,以確保檔案有效、可信。 需要設 MASTER_SITES 以指定原始檔案是放在何處。 相關網址在 bsd.sites.mk 內有一些方便的速記表可以使用。 請盡可能多用對應這些網址的變數, 以避免同樣的一堆網址有重複很多次出現在 port tree 內。 否則,這些網址只要一有改變的話,那麼就會成為維護 port 的夢魘。 如果該檔並沒有放在公開的 FTP 站或網站(HTTP)上, 或者該檔並非一般標準格式的話, 那麼可以考慮複製該檔,然後放到你可掌握、可信任的 FTP 站或網站(HTTP) 上,比如:你自己的網頁空間。 若找不到地方(方便、可信任)來放檔案的話, 那麼可以 house(暫放)ftp.FreeBSD.org 上的 committer 自屬空間內; 然而,這是最不理想的解法。 檔案要放到該 committer 的 freefall 上的 ~/public_distfiles/ 目錄內才可以。 請與協助 commit 你的 port 的那位 committer 聯繫, 以便把檔案放到他的目錄內。 那位 committer 同時也會把 MASTER_SITES 設為 MASTER_SITE_LOCAL,並且把 MASTER_SITE_SUBDIR 設為他自己的 freefall 帳號名稱。 若該 port 的原始檔打包會經常重包,但原作者卻沒更新版號的話, 請考慮把該檔改放到自己的網頁空間,並且把自己網頁空間列為 MASTER_SITES 的第一順位。 或者請與原作者聯繫:請他不要這樣做(不斷重包同樣的檔案);如此一來, 才有助於建立一定程度的 source code 版本控制。 把檔案另外複製一份放到自屬網頁空間的話,不但可有效防止使用者會發生 checksum mismatch(檔案經檢查有問題) 的錯誤訊息,也可降低我們 FTP 站維護者的工作量。此外,若該 port 的檔案僅有一個主要網址, 那麼建議:請在自屬網站上放上備份檔,並修改 MASTER_SITES 把你的網址列為第二順位。 若該 port 需要一些額外 `patches'(可透過 Internet 下載),並放在 DISTDIR 內,不必擔心這些 patch 檔是否得都跟原始檔一樣來自同一網站, 這些情況有另外的解法(請看下面的 PATCHFILES 介紹部分)。 量身打造 port 解開壓縮檔,然後開始逐一修改,使該 port 在目前所用的 FreeBSD 版本上得以順利編譯。 所做的每個動作請都 仔細記錄, 如此一來才能迅速自動套用這些修改。 在完成 port 之後,每項動作包括:對於檔案的刪除、增加、修改, 要記得存為自動化的 script 或者 patch 檔形式,以利他人直接套用。 若該 port 需要使用者的互動、自訂功能來編譯、安裝的話, 那麼建議揣摩看看 Larry Wall 的經典之作 Configure scripts 來完成類似效果。 Ports collection 的目的之一,就是讓每個 port 儘量用最小空間, 來做出軟體的 plug-and-play(即插即用) 除非有明確聲明,否則你所提交給 FreeBSD ports collection 的 patch 檔、相關 script 檔及其他檔案,都會假設是以標準的 BSD 版權形式來發佈。 Patching In the preparation of the port, files that have been added or changed can be picked up with a &man.diff.1; for later feeding to &man.patch.1;. Each patch you wish to apply should be saved into a file named patch-* where * indicates the pathname of the file that is patched, such as patch-Imakefile or patch-src-config.h. These files should be stored in PATCHDIR (usually files/, from where they will be automatically applied. All patches must be relative to WRKSRC (generally the directory your port's tarball unpacks itself into, that being where the build is done). To make fixes and upgrades easier, you should avoid having more than one patch fix the same file (e.g., patch-file and patch-file2 both changing WRKSRC/foobar.c). Please only use characters [-+._a-zA-Z0-9] for naming your patches. Do not use any other characters besides them. Do not name your patches like patch-aa or patch-ab etc, always mention path and file name in patch names. Do not put RCS strings in patches. CVS will mangle them when we put the files into the ports tree, and when we check them out again, they will come out different and the patch will fail. RCS strings are surrounded by dollar ($) signs, and typically start with $Id or $RCS. Using the recurse () option to &man.diff.1; to generate patches is fine, but please take a look at the resulting patches to make sure you do not have any unnecessary junk in there. In particular, diffs between two backup files, Makefiles when the port uses Imake or GNU configure, etc., are unnecessary and should be deleted. If you had to edit configure.in and run autoconf to regenerate configure, do not take the diffs of configure (it often grows to a few thousand lines!); define USE_AUTOTOOLS=autoconf:261 and take the diffs of configure.in. If you had to delete a file, then you can do it in the post-extract target rather than as part of the patch. Simple replacements can be performed directly from the port Makefile using the in-place mode of &man.sed.1;. This is very useful when you need to patch in a variable value. Example: post-patch: @${REINPLACE_CMD} -e 's|for Linux|for FreeBSD|g' ${WRKSRC}/README @${REINPLACE_CMD} -e 's|-pthread|${PTHREAD_LIBS}|' ${WRKSRC}/configure Quite often, there is a situation when the software being ported, especially if it is primarily developed on &windows;, uses the CR/LF convention for most of its source files. This may cause problems with further patching, compiler warnings, scripts execution (/bin/sh^M not found), etc. To quickly convert all files from CR/LF to just LF, add USE_DOS2UNIX=yes to the port Makefile. A list of files to convert can be specified: USE_DOS2UNIX= util.c util.h 若想要轉換所有子目錄內的某類別檔案,可以使用 DOS2UNIX_REGEX。 它的參數是 find 相容的正規表達式。 相關格式可參閱 &man.re.format.7;。 對於所指定副檔名的檔案之轉換而言,這相當好用, 舉例來說,只動所有原始碼部分而不改 binary 檔案: USE_DOS2UNIX= yes DOS2UNIX_REGEX= .*\.(c|cpp|h) - Configuring + 設定 Include any additional customization commands in your configure script and save it in the scripts subdirectory. As mentioned above, you can also do this with Makefile targets and/or scripts with the name pre-configure or post-configure. Handling user input If your port requires user input to build, configure, or install, you must set IS_INTERACTIVE in your Makefile. This will allow overnight builds to skip your port if the user sets the variable BATCH in his environment (and if the user sets the variable INTERACTIVE, then only those ports requiring interaction are built). This will save a lot of wasted time on the set of machines that continually build ports (see below). It is also recommended that if there are reasonable default answers to the questions, you check the PACKAGE_BUILDING variable and turn off the interactive script when it is set. This will allow us to build the packages for CDROMs and FTP. Configuring the Makefile Configuring the Makefile is pretty simple, and again we suggest that you look at existing examples before starting. Also, there is a sample Makefile in this handbook, so take a look and please follow the ordering of variables and sections in that template to make your port easier for others to read. Now, consider the following problems in sequence as you design your new Makefile: The original source Does it live in DISTDIR as a standard gzip'd tarball named something like foozolix-1.2.tar.gz? If so, you can go on to the next step. If not, you should look at overriding any of the DISTVERSION, DISTNAME, EXTRACT_CMD, EXTRACT_BEFORE_ARGS, EXTRACT_AFTER_ARGS, EXTRACT_SUFX, or DISTFILES variables, depending on how alien a format your port's distribution file is. (The most common case is EXTRACT_SUFX=.tar.Z, when the tarball is condensed by regular compress, not gzip.) In the worst case, you can simply create your own do-extract target to override the default, though this should be rarely, if ever, necessary. Naming The first part of the port's Makefile names the port, describes its version number, and lists it in the correct category. <makevar>PORTNAME</makevar> and <makevar>PORTVERSION</makevar> You should set PORTNAME to the base name of your port, and PORTVERSION to the version number of the port. <makevar>PORTREVISION</makevar> and <makevar>PORTEPOCH</makevar> <makevar>PORTREVISION</makevar> The PORTREVISION variable is a monotonically increasing value which is reset to 0 with every increase of PORTVERSION (i.e. every time a new official vendor release is made), and appended to the package name if non-zero. Changes to PORTREVISION are used by automated tools (e.g. &man.pkg.version.1;) to highlight the fact that a new package is available. PORTREVISION should be increased each time a change is made to the port which significantly affects the content or structure of the derived package. Examples of when PORTREVISION should be bumped: Addition of patches to correct security vulnerabilities, bugs, or to add new functionality to the port. Changes to the port Makefile to enable or disable compile-time options in the package. Changes in the packing list or the install-time behavior of the package (e.g. change to a script which generates initial data for the package, like ssh host keys). Version bump of a port's shared library dependency (in this case, someone trying to install the old package after installing a newer version of the dependency will fail since it will look for the old libfoo.x instead of libfoo.(x+1)). Silent changes to the port distfile which have significant functional differences, i.e. changes to the distfile requiring a correction to distinfo with no corresponding change to PORTVERSION, where a diff -ru of the old and new versions shows non-trivial changes to the code. Examples of changes which do not require a PORTREVISION bump: Style changes to the port skeleton with no functional change to what appears in the resulting package. Changes to MASTER_SITES or other functional changes to the port which do not affect the resulting package. Trivial patches to the distfile such as correction of typos, which are not important enough that users of the package should go to the trouble of upgrading. Build fixes which cause a package to become compilable where it was previously failing (as long as the changes do not introduce any functional change on any other platforms on which the port did previously build). Since PORTREVISION reflects the content of the package, if the package was not previously buildable then there is no need to increase PORTREVISION to mark a change. A rule of thumb is to ask yourself whether a change committed to a port is something which everyone would benefit from having (either because of an enhancement, fix, or by virtue that the new package will actually work at all), and weigh that against that fact that it will cause everyone who regularly updates their ports tree to be compelled to update. If yes, the PORTREVISION should be bumped. <makevar>PORTEPOCH</makevar> From time to time a software vendor or FreeBSD porter will do something silly and release a version of their software which is actually numerically less than the previous version. An example of this is a port which goes from foo-20000801 to foo-1.0 (the former will be incorrectly treated as a newer version since 20000801 is a numerically greater value than 1). In situations such as this, the PORTEPOCH version should be increased. If PORTEPOCH is nonzero it is appended to the package name as described in section 0 above. PORTEPOCH must never be decreased or reset to zero, because that would cause comparison to a package from an earlier epoch to fail (i.e. the package would not be detected as out of date): the new version number (e.g. 1.0,1 in the above example) is still numerically less than the previous version (20000801), but the ,1 suffix is treated specially by automated tools and found to be greater than the implied suffix ,0 on the earlier package. Dropping or resetting PORTEPOCH incorrectly leads to no end of grief; if you do not understand the above discussion, please keep after it until you do, or ask questions on the mailing lists. It is expected that PORTEPOCH will not be used for the majority of ports, and that sensible use of PORTVERSION can often pre-empt it becoming necessary if a future release of the software should change the version structure. However, care is needed by FreeBSD porters when a vendor release is made without an official version number — such as a code snapshot release. The temptation is to label the release with the release date, which will cause problems as in the example above when a new official release is made. For example, if a snapshot release is made on the date 20000917, and the previous version of the software was version 1.2, the snapshot release should be given a PORTVERSION of 1.2.20000917 or similar, not 20000917, so that the succeeding release, say 1.3, is still a numerically greater value. Example of <makevar>PORTREVISION</makevar> and <makevar>PORTEPOCH</makevar> usage The gtkmumble port, version 0.10, is committed to the ports collection: PORTNAME= gtkmumble PORTVERSION= 0.10 PKGNAME becomes gtkmumble-0.10. A security hole is discovered which requires a local FreeBSD patch. PORTREVISION is bumped accordingly. PORTNAME= gtkmumble PORTVERSION= 0.10 PORTREVISION= 1 PKGNAME becomes gtkmumble-0.10_1 A new version is released by the vendor, numbered 0.2 (it turns out the author actually intended 0.10 to actually mean 0.1.0, not what comes after 0.9 - oops, too late now). Since the new minor version 2 is numerically less than the previous version 10, the PORTEPOCH must be bumped to manually force the new package to be detected as newer. Since it is a new vendor release of the code, PORTREVISION is reset to 0 (or removed from the Makefile). PORTNAME= gtkmumble PORTVERSION= 0.2 PORTEPOCH= 1 PKGNAME becomes gtkmumble-0.2,1 The next release is 0.3. Since PORTEPOCH never decreases, the version variables are now: PORTNAME= gtkmumble PORTVERSION= 0.3 PORTEPOCH= 1 PKGNAME becomes gtkmumble-0.3,1 If PORTEPOCH were reset to 0 with this upgrade, someone who had installed the gtkmumble-0.10_1 package would not detect the gtkmumble-0.3 package as newer, since 3 is still numerically less than 10. Remember, this is the whole point of PORTEPOCH in the first place. <makevar>PKGNAMEPREFIX</makevar> and <makevar>PKGNAMESUFFIX</makevar> Two optional variables, PKGNAMEPREFIX and PKGNAMESUFFIX, are combined with PORTNAME and PORTVERSION to form PKGNAME as ${PKGNAMEPREFIX}${PORTNAME}${PKGNAMESUFFIX}-${PORTVERSION}. Make sure this conforms to our guidelines for a good package name. In particular, you are not allowed to use a hyphen (-) in PORTVERSION. Also, if the package name has the language- or the -compiled.specifics part (see below), use PKGNAMEPREFIX and PKGNAMESUFFIX, respectively. Do not make them part of PORTNAME. <makevar>LATEST_LINK</makevar> 在某些情況,可能會同時存在有不同版本的同一程式。 由於它們可能會有同樣的 PORTNAMEPKGNAMEPREFIX,甚至 PKGNAMESUFFIX 也相同,所以得讓這些程式有所不同, 才能讓 port 的 index 以及 package 能順利產生。 遇到這類情況, the optional LATEST_LINK variable should be set to a different value for all ports except the main one — see the editors/vim5 and editors/vim ports, and the www/apache* family for examples of its use. Note that how to choose a main version — most popular, best supported, least patched, and so on — is outside the scope of this handbook's recommendations; we only tell you how to specify the other ports' versions after you have picked a main one. Package Naming Conventions The following are the conventions you should follow in naming your packages. This is to have our package directory easy to scan, as there are already thousands of packages and users are going to turn away if they hurt their eyes! The package name should look like language_region-name-compiled.specifics-version.numbers. The package name is defined as ${PKGNAMEPREFIX}${PORTNAME}${PKGNAMESUFFIX}-${PORTVERSION}. Make sure to set the variables to conform to that format. FreeBSD strives to support the native language of its users. The language- part should be a two letter abbreviation of the natural language defined by ISO-639 if the port is specific to a certain language. Examples are ja for Japanese, ru for Russian, vi for Vietnamese, zh for Chinese, ko for Korean and de for German. If the port is specific to a certain region within the language area, add the two letter country code as well. Examples are en_US for US English and fr_CH for Swiss French. The language- part should be set in the PKGNAMEPREFIX variable. The first letter of the name part should be lowercase. (The rest of the name may contain capital letters, so use your own discretion when you are converting a software name that has some capital letters in it.) There is a tradition of naming Perl 5 modules by prepending p5- and converting the double-colon separator to a hyphen; for example, the Data::Dumper module becomes p5-Data-Dumper. Make sure that the port's name and version are clearly separated and placed into the PORTNAME and PORTVERSION variables. The only reason for PORTNAME to contain a version part is if the upstream distribution is really named that way, as in the textproc/libxml2 or japanese/kinput2-freewnn ports. Otherwise, the PORTNAME should not contain any version-specific information. It is quite normal for several ports to have the same PORTNAME, as the www/apache* ports do; in that case, different versions (and different index entries) are distinguished by the PKGNAMEPREFIX, PKGNAMESUFFIX, and LATEST_LINK values. If the port can be built with different hardcoded defaults (usually part of the directory name in a family of ports), the -compiled.specifics part should state the compiled-in defaults (the hyphen is optional). Examples are papersize and font units. The -compiled.specifics part should be set in the PKGNAMESUFFIX variable. The version string should follow a dash (-) and be a period-separated list of integers and single lowercase alphabetics. In particular, it is not permissible to have another dash inside the version string. The only exception is the string pl (meaning patchlevel), which can be used only when there are no major and minor version numbers in the software. If the software version has strings like alpha, beta, rc, or pre, take the first letter and put it immediately after a period. If the version string continues after those names, the numbers should follow the single alphabet without an extra period between them. The idea is to make it easier to sort ports by looking at the version string. In particular, make sure version number components are always delimited by a period, and if the date is part of the string, use the yyyy.mm.dd format, not dd.mm.yyyy or the non-Y2K compliant yy.mm.dd format. Here are some (real) examples on how to convert the name as called by the software authors to a suitable package name: Distribution Name PKGNAMEPREFIX PORTNAME PKGNAMESUFFIX PORTVERSION Reason mule-2.2.2 (empty) mule (empty) 2.2.2 No changes required EmiClock-1.0.2 (empty) emiclock (empty) 1.0.2 No uppercase names for single programs rdist-1.3alpha (empty) rdist (empty) 1.3.a No strings like alpha allowed es-0.9-beta1 (empty) es (empty) 0.9.b1 No strings like beta allowed mailman-2.0rc3 (empty) mailman (empty) 2.0.r3 No strings like rc allowed v3.3beta021.src (empty) tiff (empty) 3.3 What the heck was that anyway? tvtwm (empty) tvtwm (empty) pl11 Version string always required piewm (empty) piewm (empty) 1.0 Version string always required xvgr-2.10pl1 (empty) xvgr (empty) 2.10.1 pl allowed only when no major/minor version numbers gawk-2.15.6 ja- gawk (empty) 2.15.6 Japanese language version psutils-1.13 (empty) psutils -letter 1.13 Papersize hardcoded at package build time pkfonts (empty) pkfonts 300 1.0 Package for 300dpi fonts If there is absolutely no trace of version information in the original source and it is unlikely that the original author will ever release another version, just set the version string to 1.0 (like the piewm example above). Otherwise, ask the original author or use the date string (yyyy.mm.dd) as the version. Categorization <makevar>CATEGORIES</makevar> When a package is created, it is put under /usr/ports/packages/All and links are made from one or more subdirectories of /usr/ports/packages. The names of these subdirectories are specified by the variable CATEGORIES. It is intended to make life easier for the user when he is wading through the pile of packages on the FTP site or the CDROM. Please take a look at the current list of categories and pick the ones that are suitable for your port. This list also determines where in the ports tree the port is imported. If you put more than one category here, it is assumed that the port files will be put in the subdirectory with the name in the first category. See below for more discussion about how to pick the right categories. Current list of categories Here is the current list of port categories. Those marked with an asterisk (*) are virtual categories—those that do not have a corresponding subdirectory in the ports tree. They are only used as secondary categories, and only for search purposes. For non-virtual categories, you will find a one-line description in the COMMENT in that subdirectory's Makefile. Category Description Notes accessibility Ports to help disabled users. afterstep* Ports to support the AfterStep window manager. arabic Arabic language support. archivers Archiving tools. astro Astronomical ports. audio Sound support. benchmarks Benchmarking utilities. biology Biology-related software. cad Computer aided design tools. chinese Chinese language support. comms Communication software. Mostly software to talk to your serial port. converters Character code converters. databases Databases. deskutils Things that used to be on the desktop before computers were invented. devel Development utilities. Do not put libraries here just because they are libraries—unless they truly do not belong anywhere else, they should not be in this category. dns DNS-related software. editors General editors. Specialized editors go in the section for those tools (e.g., a mathematical-formula editor will go in math). elisp* Emacs-lisp ports. emulators Emulators for other operating systems. Terminal emulators do not belong here—X-based ones should go to x11 and text-based ones to either comms or misc, depending on the exact functionality. finance Monetary, financial and related applications. french French language support. ftp FTP client and server utilities. If your port speaks both FTP and HTTP, put it in ftp with a secondary category of www. games 遊戲。 geography* 地理圖資相關的軟體。 german 德文相關支援。 gnome* Ports from the GNOME Project. graphics 圖形處理的工具軟體。 gnustep* GNUstep 桌面環境相關的軟體。 hamradio* Software for amateur radio. haskell* Software related to the Haskell language. hebrew Hebrew language support. hungarian Hungarian language support. ipv6* IPv6 related software. irc Internet Relay Chat utilities. japanese Japanese language support. java Software related to the Java language. The java category shall not be the only one for a port. Save for ports directly related to the Java language, porters are also encouraged not to use java as the main category of a port. kde* Ports from the K Desktop Environment (KDE) Project. kld* Kernel loadable modules。 korean Korean language support. lang Programming languages. linux* Linux applications and support utilities. lisp* Software related to the Lisp language. mail Mail software. math Numerical computation software and other utilities for mathematics. mbone MBone applications. misc Miscellaneous utilities Basically things that do not belong anywhere else. If at all possible, try to find a better category for your port than misc, as ports tend to get overlooked in here. multimedia Multimedia software. net Miscellaneous networking software. net-im Instant messaging software. net-mgmt Networking management software. net-p2p Peer to peer network applications. news USENET news software. palm Software support for the Palm™ series. parallel* Applications dealing with parallelism in computing. pear* Ports related to the Pear PHP framework. perl5* Ports that require Perl version 5 to run. plan9* Various programs from Plan9. polish Polish language support. ports-mgmt FreeBSD ports 及 packages 的管理、安裝、開發。 portuguese Portuguese language support. print Printing software. Desktop publishing tools (previewers, etc.) belong here too. python* Software related to the Python language. ruby* Software related to the Ruby language. rubygems* Ports of RubyGems packages. russian Russian language support. scheme* Software related to the Scheme language. science Scientific ports that do not fit into other categories such as astro, biology and math. security Security utilities. shells Command line shells. spanish* 西班牙文的相關支援。 sysutils System utilities. tcl* 使用 Tcl 語言的軟體。 tcl80* Ports that use Tcl version 8.0 to run. tcl82* Ports that use Tcl version 8.2 to run. tcl83* Ports that use Tcl version 8.3 to run. tcl84* Ports that use Tcl version 8.4 to run. textproc Text processing utilities. It does not include desktop publishing tools, which go to print. tk* 使用 Tk 語言的程式。 tk80* Ports that use Tk version 8.0 to run. tk82* Ports that use Tk version 8.2 to run. tk83* Ports that use Tk version 8.3 to run. tk84* Ports that use Tk version 8.4 to run. tkstep80* Ports that use TkSTEP version 8.0 to run. ukrainian Ukrainian language support. vietnamese Vietnamese language support. windowmaker* Ports to support the WindowMaker window manager. www Software related to the World Wide Web. HTML language support belongs here too. x11 The X Window System and friends. This category is only for software that directly supports the window system. Do not put regular X applications here; most of them should go into other x11-* categories (see below). If your port is an X application, define USE_XLIB (implied by USE_IMAKE) and put it in the appropriate category. x11-clocks X11 clocks. x11-drivers X11 驅動程式。 x11-fm X11 file managers. x11-fonts X11 fonts and font utilities. x11-servers X11 servers. x11-themes X11 themes. x11-toolkits X11 toolkits. x11-wm X11 window managers. xfce* Xfce 桌面環境的相關軟體。 zope* Zope support. Choosing the right category As many of the categories overlap, you often have to choose which of the categories should be the primary category of your port. There are several rules that govern this issue. Here is the list of priorities, in decreasing order of precedence: The first category must be a physical category (see above). This is necessary to make the packaging work. Virtual categories and physical categories may be intermixed after that. Language specific categories always come first. For example, if your port installs Japanese X11 fonts, then your CATEGORIES line would read japanese x11-fonts. Specific categories are listed before less-specific ones. For instance, an HTML editor should be listed as www editors, not the other way around. Also, you should not list net when the port belongs to any of irc, mail, mbone, news, security, or www, as net is included implicitly. x11 is used as a secondary category only when the primary category is a natural language. In particular, you should not put x11 in the category line for X applications. Emacs modes should be placed in the same ports category as the application supported by the mode, not in editors. For example, an Emacs mode to edit source files of some programming language should go into lang. 會安裝 kernel loadable modules 的 port 請在 CATEGORIES 內加上 kld 這個虛擬目錄。 misc should not appear with any other non-virtual category. If you have misc with something else in your CATEGORIES line, that means you can safely delete misc and just put the port in that other subdirectory! If your port truly does not belong anywhere else, put it in misc. If you are not sure about the category, please put a comment to that effect in your &man.send-pr.1; submission so we can discuss it before we import it. If you are a committer, send a note to the &a.ports; so we can discuss it first. Too often, new ports are imported to the wrong category only to be moved right away. This causes unnecessary and undesirable bloat in the master source repository. Proposing a new category As the Ports Collection has grown over time, various new categories have been introduced. New categories can either be virtual categories—those that do not have a corresponding subdirectory in the ports tree— or physical categories—those that do. The following text discusses the issues involved in creating a new physical category so that you can understand them before you propose one. Our existing practice has been to avoid creating a new physical category unless either a large number of ports would logically belong to it, or the ports that would belong to it are a logically distinct group that is of limited general interest (for instance, categories related to spoken human languages), or preferably both. The rationale for this is that such a change creates a fair amount of work for both the committers and also for all users who track changes to the Ports Collection. In addition, proposed category changes just naturally seem to attract controversy. (Perhaps this is because there is no clear consensus on when a category is too big, nor whether categories should lend themselves to browsing (and thus what number of categories would be an ideal number), and so forth.) Here is the procedure: Propose the new category on &a.ports;. You should include a detailed rationale for the new category, including why you feel the existing categories are not sufficient, and the list of existing ports proposed to move. (If there are new ports pending in GNATS that would fit this category, list them too.) If you are the maintainer and/or submitter, respectively, mention that as it may help you to make your case. Participate in the discussion. If it seems that there is support for your idea, file a PR which includes both the rationale and the list of existing ports that need to be moved. Ideally, this PR should also include patches for the following: Makefiles for the new ports once they are repocopied Makefile for the new category Makefile for the old ports' categories Makefiles for ports that depend on the old ports (for extra credit, you can include the other files that have to change, as per the procedure in the Committer's Guide.) Since it affects the ports infrastructure and involves not only performing repo-copies but also possibly running regression tests on the build cluster, the PR should be assigned to the &a.portmgr;. If that PR is approved, a committer will need to follow the rest of the procedure that is outlined in the Committer's Guide. Proposing a new virtual category should be similar to the above but much less involved, since no ports will actually have to move. In this case, the only patches to include in the PR would be those to add the new category to the CATEGORIES of the affected ports. Proposing reorganizing all the categories Occasionally someone proposes reorganizing the categories with either a 2-level structure, or some other kind of keyword structure. To date, nothing has come of any of these proposals because, while they are very easy to make, the effort involved to retrofit the entire existing ports collection with any kind of reorganization is daunting to say the very least. Please read the history of these proposals in the mailing list archives before you post this idea; furthermore, you should be prepared to be challenged to offer a working prototype. The distribution files The second part of the Makefile describes the files that must be downloaded in order to build the port, and where they can be downloaded from. <makevar>DISTVERSION/DISTNAME</makevar> DISTNAME is the name of the port as called by the authors of the software. DISTNAME defaults to ${PORTNAME}-${PORTVERSION}, so override it only if necessary. DISTNAME is only used in two places. First, the distribution file list (DISTFILES) defaults to ${DISTNAME}${EXTRACT_SUFX}. Second, the distribution file is expected to extract into a subdirectory named WRKSRC, which defaults to work/${DISTNAME}. Some vendor's distribution names which do not fit into the ${PORTNAME}-${PORTVERSION}-scheme can be handled automatically by setting DISTVERSION. PORTVERSION and DISTNAME will be derived automatically, but can of course be overridden. The following table lists some examples: DISTVERSION PORTVERSION 0.7.1d 0.7.1.d 10Alpha3 10.a3 3Beta7-pre2 3.b7.p2 8:f_17 8f.17 PKGNAMEPREFIX and PKGNAMESUFFIX do not affect DISTNAME. Also note that if WRKSRC is equal to work/${PORTNAME}-${PORTVERSION} while the original source archive is named something other than ${PORTNAME}-${PORTVERSION}${EXTRACT_SUFX}, you should probably leave DISTNAME alone— you are better off defining DISTFILES than having to set both DISTNAME and WRKSRC (and possibly EXTRACT_SUFX). <makevar>MASTER_SITES</makevar> Record the directory part of the FTP/HTTP-URL pointing at the original tarball in MASTER_SITES. Do not forget the trailing slash (/)! The make macros will try to use this specification for grabbing the distribution file with FETCH if they cannot find it already on the system. It is recommended that you put multiple sites on this list, preferably from different continents. This will safeguard against wide-area network problems. We are even planning to add support for automatically determining the closest master site and fetching from there; having multiple sites will go a long way towards helping this effort. If the original tarball is part of one of the popular archives such as X-contrib, GNU, or Perl CPAN, you may be able refer to those sites in an easy compact form using MASTER_SITE_* (比如:MASTER_SITE_XCONTRIBMASTER_SITE_GNUMASTER_SITE_PERL_CPAN)。 Simply set MASTER_SITES to one of these variables and MASTER_SITE_SUBDIR to the path within the archive. Here is an example: MASTER_SITES= ${MASTER_SITE_XCONTRIB} MASTER_SITE_SUBDIR= applications These variables are defined in /usr/ports/Mk/bsd.sites.mk. There are new entries added all the time, so make sure to check the latest version of this file before submitting a port. The user can also set the MASTER_SITE_* variables in /etc/make.conf to override our choices, and use their favorite mirrors of these popular archives instead. <makevar>EXTRACT_SUFX</makevar> If you have one distribution file, and it uses an odd suffix to indicate the compression mechanism, set EXTRACT_SUFX. For example, if the distribution file was named foo.tgz instead of the more normal foo.tar.gz, you would write: DISTNAME= foo EXTRACT_SUFX= .tgz The USE_BZIP2 and USE_ZIP variables automatically set EXTRACT_SUFX to .tar.bz2 or .zip as necessary. If neither of these are set then EXTRACT_SUFX defaults to .tar.gz. You never need to set both EXTRACT_SUFX and DISTFILES. <makevar>DISTFILES</makevar> Sometimes the names of the files to be downloaded have no resemblance to the name of the port. For example, it might be called source.tar.gz or similar. In other cases the application's source code might be in several different archives, all of which must be downloaded. If this is the case, set DISTFILES to be a space separated list of all the files that must be downloaded. DISTFILES= source1.tar.gz source2.tar.gz If not explicitly set, DISTFILES defaults to ${DISTNAME}${EXTRACT_SUFX}. <makevar>EXTRACT_ONLY</makevar> If only some of the DISTFILES must be extracted—for example, one of them is the source code, while another is an uncompressed document—list the filenames that must be extracted in EXTRACT_ONLY. DISTFILES= source.tar.gz manual.html EXTRACT_ONLY= source.tar.gz If none of the DISTFILES should be uncompressed then set EXTRACT_ONLY to the empty string. EXTRACT_ONLY= <makevar>PATCHFILES</makevar> If your port requires some additional patches that are available by FTP or HTTP, set PATCHFILES to the names of the files and PATCH_SITES to the URL of the directory that contains them (the format is the same as MASTER_SITES). If the patch is not relative to the top of the source tree (i.e., WRKSRC) because it contains some extra pathnames, set PATCH_DIST_STRIP accordingly. For instance, if all the pathnames in the patch have an extra foozolix-1.0/ in front of the filenames, then set PATCH_DIST_STRIP=-p1. Do not worry if the patches are compressed; they will be decompressed automatically if the filenames end with .gz or .Z. If the patch is distributed with some other files, such as documentation, in a gzip'd tarball, you cannot just use PATCHFILES. If that is the case, add the name and the location of the patch tarball to DISTFILES and MASTER_SITES. Then, use the EXTRA_PATCHES variable to point to those files and bsd.port.mk will automatically apply them for you. In particular, do not copy patch files into the PATCHDIR directory—that directory may not be writable. The tarball will have been extracted alongside the regular source by then, so there is no need to explicitly extract it if it is a regular gzip'd or compress'd tarball. If you do the latter, take extra care not to overwrite something that already exists in that directory. Also, do not forget to add a command to remove the copied patch in the pre-clean target. Multiple distribution files or patches from different sites and subdirectories (<literal>MASTER_SITES:n</literal>) (Consider this to be a somewhat advanced topic; those new to this document may wish to skip this section at first). This section has information on the fetching mechanism known as both MASTER_SITES:n and MASTER_SITES_NN. We will refer to this mechanism as MASTER_SITES:n hereon. A little background first. OpenBSD has a neat feature inside both DISTFILES and PATCHFILES variables, both files and patches can be postfixed with :n identifiers where n both can be [0-9] and denote a group designation. For example: DISTFILES= alpha:0 beta:1 In OpenBSD, distribution file alpha will be associated with variable MASTER_SITES0 instead of our common MASTER_SITES and beta with MASTER_SITES1. This is a very interesting feature which can decrease that endless search for the correct download site. Just picture 2 files in DISTFILES and 20 sites in MASTER_SITES, the sites slow as hell where beta is carried by all sites in MASTER_SITES, and alpha can only be found in the 20th site. It would be such a waste to check all of them if maintainer knew this beforehand, would it not? Not a good start for that lovely weekend! Now that you have the idea, just imagine more DISTFILES and more MASTER_SITES. Surely our distfiles survey meister would appreciate the relief to network strain that this would bring. In the next sections, information will follow on the FreeBSD implementation of this idea. We improved a bit on OpenBSD's concept. Simplified information This section tells you how to quickly prepare fine grained fetching of multiple distribution files and patches from different sites and subdirectories. We describe here a case of simplified MASTER_SITES:n usage. This will be sufficient for most scenarios. However, if you need further information, you will have to refer to the next section. Some applications consist of multiple distribution files that must be downloaded from a number of different sites. For example, Ghostscript consists of the core of the program, and then a large number of driver files that are used depending on the user's printer. Some of these driver files are supplied with the core, but many others must be downloaded from a variety of different sites. To support this, each entry in DISTFILES may be followed by a colon and a tag name. Each site listed in MASTER_SITES is then followed by a colon, and the tag that indicates which distribution files should be downloaded from this site. For example, consider an application with the source split in two parts, source1.tar.gz and source2.tar.gz, which must be downloaded from two different sites. The port's Makefile would include lines like . Simplified use of <literal>MASTER_SITES:n</literal> with 1 file per site MASTER_SITES= ftp://ftp.example1.com/:source1 \ ftp://ftp.example2.com/:source2 DISTFILES= source1.tar.gz:source1 \ source2.tar.gz:source2 Multiple distribution files can have the same tag. Continuing the previous example, suppose that there was a third distfile, source3.tar.gz, that should be downloaded from ftp.example2.com. The Makefile would then be written like . Simplified use of <literal>MASTER_SITES:n</literal> with more than 1 file per site MASTER_SITES= ftp://ftp.example1.com/:source1 \ ftp://ftp.example2.com/:source2 DISTFILES= source1.tar.gz:source1 \ source2.tar.gz:source2 \ source3.tar.gz:source2 Detailed information Okay, so the previous section example did not reflect your needs? In this section we will explain in detail how the fine grained fetching mechanism MASTER_SITES:n works and how you can modify your ports to use it. Elements can be postfixed with :n where n is [^:,]+, i.e., n could conceptually be any alphanumeric string but we will limit it to [a-zA-Z_][0-9a-zA-Z_]+ for now. Moreover, string matching is case sensitive; i.e., n is different from N. However, the following words cannot be used for postfixing purposes since they yield special meaning: default, all and ALL (they are used internally in item ). Furthermore, DEFAULT is a special purpose word (check item ). Elements postfixed with :n belong to the group n, :m belong to group m and so forth. Elements without a postfix are groupless, i.e., they all belong to the special group DEFAULT. If you postfix any elements with DEFAULT, you are just being redundant unless you want to have an element belonging to both DEFAULT and other groups at the same time (check item ). The following examples are equivalent but the first one is preferred: MASTER_SITES= alpha MASTER_SITES= alpha:DEFAULT Groups are not exclusive, an element may belong to several different groups at the same time and a group can either have either several different elements or none at all. Repeated elements within the same group will be simply that, repeated elements. When you want an element to belong to several groups at the same time, you can use the comma operator (,). Instead of repeating it several times, each time with a different postfix, we can list several groups at once in a single postfix. For instance, :m,n,o marks an element that belongs to group m, n and o. All the following examples are equivalent but the last one is preferred: MASTER_SITES= alpha alpha:SOME_SITE MASTER_SITES= alpha:DEFAULT alpha:SOME_SITE MASTER_SITES= alpha:SOME_SITE,DEFAULT MASTER_SITES= alpha:DEFAULT,SOME_SITE All sites within a given group are sorted according to MASTER_SORT_AWK. All groups within MASTER_SITES and PATCH_SITES are sorted as well. Group semantics can be used in any of the following variables MASTER_SITES, PATCH_SITES, MASTER_SITE_SUBDIR, PATCH_SITE_SUBDIR, DISTFILES, and PATCHFILES according to the following syntax: All MASTER_SITES, PATCH_SITES, MASTER_SITE_SUBDIR and PATCH_SITE_SUBDIR elements must be terminated with the forward slash / character. If any elements belong to any groups, the group postfix :n must come right after the terminator /. The MASTER_SITES:n mechanism relies on the existence of the terminator / to avoid confusing elements where a :n is a valid part of the element with occurrences where :n denotes group n. For compatibility purposes, since the / terminator was not required before in both MASTER_SITE_SUBDIR and PATCH_SITE_SUBDIR elements, if the postfix immediate preceding character is not a / then :n will be considered a valid part of the element instead of a group postfix even if an element is postfixed with :n. See both and . Detailed use of <literal>MASTER_SITES:n</literal> in <makevar>MASTER_SITE_SUBDIR</makevar> MASTER_SITE_SUBDIR= old:n new/:NEW Directories within group DEFAULT -> old:n Directories within group NEW -> new Detailed use of <literal>MASTER_SITES:n</literal> with comma operator, multiple files, multiple sites and multiple subdirectories MASTER_SITES= http://site1/%SUBDIR%/ http://site2/:DEFAULT \ http://site3/:group3 http://site4/:group4 \ http://site5/:group5 http://site6/:group6 \ http://site7/:DEFAULT,group6 \ http://site8/%SUBDIR%/:group6,group7 \ http://site9/:group8 DISTFILES= file1 file2:DEFAULT file3:group3 \ file4:group4,group5,group6 file5:grouping \ file6:group7 MASTER_SITE_SUBDIR= directory-trial:1 directory-n/:groupn \ directory-one/:group6,DEFAULT \ directory The previous example results in the following fine grained fetching. Sites are listed in the exact order they will be used. file1 will be fetched from MASTER_SITE_OVERRIDE http://site1/directory-trial:1/ http://site1/directory-one/ http://site1/directory/ http://site2/ http://site7/ MASTER_SITE_BACKUP file2 will be fetched exactly as file1 since they both belong to the same group MASTER_SITE_OVERRIDE http://site1/directory-trial:1/ http://site1/directory-one/ http://site1/directory/ http://site2/ http://site7/ MASTER_SITE_BACKUP file3 will be fetched from MASTER_SITE_OVERRIDE http://site3/ MASTER_SITE_BACKUP file4 will be fetched from MASTER_SITE_OVERRIDE http://site4/ http://site5/ http://site6/ http://site7/ http://site8/directory-one/ MASTER_SITE_BACKUP file5 will be fetched from MASTER_SITE_OVERRIDE MASTER_SITE_BACKUP file6 will be fetched from MASTER_SITE_OVERRIDE http://site8/ MASTER_SITE_BACKUP How do I group one of the special variables from bsd.sites.mk, e.g., MASTER_SITE_SOURCEFORGE? See . Detailed use of <literal>MASTER_SITES:n</literal> with <makevar>MASTER_SITE_SOURCEFORGE</makevar> MASTER_SITES= http://site1/ ${MASTER_SITE_SOURCEFORGE:S/$/:sourceforge,TEST/} DISTFILES= something.tar.gz:sourceforge something.tar.gz will be fetched from all sites within MASTER_SITE_SOURCEFORGE. How do I use this with PATCH* variables? All examples were done with MASTER* variables but they work exactly the same for PATCH* ones as can be seen in . Simplified use of <literal>MASTER_SITES:n</literal> with <makevar>PATCH_SITES</makevar>. PATCH_SITES= http://site1/ http://site2/:test PATCHFILES= patch1:test What does change for ports? What does not? All current ports remain the same. The MASTER_SITES:n feature code is only activated if there are elements postfixed with :n like elements according to the aforementioned syntax rules, especially as shown in item . The port targets remain the same: checksum, makesum, patch, configure, build, etc. With the obvious exceptions of do-fetch, fetch-list, master-sites and patch-sites. do-fetch: deploys the new grouping postfixed DISTFILES and PATCHFILES with their matching group elements within both MASTER_SITES and PATCH_SITES which use matching group elements within both MASTER_SITE_SUBDIR and PATCH_SITE_SUBDIR. Check . fetch-list: works like old fetch-list with the exception that it groups just like do-fetch. master-sites and patch-sites: (incompatible with older versions) only return the elements of group DEFAULT; in fact, they execute targets master-sites-default and patch-sites-default respectively. Furthermore, using target either master-sites-all or patch-sites-all is preferred to directly checking either MASTER_SITES or PATCH_SITES. Also, directly checking is not guaranteed to work in any future versions. Check item for more information on these new port targets. New port targets There are master-sites-n and patch-sites-n targets which will list the elements of the respective group n within MASTER_SITES and PATCH_SITES respectively. For instance, both master-sites-DEFAULT and patch-sites-DEFAULT will return the elements of group DEFAULT, master-sites-test and patch-sites-test of group test, and thereon. There are new targets master-sites-all and patch-sites-all which do the work of the old master-sites and patch-sites ones. They return the elements of all groups as if they all belonged to the same group with the caveat that it lists as many MASTER_SITE_BACKUP and MASTER_SITE_OVERRIDE as there are groups defined within either DISTFILES or PATCHFILES; respectively for master-sites-all and patch-sites-all. <makevar>DIST_SUBDIR</makevar> Do not let your port clutter /usr/ports/distfiles. If your port requires a lot of files to be fetched, or contains a file that has a name that might conflict with other ports (e.g., Makefile), set DIST_SUBDIR to the name of the port (${PORTNAME} or ${PKGNAMEPREFIX}${PORTNAME} should work fine). This will change DISTDIR from the default /usr/ports/distfiles to /usr/ports/distfiles/DIST_SUBDIR, and in effect puts everything that is required for your port into that subdirectory. It will also look at the subdirectory with the same name on the backup master site at ftp.FreeBSD.org. (Setting DISTDIR explicitly in your Makefile will not accomplish this, so please use DIST_SUBDIR.) This does not affect the MASTER_SITES you define in your Makefile. <makevar>ALWAYS_KEEP_DISTFILES</makevar> If your port uses binary distfiles and has a license that requires that the source code is provided with packages distributed in binary form, e.g. GPL, ALWAYS_KEEP_DISTFILES will instruct the &os; build cluster to keep a copy of the files specified in DISTFILES. Users of these ports will generally not need these files, so it is a good idea to only add the source distfiles to DISTFILES when PACKAGE_BUILDING is defined. Use of <makevar>ALWAYS_KEEP_DISTFILES</makevar>. .if defined(PACKAGE_BUILDING) DISTFILES+= foo.tar.gz ALWAYS_KEEP_DISTFILES= yes .endif When adding extra files to DISTFILES, make sure you also add them to distinfo. Also, the additional files will normally be extracted into WRKDIR as well, which for some ports may lead to undesirable sideeffects and require special handling. <makevar>MAINTAINER</makevar> Set your mail-address here. Please. :-) Note that only a single address without the comment part is allowed as a MAINTAINER value. The format used should be user@hostname.domain. Please do not include any descriptive text such as your real name in this entry—that merely confuses bsd.port.mk. The maintainer is responsible for keeping the port up to date, and ensuring the port works correctly. For a detailed description of the responsibilities of a port maintainer, refer to the The challenge for port maintainers section. Changes to the port will be sent to the maintainer of a port for a review and an approval before being committed. If the maintainer does not respond to an update request after two weeks (excluding major public holidays), then that is considered a maintainer timeout, and the update may be made without explicit maintainer approval. If the maintainer does not respond within three months, then that maintainer is considered absent without leave, and can be replaced as the maintainer of the particular port in question. Exceptions to this are anything maintained by the &a.portmgr;, or the &a.security-officer;. No unauthorized commits may ever be made to ports maintained by those groups. We reserve the right to modify the maintainer's submission to better match existing policies and style of the Ports Collection without explicit blessing from the submitter. Also, large infrastructural changes can result in a port being modified without maintainer's consent. This kind of changes will never affect the port's functionality. The &a.portmgr; reserves the right to revoke or override anyone's maintainership for any reason, and the &a.security-officer; reserves the right to revoke or override maintainership for security reasons. <makevar>COMMENT</makevar> This is a one-line description of the port. Please do not include the package name (or version number of the software) in the comment. The comment should begin with a capital and end without a period. Here is an example: COMMENT= A cat chasing a mouse all over the screen The COMMENT variable should immediately follow the MAINTAINER variable in the Makefile. Please try to keep the COMMENT line less than 70 characters, as it is displayed to users as a one-line summary of the port. Dependencies Many ports depend on other ports. There are seven variables that you can use to ensure that all the required bits will be on the user's machine. There are also some pre-supported dependency variables for common cases, plus a few more to control the behavior of dependencies. <makevar>LIB_DEPENDS</makevar> This variable specifies the shared libraries this port depends on. It is a list of lib:dir:target tuples where lib is the name of the shared library, dir is the directory in which to find it in case it is not available, and target is the target to call in that directory. For example, LIB_DEPENDS= jpeg.9:${PORTSDIR}/graphics/jpeg will check for a shared jpeg library with major version 9, and descend into the graphics/jpeg subdirectory of your ports tree to build and install it if it is not found. The target part can be omitted if it is equal to DEPENDS_TARGET (which defaults to install). The lib part is a regular expression which is being looked up in the ldconfig -r output. Values such as intl.[5-7] and intl are allowed. The first pattern, intl.[5-7], will match any of: intl.5, intl.6 or intl.7. The second pattern, intl, will match any version of the intl library. The dependency is checked twice, once from within the extract target and then from within the install target. Also, the name of the dependency is put into the package so that &man.pkg.add.1; will automatically install it if it is not on the user's system. <makevar>RUN_DEPENDS</makevar> This variable specifies executables or files this port depends on during run-time. It is a list of path:dir:target tuples where path is the name of the executable or file, dir is the directory in which to find it in case it is not available, and target is the target to call in that directory. If path starts with a slash (/), it is treated as a file and its existence is tested with test -e; otherwise, it is assumed to be an executable, and which -s is used to determine if the program exists in the search path. For example, RUN_DEPENDS= ${LOCALBASE}/etc/innd:${PORTSDIR}/news/inn \ wish8.0:${PORTSDIR}/x11-toolkits/tk80 will check if the file or directory /usr/local/etc/innd exists, and build and install it from the news/inn subdirectory of the ports tree if it is not found. It will also see if an executable called wish8.0 is in the search path, and descend into the x11-toolkits/tk80 subdirectory of your ports tree to build and install it if it is not found. In this case, innd is actually an executable; if an executable is in a place that is not expected to be in the search path, you should use the full pathname. The official search PATH used on the ports build cluster is /sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:/usr/X11R6/bin The dependency is checked from within the install target. Also, the name of the dependency is put into the package so that &man.pkg.add.1; will automatically install it if it is not on the user's system. The target part can be omitted if it is the same as DEPENDS_TARGET. <makevar>BUILD_DEPENDS</makevar> This variable specifies executables or files this port requires to build. Like RUN_DEPENDS, it is a list of path:dir:target tuples. For example, BUILD_DEPENDS= unzip:${PORTSDIR}/archivers/unzip will check for an executable called unzip, and descend into the archivers/unzip subdirectory of your ports tree to build and install it if it is not found. build here means everything from extraction to compilation. The dependency is checked from within the extract target. The target part can be omitted if it is the same as DEPENDS_TARGET <makevar>FETCH_DEPENDS</makevar> This variable specifies executables or files this port requires to fetch. Like the previous two, it is a list of path:dir:target tuples. For example, FETCH_DEPENDS= ncftp2:${PORTSDIR}/net/ncftp2 will check for an executable called ncftp2, and descend into the net/ncftp2 subdirectory of your ports tree to build and install it if it is not found. The dependency is checked from within the fetch target. The target part can be omitted if it is the same as DEPENDS_TARGET. <makevar>EXTRACT_DEPENDS</makevar> This variable specifies executables or files this port requires for extraction. Like the previous, it is a list of path:dir:target tuples. For example, EXTRACT_DEPENDS= unzip:${PORTSDIR}/archivers/unzip will check for an executable called unzip, and descend into the archivers/unzip subdirectory of your ports tree to build and install it if it is not found. The dependency is checked from within the extract target. The target part can be omitted if it is the same as DEPENDS_TARGET. Use this variable only if the extraction does not already work (the default assumes gzip) and cannot be made to work using USE_ZIP or USE_BZIP2 described in . <makevar>PATCH_DEPENDS</makevar> This variable specifies executables or files this port requires to patch. Like the previous, it is a list of path:dir:target tuples. For example, PATCH_DEPENDS= ${NONEXISTENT}:${PORTSDIR}/java/jfc:extract will descend into the java/jfc subdirectory of your ports tree to extract it. The dependency is checked from within the patch target. The target part can be omitted if it is the same as DEPENDS_TARGET. <makevar>USE_<replaceable>*</replaceable></makevar> A number of variables exist in order to encapsulate common dependencies that many ports have. Although their use is optional, they can help to reduce the verbosity of the port Makefiles. Each of them is styled as USE_*. The usage of these variables is restricted to the port Makefiles and ports/Mk/bsd.*.mk and is not designed to encapsulate user-settable options — use WITH_* and WITHOUT_* for that purpose. It is always incorrect to set any USE_* in /etc/make.conf. For instance, setting USE_GCC=3.2 would adds a dependency on gcc32 for every port, including gcc32 itself! The <makevar>USE_<replaceable>*</replaceable></makevar> variables Variable Means USE_BZIP2 The port's tarballs are compressed with bzip2. USE_ZIP The port's tarballs are compressed with zip. USE_BISON The port uses bison for building. USE_CDRTOOLS 該 port 需要 cdrecord, 無論是 sysutils/cdrtoolssysutils/cdrtools-cjk 哪一種的 cdrecord 皆可,視使用者偏好而定 。 USE_GCC The port requires a specific version of gcc to build. The exact version can be specified with value such as 3.2. The minimal required version can be specified as 3.2+. The gcc from the base system is used when it satisfies the requested version, otherwise an appropriate gcc is compiled from ports and the CC and CXX variables are adjusted.
Variables related to gmake and the configure script are described in , while autoconf, automake and libtool are described in . Perl related variables are described in . X11 variables are listed in . deals with GNOME and with KDE related variables. documents Java variables, while contains information on Apache, PHP and PEAR modules. Python is discussed in , while Ruby in . provides variables used for SDL applications and finally, contains information on Xfce.
Minimal version of a dependency A minimal version of a dependency can be specified in any *_DEPENDS variable except LIB_DEPENDS using the following syntax: p5-Spiffy>=0.26:${PORTSDIR}/devel/p5-Spiffy The first field contains a dependent package name, which must match the entry in the package database, a comparison sign, and a package version. The dependency is satisfied if p5-Spiffy-0.26 or newer is installed on the machine. Notes on dependencies As mentioned above, the default target to call when a dependency is required is DEPENDS_TARGET. It defaults to install. This is a user variable; it is never defined in a port's Makefile. If your port needs a special way to handle a dependency, use the :target part of the *_DEPENDS variables instead of redefining DEPENDS_TARGET. When you type make clean, its dependencies are automatically cleaned too. If you do not wish this to happen, define the variable NOCLEANDEPENDS in your environment. This may be particularly desirable if the port has something that takes a long time to rebuild in its dependency list, such as KDE, GNOME or Mozilla. To depend on another port unconditionally, use the variable ${NONEXISTENT} as the first field of BUILD_DEPENDS or RUN_DEPENDS. Use this only when you need to get the source of the other port. You can often save compilation time by specifying the target too. For instance BUILD_DEPENDS= ${NONEXISTENT}:${PORTSDIR}/graphics/jpeg:extract will always descend to the jpeg port and extract it. Circular dependencies are fatal Do not introduce any circular dependencies into the ports tree! The ports building technology does not tolerate circular dependencies. If you introduce one, you will have someone, somewhere in the world, whose FreeBSD installation will break almost immediately, with many others quickly to follow. These can really be hard to detect; if in doubt, before you make that change, make sure you have done the following: cd /usr/ports; make index. That process can be quite slow on older machines, but you may be able to save a large number of people—including yourself— a lot of grief in the process.
<makevar>MASTERDIR</makevar> If your port needs to build slightly different versions of packages by having a variable (for instance, resolution, or paper size) take different values, create one subdirectory per package to make it easier for users to see what to do, but try to share as many files as possible between ports. Typically you only need a very short Makefile in all but one of the directories if you use variables cleverly. In the sole Makefile, you can use MASTERDIR to specify the directory where the rest of the files are. Also, use a variable as part of PKGNAMESUFFIX so the packages will have different names. This will be best demonstrated by an example. This is part of japanese/xdvi300/Makefile; PORTNAME= xdvi PORTVERSION= 17 PKGNAMEPREFIX= ja- PKGNAMESUFFIX= ${RESOLUTION} : # default RESOLUTION?= 300 .if ${RESOLUTION} != 118 && ${RESOLUTION} != 240 && \ ${RESOLUTION} != 300 && ${RESOLUTION} != 400 @${ECHO_MSG} "Error: invalid value for RESOLUTION: \"${RESOLUTION}\"" @${ECHO_MSG} "Possible values are: 118, 240, 300 (default) and 400." @${FALSE} .endif japanese/xdvi300 also has all the regular patches, package files, etc. If you type make there, it will take the default value for the resolution (300) and build the port normally. As for other resolutions, this is the entire xdvi118/Makefile: RESOLUTION= 118 MASTERDIR= ${.CURDIR}/../xdvi300 .include "${MASTERDIR}/Makefile" (xdvi240/Makefile and xdvi400/Makefile are similar). The MASTERDIR definition tells bsd.port.mk that the regular set of subdirectories like FILESDIR and SCRIPTDIR are to be found under xdvi300. The RESOLUTION=118 line will override the RESOLUTION=300 line in xdvi300/Makefile and the port will be built with resolution set to 118. Manpages The MAN[1-9LN] variables will automatically add any manpages to pkg-plist (this means you must not list manpages in the pkg-plist—see generating PLIST for more). It also makes the install stage automatically compress or uncompress manpages depending on the setting of NOMANCOMPRESS in /etc/make.conf. If your port tries to install multiple names for manpages using symlinks or hardlinks, you must use the MLINKS variable to identify these. The link installed by your port will be destroyed and recreated by bsd.port.mk to make sure it points to the correct file. Any manpages listed in MLINKS must not be listed in the pkg-plist. To specify whether the manpages are compressed upon installation, use the MANCOMPRESSED variable. This variable can take three values, yes, no and maybe. yes means manpages are already installed compressed, no means they are not, and maybe means the software already respects the value of NOMANCOMPRESS so bsd.port.mk does not have to do anything special. MANCOMPRESSED is automatically set to yes if USE_IMAKE is set and NO_INSTALL_MANPAGES is not set, and to no otherwise. You do not have to explicitly define it unless the default is not suitable for your port. If your port anchors its man tree somewhere other than MANPREFIX, you can use the MANPREFIX to set it. Also, if only manpages in certain sections go in a non-standard place, such as some perl modules ports, you can set individual man paths using MANsectPREFIX (where sect is one of 1-9, L or N). If your manpages go to language-specific subdirectories, set the name of the languages to MANLANG. The value of this variable defaults to "" (i.e., English only). Here is an example that puts it all together. MAN1= foo.1 MAN3= bar.3 MAN4= baz.4 MLINKS= foo.1 alt-name.8 MANLANG= "" ja MAN3PREFIX= ${PREFIX}/share/foobar MANCOMPRESSED= yes This states that six files are installed by this port; ${MANPREFIX}/man/man1/foo.1.gz ${MANPREFIX}/man/ja/man1/foo.1.gz ${PREFIX}/share/foobar/man/man3/bar.3.gz ${PREFIX}/share/foobar/man/ja/man3/bar.3.gz ${MANPREFIX}/man/man4/baz.4.gz ${MANPREFIX}/man/ja/man4/baz.4.gz Additionally ${MANPREFIX}/man/man8/alt-name.8.gz may or may not be installed by your port. Regardless, a symlink will be made to join the foo(1) manpage and alt-name(8) manpage. If only some manpages are translated, you can use several variables dynamically created from MANLANG content: MANLANG= "" de ja MAN1= foo.1 MAN1_EN= bar.1 MAN3_DE= baz.3 This translates into this list of files: ${MANPREFIX}/man/man1/foo.1.gz ${MANPREFIX}/man/de/man1/foo.1.gz ${MANPREFIX}/man/ja/man1/foo.1.gz ${MANPREFIX}/man/man1/bar.1.gz ${MANPREFIX}/man/de/man3/baz.3.gz Info files If your package needs to install GNU info files, they should be listed in the INFO variable (without the trailing .info), one entry per document. These files are assumed to be installed to PREFIX/INFO_PATH. You can change INFO_PATH if your package uses a different location. However, this is not recommended. These entries contain just the path relative to PREFIX/INFO_PATH. For example, lang/gcc33 installs info files to PREFIX/INFO_PATH/gcc33, and INFO will be something like this: INFO= gcc33/cpp gcc33/cppinternals gcc33/g77 ... Appropriate installation/de-installation code will be automatically added to the temporary pkg-plist before package registration. Makefile Options Some large applications can be built in a number of configurations, adding functionality if one of a number of libraries or applications is available. Examples include choice of natural (human) language, GUI versus command-line, or type of database to support. Since not all users want those libraries or applications, the ports system provides hooks that the port author can use to control which configuration should be built. Supporting these properly will make users happy, and effectively provide 2 or more ports for the price of one. Knobs <makevar>WITH_<replaceable>*</replaceable></makevar> and <makevar>WITHOUT_<replaceable>*</replaceable></makevar> These variables are designed to be set by the system administrator. There are many that are standardized in ports/Mk/bsd.*.mk; others are not, which can be confusing. If you need to add such a configuration variable, please consider using one of the ones from the following list. You should not assume that a WITH_* necessarily has a corresponding WITHOUT_* variable and vice versa. In general, the default is simply assumed. Unless otherwise specified, these variables are only tested for being set or not set, rather than being set to some kind of variable such as YES or NO. The <makevar>WITH_<replaceable>*</replaceable></makevar> and <makevar>WITHOUT_<replaceable>*</replaceable></makevar> variables Variable Means WITH_APACHE2 If set, use www/apache20 instead of the default of www/apache13. WITH_BERKELEY_DB Define this variable to specify the ability to use a variant of the Berkeley database package such as databases/db41. An associated variable, WITH_BDB_VER, may be set to values such as 2, 3, 4, 41 or 42. WITH_MYSQL Define this variable to specify the ability to use a variant of the MySQL database package such as databases/mysql40-server. An associated variable, WANT_MYSQL_VER, may be set to values such as 323, 40, 41, or 50. WITHOUT_NLS If set, says that internationalization is not needed, which can save compile time. By default, internationalization is used. WITH_OPENSSL_BASE Use the version of OpenSSL in the base system. WITH_OPENSSL_PORT Use the version of OpenSSL from security/openssl, overwriting the version that was originally installed in the base system. WITH_POSTGRESQL Define this variable to specify the ability to use a variant of the PostGreSQL database package such as databases/postgresql72. WITHOUT_X11 If the port can be built both with and without X support, then it should normally be built with X support. If this variable is defined, then the version that does not have X support should be built instead.
Knob naming It is recommended that porters use like-named knobs, for the benefit of end-users and to help keep the number of knob names down. A list of popular knob names can be found in the KNOBS file. Knob names should reflect what the knob is and does. When a port has a lib-prefix in the PORTNAME the lib-prefix should be dropped in knob naming.
<makevar>OPTIONS</makevar> Background The OPTIONS variable gives the user who installs the port a dialog with the available options and saves them to /var/db/ports/portname/options. Next time when the port has to be rebuild, the options are reused. Never again you will have to remember all the twenty WITH_* and WITHOUT_* options you used to build this port! When the user runs make config (or runs make build for the first time), the framework will check for /var/db/ports/portname/options. If that file does not exist, it will use the values of OPTIONS to create a dialogbox where the options can be enabled or disabled. Then the options file is saved and the selected variables will be used when building the port. If a new version of the port adds new OPTIONS, the dialog will be presented to the user, with the saved values of old OPTIONS prefilled. Use make showconfig to see the saved configuration. Use make rmconfig to remove the saved configuration. Syntax The syntax for the OPTIONS variable is: OPTIONS= OPTION "descriptive text" default ... The value for default is either ON or OFF. Multiple repetitions of these three fields are allowed. OPTIONS definition must appear before the inclusion of bsd.port.pre.mk. The WITH_* and WITHOUT_* variables can only be tested after the inclusion of bsd.port.pre.mk. Example Simple use of <makevar>OPTIONS</makevar> OPTIONS= FOO "Enable option foo" On \ BAR "Support feature bar" Off .include <bsd.port.pre.mk> .if defined(WITHOUT_FOO) CONFIGURE_ARGS+= --without-foo .else CONFIGURE_ARGS+= --with-foo .endif .if defined(WITH_BAR) RUN_DEPENDS+= bar:${PORTSDIR}/bar/bar .endif .include <bsd.port.post.mk> Feature auto-activation When using a GNU configure script, keep an eye on which optional features are activated by auto-detection. Explicitly disable optional features you do not wish to be used by passing respective --without-xxx or --disable-xxx in CONFIGURE_ARGS. Wrong handling of an option .if defined(WITH_FOO) LIB_DEPENDS+= foo.0:${PORTSDIR}/devel/foo CONFIGURE_ARGS+= --enable-foo .endif In the example above, imagine a library libfoo is installed on the system. User does not want this application to use libfoo, so he toggled the option off in the make config dialog. But the application's configure script detects the library present in the system and includes its support in the resulting executable. Now when user decides to remove libfoo from the system, the ports system does not protest (no dependency on libfoo was recorded) but the application breaks. Correct handling of an option .if defined(WITH_FOO) LIB_DEPENDS+= foo.0:${PORTSDIR}/devel/foo CONFIGURE_ARGS+= --enable-foo .else CONFIGURE_ARGS+= --disable-foo .endif In the second example, the library libfoo is explicitly disabled. The configure script does not enable related features in the application, despite library's presence in the system.
Specifying the working directory Each port is extracted in to a working directory, which must be writable. The ports system defaults to having the DISTFILES unpack in to a directory called ${DISTNAME}. In other words, if you have set: PORTNAME= foo PORTVERSION= 1.0 then the port's distribution files contain a top-level directory, foo-1.0, and the rest of the files are located under that directory. There are a number of variables you can override if that is not the case. <makevar>WRKSRC</makevar> The variable lists the name of the directory that is created when the application's distfiles are extracted. If our previous example extracted into a directory called foo (and not foo-1.0) you would write: WRKSRC= ${WRKDIR}/foo or possibly WRKSRC= ${WRKDIR}/${PORTNAME} <makevar>NO_WRKSUBDIR</makevar> If the port does not extract in to a subdirectory at all then you should set NO_WRKSUBDIR to indicate that. NO_WRKSUBDIR= yes <makevar>CONFLICTS</makevar> If your package cannot coexist with other packages (because of file conflicts, runtime incompatibility, etc.), list the other package names in the CONFLICTS variable. You can use shell globs like * and ? here. Packages names should be enumerated the same way they appear in /var/db/pkg. Please make sure that CONFLICTS does not match this port's package itself, or else forcing its installation with FORCE_PKG_REGISTER will no longer work. CONFLICTS automatically sets IGNORE, which is more fully documented in . When removing one of several conflicting ports, it is advisable to retain the CONFLICTS entries in those other ports for a few months to cater for users who only update once in a while. Installing files INSTALL_* macros Do use the macros provided in bsd.port.mk to ensure correct modes and ownership of files in your own *-install targets. INSTALL_PROGRAM is a command to install binary executables. INSTALL_SCRIPT is a command to install executable scripts. INSTALL_KLD is a command to install kernel loadable modules. Some architectures don't like it when the modules are stripped, therefor use this command instead of INSTALL_PROGRAM. INSTALL_DATA is a command to install sharable data. INSTALL_MAN is a command to install manpages and other documentation (it does not compress anything). These are basically the install command with all the appropriate flags. Stripping Binaries Do not strip binaries manually unless you have to. All binaries should be stripped, but the INSTALL_PROGRAM macro will install and strip a binary at the same time (see the next section). If you need to strip a file, but do not wish to use the INSTALL_PROGRAM macro, ${STRIP_CMD} will strip your program. This is typically done within the post-install target. For example: post-install: ${STRIP_CMD} ${PREFIX}/bin/xdl Use the &man.file.1; command on the installed executable to check whether the binary is stripped or not. If it does not say not stripped, it is stripped. Additionally, &man.strip.1; will not strip a previously stripped program; it will instead exit cleanly. Installing a whole tree of files Sometimes, there is a need to install a big number of files, preserving their hierarchical organization, ie. copying over a whole directory tree from WRKSRC to a target directory under PREFIX. Two macros exists for this situation. The advantage of using these macros instead of cp is that they guarantee proper file ownership and permissions on target files. First macro, COPYTREE_BIN, will set all the installed files to be executable, thus being suitable for installing into PREFIX/bin. The second macro, COPYTREE_SHARE, does not set executable permissions on files, and is therefore suitable for installing files under PREFIX/share target. post-install: ${MKDIR} ${EXAMPLESDIR} (cd ${WRKSRC}/examples/ && ${COPYTREE_SHARE} \* ${EXAMPLESDIR}) This example will install the contents of examples directory in the vendor distfile to the proper examples location of your port. post-install: ${MKDIR} ${DATADIR}/summer (cd ${WRKSRC}/temperatures/ && ${COPYTREE_SHARE} "June July August" ${DATADIR}/summer/) And this example will install the data of summer months to the summer subdirectory of a DATADIR. Additional find arguments can be passed via the third argument to the COPYTREE_* macros. For example, to install all files from the first example except Makefiles, one can use the following command. post-install: ${MKDIR} ${EXAMPLESDIR} (cd ${WRKSRC}/examples/ && \ ${COPYTREE_SHARE} \* ${EXAMPLESDIR} "! -name Makefile") Note that these macros does not add the installed files to pkg-plist. You still need to list them. Install additional documentation If your software has some documentation other than the standard man and info pages that you think is useful for the user, install it under PREFIX/share/doc. This can be done, like the previous item, in the post-install target. Create a new directory for your port. The directory name should reflect what the port is. This usually means PORTNAME. However, if you think the user might want different versions of the port to be installed at the same time, you can use the whole PKGNAME. Make the installation dependent on the variable NOPORTDOCS so that users can disable it in /etc/make.conf, like this: post-install: .if !defined(NOPORTDOCS) ${MKDIR} ${DOCSDIR} ${INSTALL_MAN} ${WRKSRC}/docs/xvdocs.ps ${DOCSDIR} .endif Here are some handy variables and how they are expanded by default when used in the Makefile: DATADIR gets expanded to PREFIX/share/PORTNAME. DATADIR_REL gets expanded to share/PORTNAME. DOCSDIR gets expanded to PREFIX/share/doc/PORTNAME. DOCSDIR_REL gets expanded to share/doc/PORTNAME. EXAMPLESDIR gets expanded to PREFIX/share/examples/PORTNAME. EXAMPLESDIR_REL gets expanded to share/examples/PORTNAME. NOPORTDOCS only controls additional documentation installed in DOCSDIR. It does not apply to standard man pages and info pages. Things installed in DATADIR and EXAMPLESDIR are controlled by NOPORTDATA and NOPORTEXAMPLES, respectively. These variables are exported to PLIST_SUB. Their values will appear there as pathnames relative to PREFIX if possible. That is, share/doc/PORTNAME will be substituted for %%DOCSDIR%% in the packing list by default, and so on. (See more on pkg-plist substitution here.) All conditionally installed documentation files and directories should be included in pkg-plist with the %%PORTDOCS%% prefix, for example: %%PORTDOCS%%%%DOCSDIR%%/AUTHORS %%PORTDOCS%%%%DOCSDIR%%/CONTACT %%PORTDOCS%%@dirrm %%DOCSDIR%% As an alternative to enumerating the documentation files in pkg-plist, a port can set the variable PORTDOCS to a list of file names and shell glob patterns to add to the final packing list. The names will be relative to DOCSDIR. Therefore, a port that utilizes PORTDOCS and uses a non-default location for its documentation should set DOCSDIR accordingly. If a directory is listed in PORTDOCS or matched by a glob pattern from this variable, the entire subtree of contained files and directories will be registered in the final packing list. If NOPORTDOCS is defined then files and directories listed in PORTDOCS would not be installed and neither would be added to port packing list. Installing the documentation at PORTDOCS as shown above remains up to the port itself. A typical example of utilizing PORTDOCS looks as follows: PORTDOCS= README.* ChangeLog docs/* The equivalents of PORTDOCS for files installed under DATADIR and EXAMPLESDIR are PORTDATA and PORTEXAMPLES, respectively. You can also use the pkg-message file to display messages upon installation. See the section on using pkg-message for details. The pkg-message file does not need to be added to pkg-plist. Subdirectories under PREFIX Try to let the port put things in the right subdirectories of PREFIX. Some ports lump everything and put it in the subdirectory with the port's name, which is incorrect. Also, many ports put everything except binaries, header files and manual pages in a subdirectory of lib, which does not work well with the BSD paradigm. Many of the files should be moved to one of the following: etc (setup/configuration files), libexec (executables started internally), sbin (executables for superusers/managers), info (documentation for info browser) or share (architecture independent files). See &man.hier.7; for details; the rules governing /usr pretty much apply to /usr/local too. The exception are ports dealing with USENET news. They may use PREFIX/news as a destination for their files.
Special considerations There are some more things you have to take into account when you create a port. This section explains the most common of those. Shared Libraries If your port installs one or more shared libraries, define a USE_LDCONFIG make variable, which will instruct a bsd.port.mk to run ${LDCONFIG} -m on the directory where the new library is installed (usually PREFIX/lib) during post-install target to register it into the shared library cache. This variable, when defined, will also facilitate addition of an appropriate @exec /sbin/ldconfig -m and @unexec /sbin/ldconfig -R pair into your pkg-plist file, so that a user who installed the package can start using the shared library immediately and de-installation will not cause the system to still believe the library is there. USE_LDCONFIG= yes If you need, you can override the default directory by setting the USE_LDCONFIG value to a list of directories into which shared libraries are to be installed. For example if your port installs shared libraries into PREFIX/lib/foo and PREFIX/lib/bar directories you could use the following in your Makefile: USE_LDCONFIG= ${PREFIX}/lib/foo ${PREFIX}/lib/bar Please double-check, often this is not necessary at all or can be avoided through -rpath or setting LD_RUN_PATH during linking (see lang/moscow_ml for an example), or through a shell-wrapper which sets LD_LIBRARY_PATH before invoking the binary, like www/mozilla does. When installing 32-bit libraries on 64-bit system, use USE_LDCONFIG32 instead. Try to keep shared library version numbers in the libfoo.so.0 format. Our runtime linker only cares for the major (first) number. When the major library version number increments in the update to the new port version, all other ports that link to the affected library should have their PORTREVISION incremented, to force recompilation with the new library version. Ports with distribution restrictions Licenses vary, and some of them place restrictions on how the application can be packaged, whether it can be sold for profit, and so on. It is your responsibility as a porter to read the licensing terms of the software and make sure that the FreeBSD project will not be held accountable for violating them by redistributing the source or compiled binaries either via FTP/HTTP or CD-ROM. If in doubt, please contact the &a.ports;. In situations like this, the variables described in the following sections can be set. <makevar>NO_PACKAGE</makevar> This variable indicates that we may not generate a binary package of the application. For instance, the license may disallow binary redistribution, or it may prohibit distribution of packages created from patched sources. However, the port's DISTFILES may be freely mirrored on FTP/HTTP. They may also be distributed on a CD-ROM (or similar media) unless NO_CDROM is set as well. NO_PACKAGE should also be used if the binary package is not generally useful, and the application should always be compiled from the source code. For example, if the application has configuration information that is site specific hard coded in to it at compile time, set NO_PACKAGE. NO_PACKAGE should be set to a string describing the reason why the package should not be generated. <makevar>NO_CDROM</makevar> This variable alone indicates that, although we are allowed to generate binary packages, we may put neither those packages nor the port's DISTFILES onto a CD-ROM (or similar media) for resale. However, the binary packages and the port's DISTFILES will still be available via FTP/HTTP. If this variable is set along with NO_PACKAGE, then only the port's DISTFILES will be available, and only via FTP/HTTP. NO_CDROM should be set to a string describing the reason why the port cannot be redistributed on CD-ROM. For instance, this should be used if the port's license is for non-commercial use only. <makevar>NOFETCHFILES</makevar> Files defined in the NOFETCHFILES variable are not fetchable from any of the MASTER_SITES. An example of such a file is when the file is supplied on CD-ROM by the vendor. Tools which check for the availability of these files on the MASTER_SITES should ignore these files and not report about them. <makevar>RESTRICTED</makevar> Set this variable alone if the application's license permits neither mirroring the application's DISTFILES nor distributing the binary package in any way. NO_CDROM or NO_PACKAGE should not be set along with RESTRICTED since the latter variable implies the former ones. RESTRICTED should be set to a string describing the reason why the port cannot be redistributed. Typically, this indicates that the port contains proprietary software and that the user will need to manually download the DISTFILES, possibly after registering for the software or agreeing to accept the terms of an EULA. <makevar>RESTRICTED_FILES</makevar> When RESTRICTED or NO_CDROM is set, this variable defaults to ${DISTFILES} ${PATCHFILES}, otherwise it is empty. If only some of the distribution files are restricted, then set this variable to list them. Note that the port committer should add an entry to /usr/ports/LEGAL for every listed distribution file, describing exactly what the restriction entails. Building mechanisms <command>make</command>, <command>gmake</command>, and <command>imake</command> If your port uses GNU make, set USE_GMAKE=yes. Variables for ports related to gmake Variable Means USE_GMAKE The port requires gmake to build. GMAKE The full path for gmake if it is not in the PATH.
If your port is an X application that creates Makefile files from Imakefile files using imake, then set USE_IMAKE=yes. This will cause the configure stage to automatically do an xmkmf -a. If the flag is a problem for your port, set XMKMF=xmkmf. If the port uses imake but does not understand the install.man target, NO_INSTALL_MANPAGES=yes should be set. If your port's source Makefile has something else than all as the main build target, set ALL_TARGET accordingly. Same goes for install and INSTALL_TARGET.
<command>configure</command> script If your port uses the configure script to generate Makefile files from Makefile.in files, set GNU_CONFIGURE=yes. If you want to give extra arguments to the configure script (the default argument is --prefix=${PREFIX} --infodir=${PREFIX}/${INFO_PATH} --mandir=${MANPREFIX}/man ${CONFIGURE_TARGET}), set those extra arguments in CONFIGURE_ARGS. Extra environment variables can be passed using CONFIGURE_ENV variable. If your package uses GNU configure, and the resulting executable file has a strange name like i386-portbld-freebsd4.7-appname, you will need to additionally override the CONFIGURE_TARGET variable to specify the target in the way required by scripts generated by recent versions of autoconf. Add the following line immediately after the GNU_CONFIGURE=yes line in your Makefile: CONFIGURE_TARGET=--build=${MACHINE_ARCH}-portbld-freebsd${OSREL} Variables for ports that use configure Variable Means GNU_CONFIGURE The port uses configure script to prepare build. HAS_CONFIGURE Same as GNU_CONFIGURE, except default configure target is not added to CONFIGURE_ARGS. CONFIGURE_ARGS Additional arguments passed to configure script. CONFIGURE_ENV Additional environment variables to be set for configure script run. CONFIGURE_TARGET Override default configure target. Default value is ${MACHINE_ARCH}-portbld-freebsd${OSREL}.
Using <command>scons</command> If your port uses SCons, define USE_SCONS=yes. Variables for ports that use <command>scons</command> Variable Means SCONS_ARGS Port specific SCons flags passed to the SCons environment. SCONS_BUILDENV Variables to be set in system environment. SCONS_ENV Variables to be set in SCons environment. SCONS_TARGET Last argument passed to SCons, similar to MAKE_TARGET.
Using GNU autotools Introduction The various GNU autotools provide an abstraction mechanism for building a piece of software over a wide variety of operating systems and machine architectures. Within the Ports Collection, an individual port can make use of these tools via a simple construct: USE_AUTOTOOLS= tool:version[:operation] ... At the time of writing, tool can be one of libtool, libltdl, autoconf, autoheader, automake or aclocal. version specifies the particular tool revision to be used (see devel/{automake,autoconf,libtool}[0-9]+ for valid versions). operation is an optional extension to modify how the tool is used. Multiple tools can be specified at once, either by including them all on a single line, or using the += Makefile construct. Finally, there is the special tool, called autotools, which is a convenience function to bring in all available versions of the autotools to allow for cross-development work. This can also be accomplished by installing the devel/autotools port. <command>libtool</command> Shared libraries using the GNU building framework usually use libtool to adjust the compilation and installation of shared libraries to match the specifics of the underlying operating system. The usual practice is to use copy of libtool bundled with the application. In case you need to use external libtool, you can use the version provided by The Ports Collection: USE_AUTOTOOLS= libtool:version[:env] With no additional operations, libtool:version tells the building framework to patch the configure script with the system-installed copy of libtool. The GNU_CONFIGURE is implied. Further, a number of make and shell variables will be assigned for onward use by the port. See bsd.autotools.mk for details. With the :env operation, only the environment will be set up. Finally, LIBTOOLFLAGS and LIBTOOLFILES can be optionally set to override the most likely arguments to, and files patched by, libtool. Most ports are unlikely to need this. See bsd.autotools.mk for further details. <command>libltdl</command> Some ports make use of the libltdl library package, which is part of the libtool suite. Use of this library does not automatically necessitate the use of libtool itself, so a separate construct is provided. USE_AUTOTOOLS= libltdl:version Currently, all this does is to bring in a LIB_DEPENDS on the appropriate libltdl port, and is provided as a convenience function to help eliminate any dependencies on the autotools ports outside of the USE_AUTOTOOLS framework. There are no optional operations for this tool. <command>autoconf</command> and <command>autoheader</command> Some ports do not contain a configure script, but do contain an autoconf template in the configure.ac file. You can use the following assignments to let autoconf create the configure script, and also have autoheader create template headers for use by the configure script. USE_AUTOTOOLS= autoconf:version[:env] and USE_AUTOTOOLS= autoheader:version which also implies the use of autoconf:version. Similarly to libtool, the inclusion of the optional :env operation simply sets up the environment for further use. Without it, patching and reconfiguration of the port is carried out. The additional optional variables AUTOCONF_ARGS and AUTOHEADER_ARGS can be overridden by the port Makefile if specifically requested. As with the libtool equivalents, most ports are unlikely to need this. <command>automake</command> and <command>aclocal</command> Some packages only contain Makefile.am files. These have to be converted into Makefile.in files using automake, and the further processed by configure to generate an actual Makefile. Similarly, packages occasionally do not ship with included aclocal.m4 files, again required to build the software. This can be achieved with aclocal, which scans configure.ac or configure.in. aclocal has a similar relationship to automake as autoheader does to autoconf, described in the previous section. aclocal implies the use of automake, thus we have: USE_AUTOTOOLS= automake:version[:env] and USE_AUTOTOOLS= aclocal:version which also implies the use of automake:version. Similarly to libtool and autoconf, the inclusion of the optional :env operation simply sets up the environment for further use. Without it, reconfiguration of the port is carried out. As with autoconf and autoheader, both automake and aclocal have optional argument variables, AUTOMAKE_ARGS and ACLOCAL_ARGS respectively, which may be overriden by the port Makefile if required. Using GNU <literal>gettext</literal> Basic usage If your port requires gettext, just set USE_GETTEXT to yes, and your port will grow the dependency on devel/gettext. The value of USE_GETTEXT can also specify the required version of the libintl library, the basic part of gettext, but using this feature is strongly discouraged: Your port should work with just the current version of devel/gettext. A rather common case is a port using gettext and configure. Generally, GNU configure should be able to locate gettext automatically. If it ever fails to, hints at the location of gettext can be passed in CPPFLAGS and LDFLAGS as follows: USE_GETTEXT= yes CPPFLAGS+= -I${LOCALBASE}/include LDFLAGS+= -L${LOCALBASE}/lib GNU_CONFIGURE= yes CONFIGURE_ENV= CPPFLAGS="${CPPFLAGS}" \ LDFLAGS="${LDFLAGS}" Of course, the code can be more compact if there are no more flags to pass to configure: USE_GETTEXT= yes GNU_CONFIGURE= yes CONFIGURE_ENV= CPPFLAGS="-I${LOCALBASE}/include" \ LDFLAGS="-L${LOCALBASE}/lib" Optional usage Some software products allow for disabling NLS, e.g., through passing to configure. In that case, your port should use gettext conditionally, depending on the status of WITHOUT_NLS. For ports of low to medium complexity, you can rely on the following idiom: GNU_CONFIGURE= yes .if !defined(WITHOUT_NLS) USE_GETTEXT= yes PLIST_SUB+= NLS="" .else CONFIGURE_ARGS+= --disable-nls PLIST_SUB+= NLS="@comment " .endif The next item on your to-do list is to arrange so that the message catalog files are included in the packing list conditionally. The Makefile part of this task is already provided by the idiom. It is explained in the section on advanced pkg-plist practices. In a nutshell, each occurrence of %%NLS%% in pkg-plist will be replaced by @comment  if NLS is disabled, or by a null string if NLS is enabled. Consequently, the lines prefixed by %%NLS%% will become mere comments in the final packing list if NLS is off; otherwise the prefix will be just left out. All you need to do now is insert %%NLS%% before each path to a message catalog file in pkg-plist. For example: %%NLS%%share/locale/fr/LC_MESSAGES/foobar.mo %%NLS%%share/locale/no/LC_MESSAGES/foobar.mo In high complexity cases, you may need to use more advanced techniques than the recipe given here, such as dynamic packing list generation. Handling message catalog directories There is a point to note about installing message catalog files. The target directories for them, which reside under LOCALBASE/share/locale, should rarely be created and removed by your port. The most popular languages have their respective directories listed in /etc/mtree/BSD.local.dist; that is, they are a part of the base system. The directories for many other languages are governed by the devel/gettext port. You may want to consult its pkg-plist and see whether your port is going to install a message catalog file for a unique language. Using <literal>perl</literal> If MASTER_SITES is set to MASTER_SITE_PERL_CPAN, then preferred value of MASTER_SITE_SUBDIR is top-level hierarchy name. For example, the recommend value for p5-Module-Name is Module. The top-level hierarchy can be examined at cpan.org. This keeps the port working when the author of the module changes. The exception to this rule is when the relevant directory does not exist or the distfile does not exist in the directory. In such case, using author's id as MASTER_SITE_SUBDIR is allowed. All of the tunable knobs below accept both YES and a version string, like 5.8.0+. Using YES means that the port can be used with all of the supported Perl versions. If a port only works with specific versions of Perl, it can be indicated with a version string, specifying a minimal version (e.g. 5.7.3+), a maximal version (e.g. 5.8.0-) or an exact version (e.g. 5.8.3). Variables for ports that use <literal>perl</literal> Variable Means USE_PERL5 Says that the port uses perl 5 to build and run. USE_PERL5_BUILD Says that the port uses perl 5 to build. USE_PERL5_RUN Says that the port uses perl 5 to run. PERL The full path of perl 5, either in the system or installed from a port, but without the version number. Use this if you need to replace #!lines in scripts. PERL_CONFIGURE Configure using Perl's MakeMaker. It implies USE_PERL5. PERL_MODBUILD Configure, build and install using Module::Build. It implies PERL_CONFIGURE. Read only variables PERL_VERSION The full version of perl installed (e.g., 5.00503). PERL_VER The short version of perl installed (e.g., 5.005). PERL_LEVEL The installed perl version as an integer of the form MNNNPP (e.g., 500503). PERL_ARCH Where perl stores architecture dependent libraries. Defaults to ${ARCH}-freebsd. PERL_PORT Name of the perl port that is installed (e.g., perl5). SITE_PERL Directory name where site specific perl packages go. This value is added to PLIST_SUB.
Perl 模組的 port,由於沒有正式的網站,所以 pkg-descr 內的 WWW 應該指向至 cpan.org。 比較好的 URL 格式是 http://search.cpan.org/dist/Module-Name/ (包括結尾的 / 斜線符號)。
Using X11 X.Org components The X11 implementation available in The Ports Collection is X.Org. If your application depends on X components, set USE_XORG to the list of required components. Available components, at the time of writing, are: bigreqsproto compositeproto damageproto dmx dmxproto evieproto fixesproto fontcacheproto fontenc fontsproto fontutil glproto ice inputproto kbproto libfs oldx printproto randrproto recordproto renderproto resourceproto scrnsaverproto sm trapproto videoproto x11 xau xaw xaw6 xaw7 xaw8 xbitmaps xcmiscproto xcomposite xcursor xdamage xdmcp xevie xext xextproto xf86bigfontproto xf86dgaproto xf86driproto xf86miscproto xf86rushproto xf86vidmodeproto xfixes xfont xfontcache xft xi xinerama xineramaproto xkbfile xkbui xmu xmuu xorg-server xp xpm xprintapputil xprintutil xpr oto xproxymngproto xrandr xrender xres xscrnsaver xt xtrans xtrap xtst xv xvmc xxf86dga xxf86misc xxf86vm. Always up-to-date list can be found in /usr/ports/Mk/bsd.xorg.mk. The Mesa Project is an effort to provide free OpenGL implementation. You can specify a dependency on various components of this project with USE_GL variable. Valid options are: glut, glu, glw, gl and linux. For backwards compatibility, the value of yes maps to glu. USE_XORG example USE_XORG= xrender xft xkbfile xt xaw USE_GL= glu Many ports define USE_XLIB, which makes the port depend on all the 50 or so libraries. This variable exists for backwards compatibility, as it predates modular X.Org, and should not be used on new ports. Variables for ports that use X USE_XLIB The port uses the X libraries. Deprecated - use a list of X.Org components in USE_XORG variable instead. USE_IMAKE 會用到 imake 的 port。 USE_X_PREFIX Deprecated. Today it is equivalent to USE_XLIB and can be replaced by it freely. XMKMF Set to the path of xmkmf if not in the PATH. Defaults to xmkmf -a.
Variables for depending on individual parts of X11 X_IMAKE_PORT Port providing imake and several other utilities used to build X11. X_LIBRARIES_PORT Port providing X11 libraries. X_CLIENTS_PORT Port providing X clients. X_SERVER_PORT Port providing X server. X_FONTSERVER_PORT Port providing font server. X_PRINTSERVER_PORT Port providing print server. X_VFBSERVER_PORT Port providing virtual framebuffer server. X_NESTSERVER_PORT Port providing a nested X server. X_FONTS_ENCODINGS_PORT Port providing encodings for fonts. X_FONTS_MISC_PORT Port providing miscellaneous bitmap fonts. X_FONTS_100DPI_PORT Port providing 100dpi bitmap fonts. X_FONTS_75DPI_PORT Port providing 75dpi bitmap fonts. X_FONTS_CYRILLIC_PORT Port providing cyrillic bitmap fonts. X_FONTS_TTF_PORT Port providing &truetype; fonts. X_FONTS_TYPE1_PORT Port providing Type1 fonts. X_MANUALS_PORT Port providing developer oriented manual pages
Using X11 related variables in port # Use X11 libraries and depend on # font server as well as cyrillic fonts. RUN_DEPENDS= ${X11BASE}/bin/xfs:${X_FONTSERVER_PORT} \ ${X11BASE}/lib/X11/fonts/cyrillic/crox1c.pcf.gz:${X_FONTS_CYRILLIC_PORT} USE_XLIB= yes
Ports that require Motif If your port requires a Motif library, define USE_MOTIF in the Makefile. Default Motif implementation is x11-toolkits/open-motif. Users can choose x11-toolkits/lesstif instead by setting WANT_LESSTIF variable. The MOTIFLIB variable will be set by bsd.port.mk to reference the appropriate Motif library. Please patch the source of your port to use ${MOTIFLIB} wherever the Motif library is referenced in the original Makefile or Imakefile. There are two common cases: If the port refers to the Motif library as -lXm in its Makefile or Imakefile, simply substitute ${MOTIFLIB} for it. If the port uses XmClientLibs in its Imakefile, change it to ${MOTIFLIB} ${XTOOLLIB} ${XLIB}. Note that MOTIFLIB (usually) expands to -L/usr/X11R6/lib -lXm or /usr/X11R6/lib/libXm.a, so there is no need to add -L or -l in front. X11 fonts If your port installs fonts for the X Window System, put them in X11BASE/lib/X11/fonts/local. Getting fake <envar>DISPLAY</envar> using Xvfb Some applications require a working X11 display for compilation to succeed. This pose a problem for the FreeBSD package building cluster, which operates headless. When the following canonical hack is used, the package cluster will start the virtual framebuffer X server. The working DISPLAY is then passed to the build. USE_DISPLAY= yes Desktop entries 可藉由設定 DESKTOP_ENTRIES 變數,以輕鬆設定 port 的 X 選單項目 (Desktop Entries,請參閱 Freedesktop standard)。 這些項目會在相應的桌面環境如 GNOME 或 KDE 的應用程式選單中出現。 .desktop 檔案 將會被建立、安裝以及自動加入 pkg-plist 中。語法為: DESKTOP_ENTRIES= "NAME" "COMMENT" "ICON" "COMMAND" "CATEGORY" StartupNotify 可供使用的分類可參考 Freedesktop 網站。 而 StartupNotify 變數會決定程式,是否支援 startup noficication 的環境。 範例: DESKTOP_ENTRIES= "ToME" "Roguelike game based on JRR Tolkien's work" \ "${DATADIR}/xtra/graf/tome-128.png" \ "tome -v -g" "Application;Game;RolePlaying" \ false
Using GNOME The FreeBSD/GNOME project uses its own set of variables to define which GNOME components a particular port uses. A comprehensive list of these variables exists within the FreeBSD/GNOME project's homepage. Using KDE Variable definitions Variables for ports that use KDE USE_KDELIBS_VER The port uses KDE libraries. It specifies the major version of KDE to use and implies USE_QT_VER of the appropriate version. The only possible value is 3. USE_KDEBASE_VER The port uses KDE base. It specifies the major version of KDE to use and implies USE_QT_VER of the appropriate version. The only possible value is 3.
Ports that require Qt Variables for ports that use Qt USE_QT_VER The port uses the Qt toolkit. Possible values are 3 and 4; each specify the major version of Qt to use. Appropriate parameters are passed to configure script and make. QT_PREFIX Set to the path where Qt installed to (read-only variable). MOC Set to the path of moc (read-only variable). Default set according to USE_QT_VER value. QTCPPFLAGS Additional compiler flags passed via CONFIGURE_ENV for Qt toolkit. Default set according to USE_QT_VER. QTCFGLIBS Additional libraries for linking passed via CONFIGURE_ENV for Qt toolkit. Default set according to USE_QT_VER. QTNONSTANDARD Suppress modification of CONFIGURE_ENV, CONFIGURE_ARGS, and MAKE_ENV.
Additional variables for ports that use Qt 4.x QT_COMPONENTS Specify tool and library dependencies for Qt4. See below for details. UIC Set to the path of uic (read-only variable). Default set according to USE_QT_VER value. QMAKE Set to the path of qmake (read-only variable). Default set according to USE_QT_VER value. QMAKESPEC Set to the path of configuration file for qmake (read-only variable). Default set according to USE_QT_VER value.
When USE_QT_VER is set, some useful settings are passed to configure script: CONFIGURE_ARGS+= --with-qt-includes=${QT_PREFIX}/include \ --with-qt-libraries=${QT_PREFIX}/lib \ --with-extra-libs=${LOCALBASE}/lib \ --with-extra-includes=${LOCALBASE}/include CONFIGURE_ENV+= MOC="${MOC}" CPPFLAGS="${CPPFLAGS} ${QTCPPFLAGS}" LIBS="${QTCFGLIBS}" \ QTDIR="${QT_PREFIX}" KDEDIR="${KDE_PREFIX}" If USE_QT_VER is set to 4, the following settings are also deployed: CONFIGURE_ENV+= UIC="${UIC}" QMAKE="${QMAKE}" QMAKESPEC="${QMAKESPEC}" MAKE_ENV+= QMAKESPEC="${QMAKESPEC}"
Component selection (Qt 4.x only) When USE_QT_VER is set to 4, individual Qt4 tool and library dependencies can be specified in the QT_COMPONENTS variable. Every component can be suffixed by either _build or _run, the suffix indicating whether the component should be depended on at buildtime or runtime, respectively. If unsuffixed, the component will be depended on at both build- and runtime. Usually, library components should be specified unsuffixed, tool components should be specified with the _build suffix and plugin components should be specified with the _run suffix. The most commonly used components are listed below (all available components are listed in _QT_COMPONENTS_ALL in /usr/ports/Mk/bsd.qt.mk): Available Qt4 library components Name Description corelib core library (can be omitted unless the port uses nothing but corelib) gui graphical user interface library network network library opengl OpenGL library qt3support Qt3 compatibility library qtestlib unit testing library script script library sql SQL library xml XML library
You can determine which libraries the application depends on, by running ldd on the main executable after a successful compilation. Available Qt4 tool components Name Description moc meta object compiler (needed for almost every Qt application at buildtime) qmake Makefile generator / build utility rcc resource compiler (need if the application comes with *.rc or *.qrc files) uic user interface compiler (needed if the application comes with *.ui files created by Qt Designer - in practice, every Qt application with a GUI)
Available Qt4 plugin components Name Description iconengines SVG icon engine plugin (if the application ships SVG icons) imageformats imageformat plugins for GIF, JPEG, MNG and SVG (if the application ships image files)
Selecting Qt4 components In this example, the ported application uses the Qt4 graphical user interface library, the Qt4 core library, all of the Qt4 code generation tools and Qt4's Makefile generator. Since the gui library implies a dependency on the core library, corelib does not need to be specified. The Qt4 code generation tools moc, uic and rcc, as well as the Makefile generator qmake are only needed at buildtime, thus they are specified with the _build suffix: USE_QT_VER= 4 QT_COMPONENTS= gui moc_build qmake_build rcc_build uic_build
Additional considerations If the application does not provide a configure file but a .pro file, you can use the following: HAS_CONFIGURE= yes do-configure: @cd ${WRKSRC} && ${SETENV} ${CONFIGURE_ENV} \ ${QMAKE} -unix PREFIX=${PREFIX} texmaker.pro Note the similarity to the qmake line from the provided BUILD.sh script. Passing CONFIGURE_ENV ensures qmake will see the QMAKESPEC variable, without which it cannot work. qmake generates standard Makefiles, so it is not necessary to write our own build target. Qt applications often are written to be cross-platform and often X11/Unix isn't the platform they are developed on, which in turn often leads to certain loose ends, like: Missing additional includepaths. Many applications come with system tray icon support, but neglect to look for includes and/or libraries in the X11 directories. You can tell qmake to add directories to the include and library searchpaths via the commandline, for example: ${QMAKE} -unix PREFIX=${PREFIX} INCLUDEPATH+=${X11BASE}/include \ LIBS+=-L${X11BASE}/lib sillyapp.pro Bogus installation paths. Sometimes data such as icons or .desktop files are by default installed into directories which aren't scanned by XDG-compatible applications. editors/texmaker is an example for this - look at patch-texmaker.pro in the files directory of that port for a template on how to remedy this directly in the Qmake project file.
Using Java Variable definitions If your port needs a Java™ Development Kit (JDK) to either build, run or even extract the distfile, then it should define USE_JAVA. There are several JDKs in the ports collection, from various vendors, and in several versions. If your port must use one of these versions, you can define which one. The most current version is java/jdk15. Variables that may be set by ports that use Java Variable Means USE_JAVA Should be defined for the remaining variables to have any effect. JAVA_VERSION List of space-separated suitable Java versions for the port. An optional "+" allows you to specify a range of versions (allowed values: 1.1[+] 1.2[+] 1.3[+] 1.4[+]). JAVA_OS List of space-separated suitable JDK port operating systems for the port (allowed values: native linux). JAVA_VENDOR List of space-separated suitable JDK port vendors for the port (allowed values: freebsd bsdjava sun ibm blackdown). JAVA_BUILD When set, it means that the selected JDK port should be added to the build dependencies of the port. JAVA_RUN When set, it means that the selected JDK port should be added to the run dependencies of the port. JAVA_EXTRACT When set, it means that the selected JDK port should be added to the extract dependencies of the port. USE_JIKES Whether the port should or should not use the jikes bytecode compiler to build. When no value is set for this variable, the port will use jikes to build if available. You may also explicitly forbid or enforce the use of jikes (by setting 'no' or 'yes'). In the later case, devel/jikes will be added to build dependencies of the port. In any case that jikes is actually used in place of javac, then the HAVE_JIKES variable is defined by bsd.java.mk.
Below is the list of all settings a port will receive after setting USE_JAVA: Variables provided to ports that use Java Variable Value JAVA_PORT The name of the JDK port (e.g. 'java/jdk14'). JAVA_PORT_VERSION The full version of the JDK port (e.g. '1.4.2'). If you only need the first two digits of this version number, use ${JAVA_PORT_VERSION:C/^([0-9])\.([0-9])(.*)$/\1.\2/}. JAVA_PORT_OS The operating system used by the JDK port (e.g. 'linux'). JAVA_PORT_VENDOR The vendor of the JDK port (e.g. 'sun'). JAVA_PORT_OS_DESCRIPTION Description of the operating system used by the JDK port (e.g. 'Linux'). JAVA_PORT_VENDOR_DESCRIPTION Description of the vendor of the JDK port (e.g. 'FreeBSD Foundation'). JAVA_HOME Path to the installation directory of the JDK (e.g. '/usr/local/jdk1.3.1'). JAVAC Path to the Java compiler to use (e.g. '/usr/local/jdk1.1.8/bin/javac' or '/usr/local/bin/jikes'). JAR Path to the jar tool to use (e.g. '/usr/local/jdk1.2.2/bin/jar' or '/usr/local/bin/fastjar'). APPLETVIEWER Path to the appletviewer utility (e.g. '/usr/local/linux-jdk1.2.2/bin/appletviewer'). JAVA Path to the java executable. Use this for executing Java programs (e.g. '/usr/local/jdk1.3.1/bin/java'). JAVADOC Path to the javadoc utility program. JAVAH Path to the javah program. JAVAP Path to the javap program. JAVA_KEYTOOL Path to the keytool utility program. This variable is available only if the JDK is Java 1.2 or higher. JAVA_N2A Path to the native2ascii tool. JAVA_POLICYTOOL Path to the policytool program. This variable is available only if the JDK is Java 1.2 or higher. JAVA_SERIALVER Path to the serialver utility program. RMIC Path to the RMI stub/skeleton generator, rmic. RMIREGISTRY Path to the RMI registry program, rmiregistry. RMID Path to the RMI daemon program rmid. This variable is only available if the JDK is Java 1.2 or higher. JAVA_CLASSES Path to the archive that contains the JDK class files. On JDK 1.2 or later, this is ${JAVA_HOME}/jre/lib/rt.jar. Earlier JDKs used ${JAVA_HOME}/lib/classes.zip. HAVE_JIKES Defined whenever jikes is used by the port (see USE_JIKES above).
You may use the java-debug make target to get information for debugging your port. It will display the value of many of the forecited variables. Additionally, the following constants are defined so all Java ports may be installed in a consistent way: Constants defined for ports that use Java Constant Value JAVASHAREDIR The base directory for everything related to Java. Default: ${PREFIX}/share/java. JAVAJARDIR The directory where JAR files should be installed. Default: ${JAVASHAREDIR}/classes. JAVALIBDIR The directory where JAR files installed by other ports are located. Default: ${LOCALBASE}/share/java/classes.
The related entries are defined in both PLIST_SUB (documented in ) and SUB_LIST.
Building with Ant When the port is to be built using Apache Ant, it has to define USE_ANT. Ant is thus considered to be the sub-make command. When no do-build target is defined by the port, a default one will be set that simply runs Ant according to MAKE_ENV, MAKE_ARGS and ALL_TARGETS. This is similar to the USE_GMAKE mechanism, which is documented in . If jikes is used in place of javac (see USE_JIKES in ), then Ant will automatically use it to build the port. Best practices When porting a Java library, your port should install the JAR file(s) in ${JAVAJARDIR}, and everything else under ${JAVASHAREDIR}/${PORTNAME} (except for the documentation, see below). In order to reduce the packing file size, you may reference the JAR file(s) directly in the Makefile. Just use the following statement (where myport.jar is the name of the JAR file installed as part of the port): PLIST_FILES+= %%JAVAJARDIR%%/myport.jar When porting a Java application, the port usually installs everything under a single directory (including its JAR dependencies). The use of ${JAVASHAREDIR}/${PORTNAME} is strongly encouraged in this regard. It is up the porter to decide whether the port should install the additional JAR dependencies under this directory or directly use the already installed ones (from ${JAVAJARDIR}). Regardless of the type of your port (library or application), the additional documentation should be installed in the same location as for any other port. The JavaDoc tool is known to produce a different set of files depending on the version of the JDK that is used. For ports that do not enforce the use of a particular JDK, it is therefore a complex task to specify the packing list (pkg-plist). This is one reason why porters are strongly encouraged to use the PORTDOCS macro. Moreover, even if you can predict the set of files that will be generated by javadoc, the size of the resulting pkg-plist advocates for the use of PORTDOCS. The default value for DATADIR is ${PREFIX}/share/${PORTNAME}. It is a good idea to override DATADIR to ${JAVASHAREDIR}/${PORTNAME} for Java ports. Indeed, DATADIR is automatically added to PLIST_SUB (documented in ) so you may use %%DATADIR%% directly in pkg-plist. As for the choice of building Java ports from source or directly installing them from a binary distribution, there is no defined policy at the time of writing. However, people from the &os; Java Project encourage porters to have their ports built from source whenever it is a trivial task. All the features that have been presented in this section are implemented in bsd.java.mk. If you ever think that your port needs more sophisticated Java support, please first have a look at the bsd.java.mk CVS log as it usually takes some time to document the latest features. Then, if you think the support you are lacking would be beneficial to many other Java ports, feel free to discuss it on the &a.java;. Although there is a java category for PRs, it refers to the JDK porting effort from the &os; Java project. Therefore, you should submit your Java port in the ports category as for any other port, unless the issue you are trying to resolve is related to either a JDK implementation or bsd.java.mk. Similarly, there is a defined policy regarding the CATEGORIES of a Java port, which is detailed in .
Web applications, Apache and PHP Apache Variables for ports that use Apache USE_APACHE The port requires Apache. Possible values: yes (gets any version), 1.3, 2.0, 2.2, 2.0+, etc. Default dependency is on version 1.3. WITH_APACHE2 The port requires Apache 2.0. Without this variable, the port will depend on Apache 1.3. This variable is deprecated and should not be used anymore. APXS Full path to the apxs binary. Can be overriden in your port. HTTPD Full path to the httpd binary. Can be overriden in your port. APACHE_VERSION The version of present Apache installation (read-only variable). This variable is only available after inclusion of bsd.port.pre.mk. Possible values: 13, 20, 22. APACHEMODDIR Directory for Apache modules. This variable is automatically expanded in pkg-plist. APACHEINCLUDEDIR Directory for Apache headers. This variable is automatically expanded in pkg-plist. APACHEETCDIR Directory for Apache configuration files. This variable is automatically expanded in pkg-plist.
port Apache 模組時好用的變數 MODULENAME 模組名稱。 預設值為 PORTNAME. 範例: mod_hello SHORTMODNAME 簡化的模組名稱。 自動地由變數 MODULENAME 產生,不過可以覆蓋它。 範例: hello AP_FAST_BUILD 使用 apxs 來編譯及安裝這個模組。 AP_GENPLIST 同樣地,也是自動產生 pkg-plist AP_INC 在編譯時間加入一個目錄到標頭檔搜尋路徑。 AP_LIB 在編譯時間加入一個目錄到函式庫搜尋路徑。 AP_EXTRAS 傳給 apxs 額外的 flags。
Web 應用程式 Web 應用程式應該安裝到 PREFIX/www/appname 。 For your convenience, this path is available both in Makefile and in pkg-plist as WWWDIR, and the path relative to PREFIX is available in Makefile as WWWDIR_REL. The user and group of web server process are available as WWWOWN and WWWGRP, in case you need to change the ownership of some files. The default values of both are www. If you want different values for your port, use WWWOWN?= myuser notation, to allow user to override it easily. 請別過於相依 Apache,除非這些程式有明確需要,而得相依 Apache 。也許有些使用者,會想在其他非 Apache 的 Web 伺服器上執行這些網頁程式。 PHP Variables for ports that use PHP USE_PHP The port requires PHP. The value yes adds a dependency on PHP. The list of required PHP extensions can be specified instead. Example: pcre xml gettext DEFAULT_PHP_VER Selects which major version of PHP will be installed as a dependency when no PHP is installed yet. Default is 4. Possible values: 4, 5 IGNORE_WITH_PHP The port does not work with PHP of the given version. Possible values: 4, 5 USE_PHPIZE The port will be built as a PHP extension. USE_PHPEXT The port will be treated as a PHP extension, including installation and registration in the extension registry. USE_PHP_BUILD Set PHP as a build dependency. WANT_PHP_CLI Want the CLI (command line) version of PHP. WANT_PHP_CGI Want the CGI version of PHP. WANT_PHP_MOD Want the Apache module version of PHP. WANT_PHP_SCR Want the CLI or the CGI version of PHP. WANT_PHP_WEB Want the Apache module or the CGI version of PHP.
PEAR modules Porting PEAR modules is a very simple process. Use the variables FILES, TESTS, DATA, SQLS, SCRIPTFILES, DOCS and EXAMPLES to list the files you want to install. All listed files will be automatically installed into the appropriate locations and added to pkg-plist. Include ${PORTSDIR}/devel/pear/bsd.pear.mk on the last line of the Makefile. Example Makefile for PEAR class PORTNAME= Date PORTVERSION= 1.4.3 CATEGORIES= devel www pear MAINTAINER= example@domain.com COMMENT= PEAR Date and Time Zone Classes BUILD_DEPENDS= ${PEARDIR}/PEAR.php:${PORTSDIR}/devel/pear-PEAR RUN_DEPENDS= ${BUILD_DEPENDS} FILES= Date.php Date/Calc.php Date/Human.php Date/Span.php \ Date/TimeZone.php TESTS= test_calc.php test_date_methods_span.php testunit.php \ testunit_date.php testunit_date_span.php wknotest.txt \ bug674.php bug727_1.php bug727_2.php bug727_3.php \ bug727_4.php bug967.php weeksinmonth_4_monday.txt \ weeksinmonth_4_sunday.txt weeksinmonth_rdm_monday.txt \ weeksinmonth_rdm_sunday.txt DOCS= TODO _DOCSDIR= . .include <bsd.port.pre.mk> .include "${PORTSDIR}/devel/pear/bsd.pear.mk" .include <bsd.port.post.mk>
Using Python The Ports Collection supports parallel installation of multiple Python versions. Ports should make sure to use a correct python interpreter, according to the user-settable PYTHON_VERSION variable. Most prominently, this means replacing the path to python executable in scripts with the value of PYTHON_CMD variable. Ports that install files under PYTHON_SITELIBDIR should use the pyXY- package name prefix, so their package name embeds the version of Python they are installed into. PKGNAMEPREFIX= ${PYTHON_PKGNAMEPREFIX} Most useful variables for ports that use Python USE_PYTHON The port needs Python. Minimal required version can be specified with values such as 2.3+. Version ranges can also be specified, by separating two version numbers with a dash, e.g.: 2.1-2.3 USE_PYDISTUTILS Use Python distutils for configuring, compiling and installing. This is required when the port comes with setup.py. This overrides the do-build and do-install targets and may also override do-configure if GNU_CONFIGURE is not defined. PYTHON_PKGNAMEPREFIX Used as a PKGNAMEPREFIX to distinguish packages for different Python versions. Example: py24- PYTHON_SITELIBDIR Location of the site-packages tree, that contains installation path of Python (usually LOCALBASE). The PYTHON_SITELIBDIR variable can be very useful when installing Python modules. PYTHONPREFIX_SITELIBDIR The PREFIX-clean variant of PYTHON_SITELIBDIR. Always use %%PYTHON_SITELIBDIR%% in pkg-plist when possible. The default value of %%PYTHON_SITELIBDIR%% is lib/python%%PYTHON_VERSION%%/site-packages PYTHON_CMD Python interpreter command line, including version number. PYNUMERIC Dependency line for numeric extension. PYNUMPY Dependency line for the new numeric extension, numpy. (PYNUMERIC is deprecated by upstream vendor). PYXML Dependency line for XML extension (not needed for Python 2.0 and higher as it is also in base distribution). USE_TWISTED Add dependency on twistedCore. The list of required components can be specified as a value of this variable. Example: web lore pair flow USE_ZOPE Add dependency on Zope, a web application platform. Change Python dependency to Python 2.3. Set ZOPEBASEDIR containing a directory with Zope installation.
A complete list of available variables can be found in /usr/ports/Mk/bsd.python.mk.
Using Emacs This section is yet to be written. Using Ruby Useful variables for ports that use Ruby Variable Description USE_RUBY The port requires Ruby. USE_RUBY_EXTCONF The port uses extconf.rb to configure. USE_RUBY_SETUP The port uses setup.rb to configure. RUBY_SETUP Set to the alternative name of setup.rb. Common value is install.rb.
The following table shows the selected variables available to port authors via the ports infrastructure. These variables should be used to install files into their proper locations. Use them in pkg-plist as much as possible. These variables should not be redefined in the port. Selected read-only variables for ports that use Ruby Variable Description Example value RUBY_PKGNAMEPREFIX Used as a PKGNAMEPREFIX to distinguish packages for different Ruby versions. ruby18- RUBY_VERSION Full version of Ruby in the form of x.y.z. 1.8.2 RUBY_SITELIBDIR Architecture independent libraries installation path. /usr/local/lib/ruby/site_ruby/1.8 RUBY_SITEARCHLIBDIR Architecture dependent libraries installation path. /usr/local/lib/ruby/site_ruby/1.8/amd64-freebsd6 RUBY_MODDOCDIR Module documentation installation path. /usr/local/share/doc/ruby18/patsy RUBY_MODEXAMPLESDIR Module examples installation path. /usr/local/share/examples/ruby18/patsy
A complete list of available variables can be found in /usr/ports/Mk/bsd.ruby.mk.
Using SDL The USE_SDL variable is used to autoconfigure the dependencies for ports which use an SDL based library like devel/sdl12 and x11-toolkits/sdl_gui. The following SDL libraries are recognized at the moment: sdl: devel/sdl12 gfx: graphics/sdl_gfx gui: x11-toolkits/sdl_gui image: graphics/sdl_image ldbad: devel/sdl_ldbad mixer: audio/sdl_mixer mm: devel/sdlmm net: net/sdl_net sound: audio/sdl_sound ttf: graphics/sdl_ttf Therefore, if a port has a dependency on net/sdl_net and audio/sdl_mixer, the syntax will be: USE_SDL= net mixer The dependency devel/sdl12, which is required by net/sdl_net and audio/sdl_mixer, is automatically added as well. If you use USE_SDL, it will automatically: Add a dependency on sdl12-config to BUILD_DEPENDS Add the variable SDL_CONFIG to CONFIGURE_ENV Add the dependencies of the selected libraries to the LIB_DEPENDS To check whether an SDL library is available, you can do it with the WANT_SDL variable: WANT_SDL=yes .include <bsd.port.pre.mk> .if ${HAVE_SDL:Mmixer}!="" USE_SDL+= mixer .endif .include <bsd.port.post.mk> Using <application>wxWidgets</application> This section describes the status of the wxWidgets libraries in the ports tree and its integration with the ports system. Introduction There are many versions of the wxWidgets libraries which conflict between them (install files under the same name). In the ports tree this problem has been solved by installing each version under a different name using version number suffixes. The obvious disadvantage of this is that each application has to be modified to find the expected version. Fortunately, most of the applications call the wx-config script to determine the necessary compiler and linker flags. The script is named differently for every available version. Majority of applications respect an environment variable, or accept a configure argument, to specify which wx-config script to call. Otherwise they have to be patched. Version selection To make your port use a specific version of wxWidgets there are two variables available for defining (if only one is defined the other will be set to a default value): Variables to select <application>wxWidgets</application> versions Variable Description Default value USE_WX List of versions the port can use All available versions USE_WX_NOT List of versions the port can not use None
The following is a list of available wxWidgets versions and the corresponding ports in the tree: Available <application>wxWidgets</application> versions Version Port 2.4 x11-toolkits/wxgtk24 2.6 x11-toolkits/wxgtk26 2.8 x11-toolkits/wxgtk28
The versions starting from 2.5 also come in Unicode version and are installed by a slave port named like the normal one plus a -unicode suffix, but this can be handled with variables (see ). The variables in can be set to one or more of the following combinations separated by spaces: <application>wxWidgets</application> version specifications Description Example Single version 2.4 Ascending range 2.4+ Descending range 2.6- Full range (must be ascending) 2.4-2.6
There are also some variables to select the preferred versions from the available ones. They can be set to a list of versions, the first ones will have higher priority. Variables to select preferred <application>wxWidgets</application> versions Name Designed for WANT_WX_VER the port WITH_WX_VER the user
Component selection There are other applications that, while not being wxWidgets libraries, are related to them. These applications can be specified in the WX_COMPS variable. The following components are available: Available <application>wxWidgets</application> components Name Description Version restriction wx main library none contrib contributed libraries none python wxPython (Python bindings) 2.4-2.6 mozilla wxMozilla 2.4 svg wxSVG 2.6
The dependency type can be selected for each component by adding a suffix separated by a semicolon. If not present then a default type will be used (see ). The following types are available: Available <application>wxWidgets</application> dependency types Name Description build Component is required for building, equivalent to BUILD_DEPENDS run Component is required for running, equivalent to RUN_DEPENDS lib Component is required for building and running, equivalent to LIB_DEPENDS
The default values for the components are detailed in the following table: Default <application>wxWidgets</application> dependency types Component Dependency type wx lib contrib lib python run mozilla lib svg lib
Selecting <application>wxWidgets</application> components The following fragment corresponds to a port which uses wxWidgets version 2.4 and its contributed libraries. USE_WX= 2.4 WX_COMPS= wx contrib
Unicode The wxWidgets library supports Unicode since version 2.5. In the ports tree both versions are available and can be selected with the following variables: Variables to select Unicode in <application>wxWidgets</application> versions Variable Description Designed for WX_UNICODE The port works only with the Unicode version the port WANT_UNICODE The port works with both versions but prefers the Unicode one the port WITH_UNICODE The port will use the Unicode version the user WITHOUT_UNICODE The port will use the normal version if supported (when WX_UNICODE is not defined) the user
Do not use WX_UNICODE for ports that can use both Unicode and normal versions. If you want the port to use Unicode by default define WANT_UNICODE instead.
Detecting installed versions To detect an installed version you have to define WANT_WX. If you do not set it to a specific version then the components will have a version suffix. The HAVE_WX variable will be filled after detection. Detecting installed <application>wxWidgets</application> versions and components The following fragment can be used in a port that uses wxWidgets if it is installed, or an option is selected. WANT_WX= yes .include <bsd.port.pre.mk> .if defined(WITH_WX) || ${HAVE_WX:Mwx-2.4} != "" USE_WX= 2.4 CONFIGURE_ARGS+=--enable-wx .endif The following fragment can be used in a port that enables wxPython support if it is installed or if an option is selected, in addition to wxWidgets, both version 2.6. USE_WX= 2.6 WX_COMPS= wx WANT_WX= 2.6 .include <bsd.port.pre.mk> .if defined(WITH_WXPYTHON) || ${HAVE_WX:Mpython} != "" WX_COMPS+= python CONFIGURE_ARGS+=--enable-wxpython .endif Defined variables The following variables are available in the port (after defining one from ). Variables defined for ports that use <application>wxWidgets</application> Name Description WX_CONFIG The path to the wxWidgets wx-config script (with different name) WXRC_CMD The path to the wxWidgets wxrc program (with different name) WX_VERSION The wxWidgets version that is going to be used (e.g., 2.6) WX_UNICODE If not defined but Unicode is going to be used then it will be defined
Processing in <filename>bsd.port.pre.mk</filename> If you need to use the variables for running commands right after including bsd.port.pre.mk you need to define WX_PREMK. If you define WX_PREMK, then the version, dependencies, components and defined variables will not change if you modify the wxWidgets port variables after including bsd.port.pre.mk. Using <application>wxWidgets</application> variables in commands The following fragment illustrates the use of WX_PREMK by running the wx-config script to obtain the full version string, assign it to a variable and pass it to the program. USE_WX= 2.4 WX_PREMK= yes .include <bsd.port.pre.mk> .if exists(${WX_CONFIG}) VER_STR!= ${WX_CONFIG} --release PLIST_SUB+= VERSION="${VER_STR}" .endif The wxWidgets variables can be safely used in commands when they are inside targets without the need of WX_PREMK. Additional <command>configure</command> arguments Some GNU configure scripts can not find wxWidgets with just the WX_CONFIG environment variable set, requiring additional arguments. The WX_CONF_ARGS variable can be used for provide them. Legal values for <makevar>WX_CONF_ARGS</makevar> Possible value Resulting argument absolute --with-wx-config=${WX_CONFIG} relative --with-wx=${X11BASE} --with-wx-config=${WX_CONFIG:T}
Using <application>Lua</application> This section describes the status of the Lua libraries in the ports tree and its integration with the ports system. Introduction There are many versions of the Lua libraries and corresponding interpreters, which conflict between them (install files under the same name). In the ports tree this problem has been solved by installing each version under a different name using version number suffixes. The obvious disadvantage of this is that each application has to be modified to find the expected version. But it can be solved by adding some additional flags to the compiler and linker. Version selection To make your port use a specific version of Lua there are two variables available for defining (if only one is defined the other will be set to a default value): Variables to select <application>Lua</application> versions Variable Description Default value USE_LUA List of versions the port can use All available versions USE_LUA_NOT List of versions the port can not use None
The following is a list of available Lua versions and the corresponding ports in the tree: Available <application>Lua</application> versions Version Port 4.0 lang/lua4 5.0 lang/lua50 5.1 lang/lua
The variables in can be set to one or more of the following combinations separated by spaces: <application>Lua</application> version specifications Description Example Single version 4.0 Ascending range 5.0+ Descending range 5.0- Full range (must be ascending) 5.0-5.1
There are also some variables to select the preferred versions from the available ones. They can be set to a list of versions, the first ones will have higher priority. Variables to select preferred <application>Lua</application> versions Name Designed for WANT_LUA_VER the port WITH_LUA_VER the user
Selecting the <application>Lua</application> version The following fragment is from a port which can use Lua version 5.0 or 5.1, and uses 5.0 by default. It can be overriden by the user using WITH_LUA_VER. USE_LUA= 5.0-5.1 WANT_LUA_VER= 5.0
Component selection There are other applications that, while not being Lua libraries, are related to them. These applications can be specified in the LUA_COMPS variable. The following components are available: Available <application>Lua</application> components Name Description Version restriction lua main library none tolua Library for accesing C/C++ code 4.0-5.0 ruby Ruby bindings 4.0-5.0
There are more components but they are modules for the interpreter, not used by applications (only by other modules). The dependency type can be selected for each component by adding a suffix separated by a semicolon. If not present then a default type will be used (see ). The following types are available: Available <application>Lua</application> dependency types Name Description build Component is required for building, equivalent to BUILD_DEPENDS run Component is required for running, equivalent to RUN_DEPENDS lib Component is required for building and running, equivalent to LIB_DEPENDS
The default values for the components are detailed in the following table: Default <application>Lua</application> dependency types Component Dependency type lua lib for 4.0-5.0 (shared) and build for 5.1 (static) tolua build (static) ruby lib (shared)
Selecting <application>Lua</application> components The following fragment corresponds to a port which uses Lua version 4.0 and its Ruby bindings. USE_LUA= 4.0 LUA_COMPS= lua ruby
Detecting installed versions To detect an installed version you have to define WANT_LUA. If you do not set it to a specific version then the components will have a version suffix. The HAVE_LUA variable will be filled after detection. Detecting installed <application>Lua</application> versions and components The following fragment can be used in a port that uses Lua if it is installed, or an option is selected. WANT_LUA= yes .include <bsd.port.pre.mk> .if defined(WITH_LUA5) || ${HAVE_LUA:Mlua-5.[01]} != "" USE_LUA= 5.0-5.1 CONFIGURE_ARGS+=--enable-lua5 .endif The following fragment can be used in a port that enables tolua support if it is installed or if an option is selected, in addition to Lua, both version 4.0. USE_LUA= 4.0 LUA_COMPS= lua WANT_LUA= 4.0 .include <bsd.port.pre.mk> .if defined(WITH_TOLUA) || ${HAVE_LUA:Mtolua} != "" LUA_COMPS+= tolua CONFIGURE_ARGS+=--enable-tolua .endif Defined variables The following variables are available in the port (after defining one from ). Variables defined for ports that use <application>Lua</application> Name Description LUA_VER The Lua version that is going to be used (e.g., 5.1) LUA_VER_SH The Lua shared library major version (e.g., 1) LUA_VER_STR The Lua version without the dots (e.g., 51) LUA_PREFIX The prefix where Lua (and components) is installed LUA_SUBDIR The directory under ${PREFIX}/bin, ${PREFIX}/share and ${PREFIX}/lib where Lua is installed LUA_INCDIR The directory where Lua and tolua header files are installed LUA_LIBDIR The directory where Lua and tolua libraries are installed LUA_MODLIBDIR The directory where Lua module libraries (.so) are installed LUA_MODSHAREDIR The directory where Lua modules (.lua) are installed LUA_PKGNAMEPREFIX The package name prefix used by Lua modules LUA_CMD The path to the Lua interpreter LUAC_CMD The path to the Lua compiler TOLUA_CMD The path to the tolua program
Telling the port where to find <application>Lua</application> The following fragment shows how to tell a port that uses a configure script where the Lua header files and libraries are. USE_LUA= 4.0 GNU_CONFIGURE= yes CONFIGURE_ENV= CPPFLAGS="-I${LUA_INCDIR}" LDFLAGS="-L${LUA_LIBDIR}"
Processing in <filename>bsd.port.pre.mk</filename> If you need to use the variables for running commands right after including bsd.port.pre.mk you need to define LUA_PREMK. If you define LUA_PREMK, then the version, dependencies, components and defined variables will not change if you modify the Lua port variables after including bsd.port.pre.mk. Using <application>Lua</application> variables in commands The following fragment illustrates the use of LUA_PREMK by running the Lua interpreter to obtain the full version string, assign it to a variable and pass it to the program. USE_LUA= 5.0 LUA_PREMK= yes .include <bsd.port.pre.mk> .if exists(${LUA_CMD}) VER_STR!= ${LUA_CMD} -v CFLAGS+= -DLUA_VERSION_STRING="${VER_STR}" .endif The Lua variables can be safely used in commands when they are inside targets without the need of LUA_PREMK.
Using Xfce The USE_XFCE variable is used to autoconfigure the dependencies for ports which use an Xfce based library or application like x11-toolkits/libxfce4gui and x11-wm/xfce4-panel. The following Xfce libraries and applications are recognized at the moment: libexo: x11/libexo libgui: x11-toolkits/libxfce4gui libutil: x11/libxfce4util libmcs: x11/libxfce4mcs mcsmanager: sysutils/xfce4-mcs-manager panel: x11-wm/xfce4-panel thunar: x11-fm/thunar wm: x11-wm/xfce4-wm xfdev: dev/xfce4-dev-tools The following additional parameters are recognized: configenv: Use this if your port requires a special modified CONFIGURE_ENV to find it's required libraries. -I${LOCALBASE}/include -L${LOCALBASE}/lib gets added to CPPFLAGS to CONFIGURE_ENV. Therefore, if a port has a dependency on sysutils/xfce4-mcs-manager and requires the special CPPFLAGS in its configure environment, the syntax will be: USE_XFCE= mcsmanager configenv Starting and stopping services (rc scripts) rc.d scripts are used to start services on system startup, and to give administrators a standard way of stopping, starting and restarting the service. Ports integrate into the system rc.d framework. Details on its usage can be found in the rc.d Handbook chapter. Detailed explanation of available commands is provided in &man.rc.8; and &man.rc.subr.8;. Finally, there is an article on practical aspects of rc.d scripting. One or more rc scripts can be installed: USE_RC_SUBR= doormand Scripts must be placed in the files subdirectory and a .in suffix must be added to their filename. The only difference from a base system rc.d script is that the . /etc/rc.subr line must be replaced with the . %%RC_SUBR%%, because older versions of &os; do not have an /etc/rc.subr file. Standard SUB_LIST expansions are used too. Use of the %%PREFIX%%, %%LOCALBASE%%, and %%X11BASE%% expansions is strongly encouraged as well. More on SUB_LIST in the relevant section. Prior to &os; 6.1-RELEASE, integration with &man.rcorder.8; is available by using USE_RCORDER instead of USE_RC_SUBR. However, use of this method is deprecated. As of &os; 6.1-RELEASE, local rc.d scripts (including those installed by ports) are included in the overall &man.rcorder.8; of the base system. Example simple rc.d script: #!/bin/sh # PROVIDE: doormand # REQUIRE: LOGIN # # Add the following lines to /etc/rc.conf.local or /etc/rc.conf # to enable this service: # # doormand_enable (bool): Set to NO by default. # Set it to YES to enable doormand. # doormand_config (path): Set to %%PREFIX%%/etc/doormand/doormand.cf # by default. # . %%RC_SUBR%% name="doormand" rcvar=${name}_enable command=%%PREFIX%%/sbin/${name} pidfile=/var/run/${name}.pid load_rc_config $name : ${doormand_enable="NO"} : ${doormand_config="%%PREFIX%%/etc/doormand/doormand.cf"} command_args="-p $pidfile -f $doormand_config" run_rc_command "$1" The "=" style of default variable assignment is preferable to the ":=" style here, since the former sets a default value only if the variable is unset, and the latter sets one if the variable is unset or null. A user might very well include something like doormand_flags="" in their rc.conf.local file, and a variable substitution using ":=" would inappropriately override the user's intention. The suffix of the rc script is provided in RC_SUBR_SUFFIX for further use in the port's Makefile. Current versions of &os; do not add any suffix to the script name, but older versions used to add .sh suffix. No new scripts should be added with the .sh suffix. At some point there will be a mass repocopy of all the scripts that still have that suffix. Stopping services at deinstall It is possible to have a service stopped automatically as part of the deinstall routine. We advise using this feature only when it's absolutely necessary to stop a service before it's files go away. Usually, it's up to the administrator's discretion to decide, whether to stop the service on deinstall or not. Also note this affects upgrades, too. Line like this goes to the pkg-plist: @stopdaemon doormand The argument must match the content of USE_RC_SUBR variable.
Advanced <filename>pkg-plist</filename> practices Changing <filename>pkg-plist</filename> based on make variables Some ports, particularly the p5- ports, need to change their pkg-plist depending on what options they are configured with (or version of perl, in the case of p5- ports). To make this easy, any instances in the pkg-plist of %%OSREL%%, %%PERL_VER%%, and %%PERL_VERSION%% will be substituted for appropriately. The value of %%OSREL%% is the numeric revision of the operating system (e.g., 4.9). %%PERL_VERSION%% is the full version number of perl (e.g., 5.00502) and %%PERL_VER%% is the perl version number minus the patchlevel (e.g., 5.005). Several other %%VARS%% related to port's documentation files are described in the relevant section. If you need to make other substitutions, you can set the PLIST_SUB variable with a list of VAR=VALUE pairs and instances of %%VAR%% will be substituted with VALUE in the pkg-plist. For instance, if you have a port that installs many files in a version-specific subdirectory, you can put something like OCTAVE_VERSION= 2.0.13 PLIST_SUB= OCTAVE_VERSION=${OCTAVE_VERSION} in the Makefile and use %%OCTAVE_VERSION%% wherever the version shows up in pkg-plist. That way, when you upgrade the port, you will not have to change dozens (or in some cases, hundreds) of lines in the pkg-plist. This substitution (as well as addition of any manual pages) will be done between the pre-install and do-install targets, by reading from PLIST and writing to TMPPLIST (default: WRKDIR/.PLIST.mktmp). So if your port builds PLIST on the fly, do so in or before pre-install. Also, if your port needs to edit the resulting file, do so in post-install to a file named TMPPLIST. Another possibility to modify port's packing list is based on setting the variables PLIST_FILES and PLIST_DIRS. The value of each variable is regarded as a list of pathnames to write to TMPPLIST along with PLIST contents. Names listed in PLIST_FILES and PLIST_DIRS are subject to %%VAR%% substitution, as described above. Except for that, names from PLIST_FILES will appear in the final packing list unchanged, while @dirrm will be prepended to names from PLIST_DIRS. To take effect, PLIST_FILES and PLIST_DIRS must be set before TMPPLIST is written, i.e. in pre-install or earlier. Empty directories Cleaning up empty directories Do make your ports remove empty directories when they are de-installed. This is usually accomplished by adding @dirrm lines for all directories that are specifically created by the port. You need to delete subdirectories before you can delete parent directories. : lib/X11/oneko/pixmaps/cat.xpm lib/X11/oneko/sounds/cat.au : @dirrm lib/X11/oneko/pixmaps @dirrm lib/X11/oneko/sounds @dirrm lib/X11/oneko However, sometimes @dirrm will give you errors because other ports share the same directory. You can use @dirrmtry to remove only empty directories without warning. @dirrmtry share/doc/gimp This will neither print any error messages nor cause &man.pkg.delete.1; to exit abnormally even if ${PREFIX}/share/doc/gimp is not empty due to other ports installing some files in there. Creating empty directories Empty directories created during port installation need special attention. They will not get created when installing the package, because packages only store the files, and &man.pkg.add.1; creates directories for them as needed. To make sure the empty directory is created when installing the package, add this line to pkg-plist above the corresponding @dirrm line: @exec mkdir -p %D/share/foo/templates Configuration files If your port requires some configuration files in PREFIX/etc, do not just install them and list them in pkg-plist. That will cause &man.pkg.delete.1; to delete files carefully edited by the user and a new installation to wipe them out. Instead, install sample files with a suffix (filename.sample will work well). Copy the sample file as the real configuration file, if it does not exist. On deinstall, delete the configuration file, but only if it was not modified by the user. You need to handle this both in the port Makefile, and in the pkg-plist (for installation from the package). Example of the Makefile part: post-install: @if [ ! -f ${PREFIX}/etc/orbit.conf ]; then \ ${CP} -p ${PREFIX}/etc/orbit.conf.sample ${PREFIX}/etc/orbit.conf ; \ fi Example of the pkg-plist part: @unexec if cmp -s %D/etc/orbit.conf.sample %D/etc/orbit.conf; then rm -f %D/etc/orbit.conf; fi etc/orbit.conf.sample @exec if [ ! -f %D/etc/orbit.conf ] ; then cp -p %D/%F %B/orbit.conf; fi Alternatively, print out a message pointing out that the user has to copy and edit the file before the software can be made to work. Dynamic vs. static package list A static package list is a package list which is available in the Ports Collection either as a pkg-plist file (with or without variable substitution), or embedded into the Makefile via PLIST_FILES and PLIST_DIRS. Even if the contents are auto-generated by a tool or a target in the Makefile before the inclusion into the Ports Collection by a committer, this is still considered a static list, since it is possible to examine it without having to download or compile the distfile. A dynamic package list is a package list which is generated at the time the port is compiled based upon the files and directories which are installed. It is not possible to examine it before the source code of the ported application is downloaded and compiled, or after running a make clean. While the use of dynamic package lists is not forbidden, maintainers should use static package lists wherever possible, as it enables users to &man.grep.1; through available ports to discover, for example, which port installs a certain file. Dynamic lists should be primarily used for complex ports where the package list changes drastically based upon optional features of the port (and thus maintaining a static package list is infeasible), or ports which change the package list based upon the version of dependent software used (e.g. ports which generate docs with Javadoc). Maintainers who prefer dynamic package lists are encouraged to add a new target to their port which generates the pkg-plist file so that users may examine the contents. 自動產生 package list 首先,先確認您的 port 除了 pkg-plist 尚未搞定之外,其他都完成了。 接著,建立臨時目錄以供該 port 安裝,並且把所有相依套件都裝好 。 &prompt.root; mkdir /var/tmp/$(make -V PORTNAME) &prompt.root; mtree -U -f $(make -V MTREE_FILE) -d -e -p /var/tmp/$(make -V PORTNAME) &prompt.root; make depends PREFIX=/var/tmp/$(make -V PORTNAME) 把這目錄架構存到新檔案。 &prompt.root; (cd /var/tmp/$(make -V PORTNAME) && find -d * -type d) | sort > OLD-DIRS 新增空的 pkg-plist 檔案: &prompt.root; :>pkg-plist 若該 port 有遵循 PREFIX(也應該要遵循), 接著就可以安裝該 port 並產生檔案清單。 &prompt.root; make install PREFIX=/var/tmp/$(make -V PORTNAME) &prompt.root; (cd /var/tmp/$(make -V PORTNAME) && find -d * \! -type d) | sort > pkg-plist 這時要記得把新建的目錄,也加到檔案清單內。 &prompt.root; (cd /var/tmp/$(make -V PORTNAME) && find -d * -type d) | sort | comm -13 OLD-DIRS - | sort -r | sed -e 's#^#@dirrm #' >> pkg-plist - Finally, you need to tidy up the packing list by hand; it is not - all automated. Manual pages should be listed in - the port's Makefile under - MANn, and not in the - package list. User configuration files should be removed, or - installed as - filename.sample. + 最後,您應該手動整理檔案清單(這不是全部自動化處理的)。Man page 則應該利用 MANn 的方式 + 寫在 port 的 Makefile 而不是寫在檔案清單中。 + 使用者設定檔應該移除,或更名為filename.sample。 The info/dir file should not be listed and appropriate install-info lines should be added as noted in the info files section. Any libraries installed by the port should be listed as specified in the shared libraries section. Alternatively, use the plist script in /usr/ports/Tools/scripts/ to build the package list automatically. The first step is the same as above: take the first three lines, that is, mkdir, mtree and make depends. Then build and install the port: &prompt.root; make install PREFIX=/var/tmp/port-name And let plist create the pkg-plist file: &prompt.root; /usr/ports/Tools/scripts/plist -Md -m /etc/mtree/BSD.port-type.dist /var/tmp/port-name > pkg-plist The packing list still has to be tidied up by hand as stated above. The <filename>pkg-<replaceable>*</replaceable></filename> files There are some tricks we have not mentioned yet about the pkg-* files that come in handy sometimes. <filename>pkg-message</filename> If you need to display a message to the installer, you may place the message in pkg-message. This capability is often useful to display additional installation steps to be taken after a &man.pkg.add.1; or to display licensing information. When some lines about the build-time knobs or warnings have to be displayed, use ECHO_MSG. The pkg-message file is only for post-installation steps. Likewise, the distinction between ECHO_MSG and ECHO_CMD should be kept in mind. The former is for printing informational text to the screen, while the latter is for command pipelining. A good example for both can be found in shells/bash2/Makefile: update-etc-shells: @${ECHO_MSG} "updating /etc/shells" @${CP} /etc/shells /etc/shells.bak @( ${GREP} -v ${PREFIX}/bin/bash /etc/shells.bak; \ ${ECHO_CMD} ${PREFIX}/bin/bash) >/etc/shells @${RM} /etc/shells.bak The pkg-message file does not need to be added to pkg-plist. Also, it will not get automatically printed if the user is using the port, not the package, so you should probably display it from the post-install target yourself. <filename>pkg-install</filename> If your port needs to execute commands when the binary package is installed with &man.pkg.add.1; you can do this via the pkg-install script. This script will automatically be added to the package, and will be run twice by &man.pkg.add.1;: the first time as ${SH} pkg-install ${PKGNAME} PRE-INSTALL and the second time as ${SH} pkg-install ${PKGNAME} POST-INSTALL. $2 can be tested to determine which mode the script is being run in. The PKG_PREFIX environmental variable will be set to the package installation directory. See &man.pkg.add.1; for additional information. This script is not run automatically if you install the port with make install. If you are depending on it being run, you will have to explicitly call it from your port's Makefile, with a line like PKG_PREFIX=${PREFIX} ${SH} ${PKGINSTALL} ${PKGNAME} PRE-INSTALL. <filename>pkg-deinstall</filename> This script executes when a package is removed. This script will be run twice by &man.pkg.delete.1;. The first time as ${SH} pkg-deinstall ${PKGNAME} DEINSTALL and the second time as ${SH} pkg-deinstall ${PKGNAME} POST-DEINSTALL. <filename>pkg-req</filename> If your port needs to determine if it should install or not, you can create a pkg-req requirements script. It will be invoked automatically at installation/de-installation time to determine whether or not installation/de-installation should proceed. The script will be run at installation time by &man.pkg.add.1; as pkg-req ${PKGNAME} INSTALL. At de-installation time it will be run by &man.pkg.delete.1; as pkg-req ${PKGNAME} DEINSTALL. Changing the names of <filename>pkg-<replaceable>*</replaceable></filename> files All the names of pkg-* files are defined using variables so you can change them in your Makefile if need be. This is especially useful when you are sharing the same pkg-* files among several ports or have to write to one of the above files (see writing to places other than WRKDIR for why it is a bad idea to write directly into the pkg-* subdirectory). Here is a list of variable names and their default values. (PKGDIR defaults to ${MASTERDIR}.) Variable Default value DESCR ${PKGDIR}/pkg-descr PLIST ${PKGDIR}/pkg-plist PKGINSTALL ${PKGDIR}/pkg-install PKGDEINSTALL ${PKGDIR}/pkg-deinstall PKGREQ ${PKGDIR}/pkg-req PKGMESSAGE ${PKGDIR}/pkg-message Please change these variables rather than overriding PKG_ARGS. If you change PKG_ARGS, those files will not correctly be installed in /var/db/pkg upon install from a port. Making use of <makevar>SUB_FILES</makevar> and <makevar>SUB_LIST</makevar> The SUB_FILES and SUB_LIST variables are useful for dynamic values in port files, such as the installation PREFIX in pkg-message. The SUB_FILES variable specifies a list of files to be automatically modified. Each file in the SUB_FILES list must have a corresponding file.in present in FILESDIR. A modified version will be created in WRKDIR. Files defined as a value of USE_RC_SUBR (or the deprecated USE_RCORDER) are automatically added to the SUB_FILES. For the files pkg-message, pkg-install, pkg-deinstall and pkg-reg, the corresponding Makefile variable is automatically set to point to the processed version. The SUB_LIST variable is a list of VAR=VALUE pairs. For each pair %%VAR%% will get replaced with VALUE in each file listed in SUB_FILES. Several common pairs are automatically defined: PREFIX, LOCALBASE, X11BASE, DATADIR, DOCSDIR, EXAMPLESDIR. Any line beginning with @comment will be deleted from resulting files after a variable substitution. The following example will replace %%ARCH%% with the system architecture in a pkg-message: SUB_FILES= pkg-message SUB_LIST= ARCH=${ARCH} Note that for this example, the pkg-message.in file must exist in FILESDIR. Example of a good pkg-message.in: Now it is time to configure this package. Copy %%PREFIX%%/share/examples/putsy/%%ARCH%%.conf into your home directory as .putsy.conf and edit it. Testing your port Running <command>make describe</command> Several of the &os; port maintenance tools, such as &man.portupgrade.1;, rely on a database called /usr/ports/INDEX which keeps track of such items as port dependencies. INDEX is created by the top-level ports/Makefile via make index, which descends into each port subdirectory and executes make describe there. Thus, if make describe fails in any port, no one can generate INDEX, and many people will quickly become unhappy. It is important to be able to generate this file no matter what options are present in make.conf, so please avoid doing things such as using .error statements when (for instance) a dependency is not satisfied. (See .) If make describe produces a string rather than an error message, you are probably safe. See bsd.port.mk for the meaning of the string produced. Also note that running a recent version of portlint (as specified in the next section) will cause make describe to be run automatically. Portlint Do check your work with portlint before you submit or commit it. portlint warns you about many common errors, both functional and stylistic. For a new (or repocopied) port, portlint -A is the most thorough; for an existing port, portlint -C is sufficient. Since portlint uses heuristics to try to figure out errors, it can produce false positive warnings. In addition, occasionally something that is flagged as a problem really cannot be done in any other way due to limitations in the ports framework. When in doubt, the best thing to do is ask on &a.ports;. Port Tools The ports-mgmt/porttools program is part of the Ports Collection. port is the front-end script, which can help you simplify the testing job. Whenever you want to test a new port or update an existing one, you can use port test to test your port, including the portlint checking. This command also detects and lists any files that are not listed in pkg-plist. See the following example: &prompt.root; port test /usr/ports/net/csup <makevar>PREFIX</makevar> 以及 <makevar>DESTDIR</makevar> PREFIX 變數會決定該 port 所會安裝的位置, 通常是 /usr/local/opt 。 使用者可以藉由設定 PREFIX 決定要裝在哪邊, 而你所維護的 port 必須遵循該規則。 若使用者有設定 DESTDIR 變數, 那麼它會採用所設定的環境,通常可能是 jail 環境或者是並非掛載於 / 上的系統。 通常 port 會裝在 DESTDIR/PREFIX 底下, 並且會紀錄在 DESTDIR/var/db/pkg 內的套件資料庫。 由於事實上 DESTDIR 會由 ports 架構透過 &man.chroot.8; 來自動處理,所以您不需去作相關修改或刻意維護 DESTDIR 相容的 ports。 PREFIX 變數若無特別設定,會與 LOCALBASE 相同 (預設為 /usr/local)。 若有設定 USE_X_PREFIXUSE_IMAKE, 那麼 PREFIX 則為 X11BASE ( 為了相容的理由,預設仍為 /usr/X11R6, 但不久後會徹底移除)。 若有設定 USE_LINUX_PREFIX, 那麼 PREFIX 則為 LINUXBASE ( 預設為 /compat/linux)。 Avoiding the hard-coding of /usr/local or /usr/X11R6 anywhere in the source will make the port much more flexible and able to cater to the needs of other sites. For X ports that use imake, this is automatic; otherwise, this can often be done by simply replacing the occurrences of /usr/local (or /usr/X11R6 for X ports that do not use imake) in the various Makefiles in the port to read ${PREFIX}, as this variable is automatically passed down to every stage of the build and install processes. Make sure your application is not installing things in /usr/local instead of PREFIX. A quick test for this is to do this is: &prompt.root; make clean; make package PREFIX=/var/tmp/port-name If anything is installed outside of PREFIX, the package creation process will complain that it cannot find the files. This does not test for the existence of internal references, or correct use of LOCALBASE for references to files from other ports. Testing the installation in /var/tmp/port-name to do that while you have it installed would do that. Do not set USE_X_PREFIX unless your port truly requires it (i.e., it needs to reference files in X11BASE). The variable PREFIX can be reassigned in your Makefile or in the user's environment. However, it is strongly discouraged for individual ports to set this variable explicitly in the Makefiles. Also, refer to programs/files from other ports with the variables mentioned above, not explicit pathnames. For instance, if your port requires a macro PAGER to be the full pathname of less, use the compiler flag: -DPAGER=\"${LOCALBASE}/bin/less\" instead of -DPAGER=\"/usr/local/bin/less\". This way it will have a better chance of working if the system administrator has moved the whole /usr/local tree somewhere else. Tinderbox If you're an avid ports contributor, you might want to take a look at Tinderbox. It is a powerful system for building and testing ports based on the scripts used on Pointyhat. You can install Tinderbox using ports-mgmt/tinderbox port. Be sure to read supplied documentation since the configuration is not trivial. Visit the Tinderbox website for more details. Upgrading When you notice that a port is out of date compared to the latest version from the original authors, you should first ensure that you have the latest port. You can find them in the ports/ports-current directory of the &os; FTP mirror sites. However, if you are working with more than a few ports, you will probably find it easier to use CVSup to keep your whole ports collection up-to-date, as described in the Handbook. This will have the added benefit of tracking all the ports' dependencies. The next step is to see if there is an update already pending. To do this, you have two options. There is a searchable interface to the FreeBSD Problem Report (PR) database (also known as GNATS). Select ports in the dropdown, and enter the name of the port. However, sometimes people forget to put the name of the port into the Synopsis field in an unambiguous fashion. In that case, you can try the FreeBSD Ports Monitoring System (also known as portsmon). This system attempts to classify port PRs by portname. To search for PRs about a particular port, use the Overview of One Port. If there is no pending PR, the next step is to send an email to the port's maintainer, as shown by make maintainer. That person may already be working on an upgrade, or have a reason to not upgrade the port right now (because of, for example, stability problems of the new version); you would not want to duplicate their work. Note that unmaintained ports are listed with a maintainer of ports@FreeBSD.org, which is just the general ports mailing list, so sending mail there probably will not help in this case. If the maintainer asks you to do the upgrade or there is no maintainer, then you have a chance to help out &os; by preparing the update yourself! Please make the changes and save the result of the recursive diff output of the new and old ports directories (e.g., if your modified port directory is called superedit and the original is in our tree as superedit.bak, then save the result of diff -ruN superedit.bak superedit). Either unified or context diff is fine, but port committers generally prefer unified diffs. Note the use of the -N option—this is the accepted way to force diff to properly deal with the case of new files being added or old files being deleted. Before sending us the diff, please examine the output to make sure all the changes make sense. To simplify common operations with patch files, you can use /usr/ports/Tools/scripts/patchtool.py. Before using it, please read /usr/ports/Tools/scripts/README.patchtool. If the port is unmaintained, and you are actively using it yourself, please consider volunteering to become its maintainer. &os; has over 2000 ports without maintainers, and this is an area where more volunteers are always needed. (For a detailed description of the responsibilities of maintainers, refer to the section in the Developer's Handbook.) 最好的方式是使用 &man.send-pr.1; 並附上 diff 一併回報(類別請選 ports)。 若你是該 port 的維護者,請記得在 synopsis 那行的開頭註明 [maintainer update],並且在 PR 的 Class 分類填上 maintainer-update。 否則,該 PR 的 Class 處就是填 change-request。 Please mention any added or deleted files in the message, as they have to be explicitly specified to &man.cvs.1; when doing a commit. If the diff is more than about 20KB, please compress and uuencode it; otherwise, just include it in the PR as is. Before you &man.send-pr.1;, you should review the Writing the problem report section in the Problem Reports article; it contains far more information about how to write useful problem reports. If your upgrade is motivated by security concerns or a serious fault in the currently committed port, please notify the &a.portmgr; to request immediate rebuilding and redistribution of your port's package. Unsuspecting users of &man.pkg.add.1; will otherwise continue to install the old version via pkg_add -r for several weeks. Once again, please use &man.diff.1; and not &man.shar.1; to send updates to existing ports! Now that you have done all that, you will want to read about how to keep up-to-date in . Ports security Why security is so important Bugs are occasionally introduced to the software. Arguably, the most dangerous of them are those opening security vulnerabilities. From the technical viewpoint, such vulnerabilities are to be closed by exterminating the bugs that caused them. However, the policies for handling mere bugs and security vulnerabilities are very different. A typical small bug affects only those users who have enabled some combination of options triggering the bug. The developer will eventually release a patch followed by a new version of the software, free of the bug, but the majority of users will not take the trouble of upgrading immediately because the bug has never vexed them. A critical bug that may cause data loss represents a graver issue. Nevertheless, prudent users know that a lot of possible accidents, besides software bugs, are likely to lead to data loss, and so they make backups of important data; in addition, a critical bug will be discovered really soon. A security vulnerability is all different. First, it may remain unnoticed for years because often it does not cause software malfunction. Second, a malicious party can use it to gain unauthorized access to a vulnerable system, to destroy or alter sensitive data; and in the worst case the user will not even notice the harm caused. Third, exposing a vulnerable system often assists attackers to break into other systems that could not be compromised otherwise. Therefore closing a vulnerability alone is not enough: the audience should be notified of it in most clear and comprehensive manner, which will allow to evaluate the danger and take appropriate actions. Fixing security vulnerabilities While on the subject of ports and packages, a security vulnerability may initially appear in the original distribution or in the port files. In the former case, the original software developer is likely to release a patch or a new version instantly, and you will only need to update the port promptly with respect to the author's fix. If the fix is delayed for some reason, you should either mark the port as FORBIDDEN or introduce a patch file of your own to the port. In the case of a vulnerable port, just fix the port as soon as possible. In either case, the standard procedure for submitting your change should be followed unless you have rights to commit it directly to the ports tree. Being a ports committer is not enough to commit to an arbitrary port. Remember that ports usually have maintainers, whom you should respect. Please make sure that the port's revision is bumped as soon as the vulnerability has been closed. That is how the users who upgrade installed packages on a regular basis will see they need to run an update. Besides, a new package will be built and distributed over FTP and WWW mirrors, replacing the vulnerable one. PORTREVISION should be bumped unless PORTVERSION has changed in the course of correcting the vulnerability. That is you should bump PORTREVISION if you have added a patch file to the port, but you should not if you have updated the port to the latest software version and thus already touched PORTVERSION. Please refer to the corresponding section for more information. Keeping the community informed The VuXML database A very important and urgent step to take as early as a security vulnerability is discovered is to notify the community of port users about the jeopardy. Such notification serves two purposes. First, should the danger be really severe, it will be wise to apply an instant workaround, e.g., stop the affected network service or even deinstall the port completely, until the vulnerability is closed. Second, a lot of users tend to upgrade installed packages just occasionally. They will know from the notification that they must update the package without delay as soon as a corrected version is available. Given the huge number of ports in the tree, a security advisory cannot be issued on each incident without creating a flood and losing the attention of the audience by the time it comes to really serious matters. Therefore security vulnerabilities found in ports are recorded in the FreeBSD VuXML database. The Security Officer Team members are monitoring it for issues requiring their intervention. If you have committer rights, you can update the VuXML database by yourself. So you will both help the Security Officer Team and deliver the crucial information to the community earlier. However, if you are not a committer, or you believe you have found an exceptionally severe vulnerability, or whatever, please do not hesitate to contact the Security Officer Team directly as described on the FreeBSD Security Information page. All right, you elected the hard way. As it may be obvious from its title, the VuXML database is essentially an XML document. Its source file vuln.xml is kept right inside the port security/vuxml. Therefore the file's full pathname will be PORTSDIR/security/vuxml/vuln.xml. Each time you discover a security vulnerability in a port, please add an entry for it to that file. Until you are familiar with VuXML, the best thing you can do is to find an existing entry fitting your case, then copy it and use as a template. A short introduction to VuXML The full-blown XML is complex and far beyond the scope of this book. However, to gain basic insight on the structure of a VuXML entry, you need only the notion of tags. XML tag names are enclosed in angle brackets. Each opening <tag> must have a matching closing </tag>. Tags may be nested. If nesting, the inner tags must be closed before the outer ones. There is a hierarchy of tags, i.e. more complex rules of nesting them. Sounds very similar to HTML, doesn't it? The major difference is that XML is eXtensible, i.e. based on defining custom tags. Due to its intrinsic structure, XML puts otherwise amorphous data into shape. VuXML is particularly tailored to mark up descriptions of security vulnerabilities. Now let's consider a realistic VuXML entry: <vuln vid="f4bc80f4-da62-11d8-90ea-0004ac98a7b9"> <topic>Several vulnerabilities found in Foo</topic> <affects> <package> <name>foo</name> <name>foo-devel</name> <name>ja-foo</name> <range><ge>1.6</ge><lt>1.9</lt></range> <range><ge>2.*</ge><lt>2.4_1</lt></range> <range><eq>3.0b1</eq></range> </package> <package> <name>openfoo</name> <range><lt>1.10_7</lt></range> <range><ge>1.2,1</ge><lt>1.3_1,1</lt></range> </package> </affects> <description> <body xmlns="http://www.w3.org/1999/xhtml"> <p>J. Random Hacker reports:</p> <blockquote cite="http://j.r.hacker.com/advisories/1"> <p>Several issues in the Foo software may be exploited via carefully crafted QUUX requests. These requests will permit the injection of Bar code, mumble theft, and the readability of the Foo administrator account.</p> </blockquote> </body> </description> <references> <freebsdsa>SA-10:75.foo</freebsdsa> <freebsdpr>ports/987654</freebsdpr> <cvename>CAN-2010-0201</cvename> <cvename>CAN-2010-0466</cvename> <bid>96298</bid> <certsa>CA-2010-99</certsa> <certvu>740169</certvu> <uscertsa>SA10-99A</uscertsa> <uscertta>SA10-99A</uscertta> <mlist msgid="201075606@hacker.com">http://marc.theaimsgroup.com/?l=bugtraq&amp;m=203886607825605</mlist> <url>http://j.r.hacker.com/advisories/1</url> </references> <dates> <discovery>2010-05-25</discovery> <entry>2010-07-13</entry> <modified>2010-09-17</entry> </dates> </vuln> The tag names are supposed to be self-descriptive, so we shall take a closer look only at fields you will need to fill in by yourself: This is the top-level tag of a VuXML entry. It has a mandatory attribute, vid, specifying a universally unique identifier (UUID) for this entry (in quotes). You should generate a UUID for each new VuXML entry (and do not forget to substitute it for the template UUID unless you are writing the entry from scratch). You can use &man.uuidgen.1; to generate a VuXML UUID; alternatively, if you are using FreeBSD 4.x, you may install the port devel/p5-Data-UUID and issue the following command: perl -MData::UUID -le 'print lc new Data::UUID->create_str' This is a one-line description of the issue found. The names of packages affected are listed there. Multiple names can be given since several packages may be based on a single master port or software product. This may include stable and development branches, localized versions, and slave ports featuring different choices of important build-time configuration options. It is your responsibility to find all such related packages when writing a VuXML entry. Keep in mind that make search name=foo is your friend. The primary points to look for are as follows: the foo-devel variant for a foo port; other variants with a suffix like -a4 (for print-related packages), -without-gui (for packages with X support disabled), or similar; jp-, ru-, zh-, and other possible localized variants in the corresponding national categories of the ports collection. Affected versions of the package(s) are specified there as one or more ranges using a combination of <lt>, <le>, <eq>, <ge>, and <gt> elements. The version ranges given should not overlap. In a range specification, * (asterisk) denotes the smallest version number. In particular, 2.* is less than 2.a. Therefore an asterisk may be used for a range to match all possible alpha, beta, and RC versions. For instance, <ge>2.*</ge><lt>3.*</lt> will selectively match every 2.x version while <ge>2.0</ge><lt>3.0</lt> will obviously not since the latter misses 2.r3 and matches 3.b. The above example specifies that affected are versions from 1.6 to 1.9 inclusive, versions 2.x before 2.4_1, and version 3.0b1. Several related package groups (essentially, ports) can be listed in the <affected> section. This can be used if several software products (say FooBar, FreeBar and OpenBar) grow from the same code base and still share its bugs and vulnerabilities. Note the difference from listing multiple names within a single <package> section. The version ranges should allow for PORTEPOCH and PORTREVISION if applicable. Please remember that according to the collation rules, a version with a non-zero PORTEPOCH is greater than any version without PORTEPOCH, e.g., 3.0,1 is greater than 3.1 or even than 8.9. This is a summary of the issue. XHTML is used in this field. At least enclosing <p> and </p> should appear. More complex mark-up may be used, but only for the sake of accuracy and clarity: No eye candy please. This section contains references to relevant documents. As many references as apply are encouraged. This is a FreeBSD security advisory. This is a FreeBSD problem report. This is a Mitre CVE identifier. This is a SecurityFocus Bug ID. This is a US-CERT security advisory. This is a US-CERT vulnerability note. This is a US-CERT Cyber Security Alert. This is a US-CERT Technical Cyber Security Alert. This is a URL to an archived posting in a mailing list. The attribute msgid is optional and may specify the message ID of the posting. This is a generic URL. It should be used only if none of the other reference categories apply. This is the date when the issue was disclosed (YYYY-MM-DD). This is the date when the entry was added (YYYY-MM-DD). This is the date when any information in the entry was last modified (YYYY-MM-DD). New entries must not include this field. It should be added upon editing an existing entry. Testing your changes to the VuXML database Assume you just wrote or filled in an entry for a vulnerability in the package clamav that has been fixed in version 0.65_7. As a prerequisite, you need to install fresh versions of the ports ports-mgmt/portaudit and ports-mgmt/portaudit-db. First, check whether there already is an entry for this vulnerability. If there were such entry, it would match the previous version of the package, 0.65_6: &prompt.user; packaudit &prompt.user; portaudit clamav-0.65_6 To run packaudit, you must have permission to write to its DATABASEDIR, typically /var/db/portaudit. If there is none found, you get the green light to add a new entry for this vulnerability. Now you can generate a brand-new UUID (assume it's 74a9541d-5d6c-11d8-80e3-0020ed76ef5a) and add your new entry to the VuXML database. Please verify its syntax after that as follows: &prompt.user; cd ${PORTSDIR}/security/vuxml && make validate You will need at least one of the following packages installed: textproc/libxml2, textproc/jade. Now rebuild the portaudit database from the VuXML file: &prompt.user; packaudit To verify that the <affected> section of your entry will match correct package(s), issue the following command: &prompt.user; portaudit -f /usr/ports/INDEX -r 74a9541d-5d6c-11d8-80e3-0020ed76ef5a Please refer to &man.portaudit.1; for better understanding of the command syntax. Make sure that your entry produces no spurious matches in the output. Now check whether the right package versions are matched by your entry: &prompt.user; portaudit clamav-0.65_6 clamav-0.65_7 Affected package: clamav-0.65_6 (matched by clamav<0.65_7) Type of problem: clamav remote denial-of-service. Reference: <http://www.freebsd.org/ports/portaudit/74a9541d-5d6c-11d8-80e3-0020ed76ef5a.html> 1 problem(s) found. Obviously, the former version should match while the latter one should not. Finally, verify whether the web page generated from the VuXML database looks like expected: &prompt.user; mkdir -p ~/public_html/portaudit &prompt.user; packaudit &prompt.user; lynx ~/public_html/portaudit/74a9541d-5d6c-11d8-80e3-0020ed76ef5a.html Dos and Don'ts Introduction Here is a list of common dos and don'ts that you encounter during the porting process. You should check your own port against this list, but you can also check ports in the PR database that others have submitted. Submit any comments on ports you check as described in Bug Reports and General Commentary. Checking ports in the PR database will both make it faster for us to commit them, and prove that you know what you are doing. <makevar>WRKDIR</makevar> Do not write anything to files outside WRKDIR. WRKDIR is the only place that is guaranteed to be writable during the port build (see installing ports from a CDROM for an example of building ports from a read-only tree). If you need to modify one of the pkg-* files, do so by redefining a variable, not by writing over it. <makevar>WRKDIRPREFIX</makevar> Make sure your port honors WRKDIRPREFIX. Most ports do not have to worry about this. In particular, if you are referring to a WRKDIR of another port, note that the correct location is WRKDIRPREFIXPORTSDIR/subdir/name/work not PORTSDIR/subdir/name/work or .CURDIR/../../subdir/name/work or some such. Also, if you are defining WRKDIR yourself, make sure you prepend ${WRKDIRPREFIX}${.CURDIR} in the front. Differentiating operating systems and OS versions You may come across code that needs modifications or conditional compilation based upon what version of Unix it is running under. If you need to make such changes to the code for conditional compilation, make sure you make the changes as general as possible so that we can back-port code to older FreeBSD systems and cross-port to other BSD systems such as 4.4BSD from CSRG, BSD/386, 386BSD, NetBSD, and OpenBSD. The preferred way to tell 4.3BSD/Reno (1990) and newer versions of the BSD code apart is by using the BSD macro defined in sys/param.h. Hopefully that file is already included; if not, add the code: #if (defined(__unix__) || defined(unix)) && !defined(USG) #include <sys/param.h> #endif to the proper place in the .c file. We believe that every system that defines these two symbols has sys/param.h. If you find a system that does not, we would like to know. Please send mail to the &a.ports;. Another way is to use the GNU Autoconf style of doing this: #ifdef HAVE_SYS_PARAM_H #include <sys/param.h> #endif Do not forget to add -DHAVE_SYS_PARAM_H to the CFLAGS in the Makefile for this method. Once you have sys/param.h included, you may use: #if (defined(BSD) && (BSD >= 199103)) to detect if the code is being compiled on a 4.3 Net2 code base or newer (e.g. FreeBSD 1.x, 4.3/Reno, NetBSD 0.9, 386BSD, BSD/386 1.1 and below). Use: #if (defined(BSD) && (BSD >= 199306)) to detect if the code is being compiled on a 4.4 code base or newer (e.g. FreeBSD 2.x, 4.4, NetBSD 1.0, BSD/386 2.0 or above). The value of the BSD macro is 199506 for the 4.4BSD-Lite2 code base. This is stated for informational purposes only. It should not be used to distinguish between versions of FreeBSD based only on 4.4-Lite vs. versions that have merged in changes from 4.4-Lite2. The __FreeBSD__ macro should be used instead. Use sparingly: __FreeBSD__ is defined in all versions of FreeBSD. Use it if the change you are making only affects FreeBSD. Porting gotchas like the use of sys_errlist[] vs strerror() are Berkeley-isms, not FreeBSD changes. In FreeBSD 2.x, __FreeBSD__ is defined to be 2. In earlier versions, it is 1. Later versions always bump it to match their major version number. If you need to tell the difference between a FreeBSD 1.x system and a FreeBSD 2.x or above system, usually the right answer is to use the BSD macros described above. If there actually is a FreeBSD specific change (such as special shared library options when using ld) then it is OK to use __FreeBSD__ and #if __FreeBSD__ > 1 to detect a FreeBSD 2.x and later system. If you need more granularity in detecting FreeBSD systems since 2.0-RELEASE you can use the following: #if __FreeBSD__ >= 2 #include <osreldate.h> # if __FreeBSD_version >= 199504 /* 2.0.5+ release specific code here */ # endif #endif In the hundreds of ports that have been done, there have only been one or two cases where __FreeBSD__ should have been used. Just because an earlier port screwed up and used it in the wrong place does not mean you should do so too. FreeBSD 版本速查表(__FreeBSD_version) 以下是 sys/param.h 內的 __FreeBSD_version 版本速查表: __FreeBSD_version values Release __FreeBSD_version 2.0-RELEASE 119411 2.1-CURRENT 199501, 199503 2.0.5-RELEASE 199504 2.2-CURRENT before 2.1 199508 2.1.0-RELEASE 199511 2.2-CURRENT before 2.1.5 199512 2.1.5-RELEASE 199607 2.2-CURRENT before 2.1.6 199608 2.1.6-RELEASE 199612 2.1.7-RELEASE 199612 2.2-RELEASE 220000 2.2.1-RELEASE 220000 (no change) 2.2-STABLE after 2.2.1-RELEASE 220000 (no change) 2.2-STABLE after texinfo-3.9 221001 2.2-STABLE after top 221002 2.2.2-RELEASE 222000 2.2-STABLE after 2.2.2-RELEASE 222001 2.2.5-RELEASE 225000 2.2-STABLE after 2.2.5-RELEASE 225001 2.2-STABLE after ldconfig -R merge 225002 2.2.6-RELEASE 226000 2.2.7-RELEASE 227000 2.2-STABLE after 2.2.7-RELEASE 227001 2.2-STABLE after &man.semctl.2; change 227002 2.2.8-RELEASE 228000 2.2-STABLE after 2.2.8-RELEASE 228001 3.0-CURRENT before &man.mount.2; change 300000 3.0-CURRENT after &man.mount.2; change 300001 3.0-CURRENT after &man.semctl.2; change 300002 3.0-CURRENT after ioctl arg changes 300003 3.0-CURRENT after ELF conversion 300004 3.0-RELEASE 300005 3.0-CURRENT after 3.0-RELEASE 300006 3.0-STABLE after 3/4 branch 300007 3.1-RELEASE 310000 3.1-STABLE after 3.1-RELEASE 310001 3.1-STABLE after C++ constructor/destructor order change 310002 3.2-RELEASE 320000 3.2-STABLE 320001 3.2-STABLE after binary-incompatible IPFW and socket changes 320002 3.3-RELEASE 330000 3.3-STABLE 330001 3.3-STABLE after adding &man.mkstemp.3; to libc 330002 3.4-RELEASE 340000 3.4-STABLE 340001 3.5-RELEASE 350000 3.5-STABLE 350001 4.0-CURRENT after 3.4 branch 400000 4.0-CURRENT after change in dynamic linker handling 400001 4.0-CURRENT after C++ constructor/destructor order change 400002 4.0-CURRENT after functioning &man.dladdr.3; 400003 4.0-CURRENT after __deregister_frame_info dynamic linker bug fix (also 4.0-CURRENT after EGCS 1.1.2 integration) 400004 4.0-CURRENT after &man.suser.9; API change (also 4.0-CURRENT after newbus) 400005 4.0-CURRENT after cdevsw registration change 400006 4.0-CURRENT after the addition of so_cred for socket level credentials 400007 4.0-CURRENT after the addition of a poll syscall wrapper to libc_r 400008 4.0-CURRENT after the change of the kernel's dev_t type to struct specinfo pointer 400009 4.0-CURRENT after fixing a hole in &man.jail.2; 400010 4.0-CURRENT after the sigset_t datatype change 400011 4.0-CURRENT after the cutover to the GCC 2.95.2 compiler 400012 4.0-CURRENT after adding pluggable linux-mode ioctl handlers 400013 4.0-CURRENT after importing OpenSSL 400014 4.0-CURRENT after the C++ ABI change in GCC 2.95.2 from -fvtable-thunks to -fno-vtable-thunks by default 400015 4.0-CURRENT after importing OpenSSH 400016 4.0-RELEASE 400017 4.0-STABLE after 4.0-RELEASE 400018 4.0-STABLE after the introduction of delayed checksums. 400019 4.0-STABLE after merging libxpg4 code into libc. 400020 4.0-STABLE after upgrading Binutils to 2.10.0, ELF branding changes, and tcsh in the base system. 400021 4.1-RELEASE 410000 4.1-STABLE after 4.1-RELEASE 410001 4.1-STABLE after &man.setproctitle.3; moved from libutil to libc. 410002 4.1.1-RELEASE 411000 4.1.1-STABLE after 4.1.1-RELEASE 411001 4.2-RELEASE 420000 4.2-STABLE after combining libgcc.a and libgcc_r.a, and associated GCC linkage changes. 420001 4.3-RELEASE 430000 4.3-STABLE after wint_t introduction. 430001 4.3-STABLE after PCI powerstate API merge. 430002 4.4-RELEASE 440000 4.4-STABLE after d_thread_t introduction. 440001 4.4-STABLE after mount structure changes (affects filesystem klds). 440002 4.4-STABLE after the userland components of smbfs were imported. 440003 4.5-RELEASE 450000 4.5-STABLE after the usb structure element rename. 450001 4.5-STABLE after the sendmail_enable &man.rc.conf.5; variable was made to take the value NONE. 450004 4.5-STABLE after moving to XFree86 4 by default for package builds. 450005 4.5-STABLE after accept filtering was fixed so that is no longer susceptible to an easy DoS. 450006 4.6-RELEASE 460000 4.6-STABLE &man.sendfile.2; fixed to comply with documentation, not to count any headers sent against the amount of data to be sent from the file. 460001 4.6.2-RELEASE 460002 4.6-STABLE 460100 4.6-STABLE after MFC of `sed -i'. 460101 4.6-STABLE after MFC of many new pkg_install features from the HEAD. 460102 4.7-RELEASE 470000 4.7-STABLE 470100 Start generated __std{in,out,err}p references rather than __sF. This changes std{in,out,err} from a compile time expression to a runtime one. 470101 4.7-STABLE after MFC of mbuf changes to replace m_aux mbufs by m_tag's 470102 4.7-STABLE gets OpenSSL 0.9.7 470103 4.8-RELEASE 480000 4.8-STABLE 480100 4.8-STABLE after &man.realpath.3; has been made thread-safe 480101 4.8-STABLE 3ware API changes to twe. 480102 4.9-RELEASE 490000 4.9-STABLE 490100 4.9-STABLE after e_sid was added to struct kinfo_eproc. 490101 4.9-STABLE after MFC of libmap functionality for rtld. 490102 4.10-RELEASE 491000 4.10-STABLE 491100 4.10-STABLE after MFC of revision 20040629 of the package tools 491101 4.10-STABLE after VM fix dealing with unwiring of fictitious pages 491102 4.11-RELEASE 492000 4.11-STABLE 492100 4.11-STABLE after adding libdata/ldconfig directories to mtree files. 492101 5.0-CURRENT 500000 5.0-CURRENT after adding addition ELF header fields, and changing our ELF binary branding method. 500001 5.0-CURRENT after kld metadata changes. 500002 5.0-CURRENT after buf/bio changes. 500003 5.0-CURRENT after binutils upgrade. 500004 5.0-CURRENT after merging libxpg4 code into libc and after TASKQ interface introduction. 500005 5.0-CURRENT after the addition of AGP interfaces. 500006 5.0-CURRENT after Perl upgrade to 5.6.0 500007 5.0-CURRENT after the update of KAME code to 2000/07 sources. 500008 5.0-CURRENT after ether_ifattach() and ether_ifdetach() changes. 500009 5.0-CURRENT after changing mtree defaults back to original variant, adding -L to follow symlinks. 500010 5.0-CURRENT after kqueue API changed. 500011 5.0-CURRENT after &man.setproctitle.3; moved from libutil to libc. 500012 5.0-CURRENT after the first SMPng commit. 500013 5.0-CURRENT after <sys/select.h> moved to <sys/selinfo.h>. 500014 5.0-CURRENT after combining libgcc.a and libgcc_r.a, and associated GCC linkage changes. 500015 5.0-CURRENT after change allowing libc and libc_r to be linked together, deprecating -pthread option. 500016 5.0-CURRENT after switch from struct ucred to struct xucred to stabilize kernel-exported API for mountd et al. 500017 5.0-CURRENT after addition of CPUTYPE make variable for controlling CPU-specific optimizations. 500018 5.0-CURRENT after moving machine/ioctl_fd.h to sys/fdcio.h 500019 5.0-CURRENT after locale names renaming. 500020 5.0-CURRENT after Bzip2 import. Also signifies removal of S/Key. 500021 5.0-CURRENT after SSE support. 500022 5.0-CURRENT after KSE Milestone 2. 500023 5.0-CURRENT after d_thread_t, and moving UUCP to ports. 500024 5.0-CURRENT after ABI change for descriptor and creds passing on 64 bit platforms. 500025 5.0-CURRENT after moving to XFree86 4 by default for package builds, and after the new libc strnstr() function was added. 500026 5.0-CURRENT after the new libc strcasestr() function was added. 500027 5.0-CURRENT after the userland components of smbfs were imported. 500028 5.0-CURRENT after the new C99 specific-width integer types were added. (Not incremented.) 5.0-CURRENT after a change was made in the return value of &man.sendfile.2;. 500029 5.0-CURRENT after the introduction of the type fflags_t, which is the appropriate size for file flags. 500030 5.0-CURRENT after the usb structure element rename. 500031 5.0-CURRENT after the introduction of Perl 5.6.1. 500032 5.0-CURRENT after the sendmail_enable &man.rc.conf.5; variable was made to take the value NONE. 500033 5.0-CURRENT after mtx_init() grew a third argument. 500034 5.0-CURRENT with Gcc 3.1. 500035 5.0-CURRENT without Perl in /usr/src 500036 5.0-CURRENT after the addition of &man.dlfunc.3; 500037 5.0-CURRENT after the types of some struct sockbuf members were changed and the structure was reordered. 500038 5.0-CURRENT after GCC 3.2.1 import. Also after headers stopped using _BSD_FOO_T_ and started using _FOO_T_DECLARED. This value can also be used as a conservative estimate of the start of &man.bzip2.1; package support. 500039 5.0-CURRENT after various changes to disk functions were made in the name of removing dependency on disklabel structure internals. 500040 5.0-CURRENT after the addition of &man.getopt.long.3; to libc. 500041 5.0-CURRENT after Binutils 2.13 upgrade, which included new FreeBSD emulation, vec, and output format. 500042 5.0-CURRENT after adding weak pthread_XXX stubs to libc, obsoleting libXThrStub.so. 5.0-RELEASE. 500043 5.0-CURRENT after branching for RELENG_5_0 500100 <sys/dkstat.h> is empty and should not be included. 500101 5.0-CURRENT after the d_mmap_t interface change. 500102 5.0-CURRENT after taskqueue_swi changed to run without Giant, and taskqueue_swi_giant added to run with Giant. 500103 cdevsw_add() and cdevsw_remove() no longer exists. Appearance of MAJOR_AUTO allocation facility. 500104 5.0-CURRENT after new cdevsw initialization method. 500105 devstat_add_entry() has been replaced by devstat_new_entry() 500106 Devstat interface change; see sys/sys/param.h 1.149 500107 Token-Ring interface changes. 500108 Addition of vm_paddr_t. 500109 5.0-CURRENT after &man.realpath.3; has been made thread-safe 500110 5.0-CURRENT after &man.usbhid.3; has been synced with NetBSD 500111 5.0-CURRENT after new NSS implementation and addition of POSIX.1 getpw*_r, getgr*_r functions 500112 5.0-CURRENT after removal of the old rc system. 500113 5.1-RELEASE. 501000 5.1-CURRENT after branching for RELENG_5_1. 501100 5.1-CURRENT after correcting the semantics of sigtimedwait(2) and sigwaitinfo(2). 501101 5.1-CURRENT after adding the lockfunc and lockfuncarg fields to &man.bus.dma.tag.create.9;. 501102 5.1-CURRENT after GCC 3.3.1-pre 20030711 snapshot integration. 501103 5.1-CURRENT 3ware API changes to twe. 501104 5.1-CURRENT dynamically-linked /bin and /sbin support and movement of libraries to /lib. 501105 5.1-CURRENT after adding kernel support for Coda 6.x. 501106 5.1-CURRENT after 16550 UART constants moved from <dev/sio/sioreg.h> to <dev/ic/ns16550.h>. Also when libmap functionality was unconditionally supported by rtld. 501107 5.1-CURRENT after PFIL_HOOKS API update 501108 5.1-CURRENT after adding kiconv(3) 501109 5.1-CURRENT after changing default operations for open and close in cdevsw 501110 5.1-CURRENT after changed layout of cdevsw 501111 5.1-CURRENT after adding kobj multiple inheritance 501112 5.1-CURRENT after the if_xname change in struct ifnet 501113 5.1-CURRENT after changing /bin and /sbin to be dynamically linked 501114 5.2-RELEASE 502000 5.2.1-RELEASE 502010 5.2-CURRENT after branching for RELENG_5_2 502100 5.2-CURRENT after __cxa_atexit/__cxa_finalize functions were added to libc. 502101 5.2-CURRENT after change of default thread library from libc_r to libpthread. 502102 5.2-CURRENT after device driver API megapatch. 502103 5.2-CURRENT after getopt_long_only() addition. 502104 5.2-CURRENT after NULL is made into ((void *)0) for C, creating more warnings. 502105 5.2-CURRENT after pf is linked to the build and install. 502106 5.2-CURRENT after time_t is changed to a 64-bit value on sparc64. 502107 5.2-CURRENT after Intel C/C++ compiler support in some headers and execve(2) changes to be more strictly conforming to POSIX. 502108 5.2-CURRENT after the introduction of the bus_alloc_resource_any API 502109 5.2-CURRENT after the addition of UTF-8 locales 502110 5.2-CURRENT after the removal of the getvfsent(3) API 502111 5.2-CURRENT after the addition of the .warning directive for make. 502112 5.2-CURRENT after ttyioctl() was made mandatory for serial drivers. 502113 5.2-CURRENT after import of the ALTQ framework. 502114 5.2-CURRENT after changing sema_timedwait(9) to return 0 on success and a non-zero error code on failure. 502115 5.2-CURRENT after changing kernel dev_t to be pointer to struct cdev *. 502116 5.2-CURRENT after changing kernel udev_t to dev_t. 502117 5.2-CURRENT after adding support for CLOCK_VIRTUAL and CLOCK_PROF to clock_gettime(2) and clock_getres(2). 502118 5.2-CURRENT after changing network interface cloning overhaul. 502119 5.2-CURRENT after the update of the package tools to revision 20040629. 502120 5.2-CURRENT after marking Bluetooth code as non-i386 specific. 502121 5.2-CURRENT after the introduction of the KDB debugger framework, the conversion of DDB into a backend and the introduction of the GDB backend. 502122 5.2-CURRENT after change to make VFS_ROOT take a struct thread argument as does vflush. Struct kinfo_proc now has a user data pointer. The switch of the default X implementation to xorg was also made at this time. 502123 5.2-CURRENT after the change to separate the way ports rc.d and legacy scripts are started. 502124 5.2-CURRENT after the backout of the previous change. 502125 5.2-CURRENT after the removal of kmem_alloc_pageable() and the import of gcc 3.4.2. 502126 5.2-CURRENT after changing the UMA kernel API to allow ctors/inits to fail. 502127 5.2-CURRENT after the change of the vfs_mount signature as well as global replacement of PRISON_ROOT with SUSER_ALLOWJAIL for the suser(9) API. 502128 5.3-BETA/RC before the pfil API change 503000 5.3-RELEASE 503001 5.3-STABLE after branching for RELENG_5_3 503100 5.3-STABLE after addition of glibc style &man.strftime.3; padding options. 503101 5.3-STABLE after OpenBSD's nc(1) import MFC. 503102 5.4-PRERELEASE after the MFC of the fixes in <src/include/stdbool.h> and <src/sys/i386/include/_types.h> for using the GCC-compatibility of the Intel C/C++ compiler. 503103 5.4-PRERELEASE after the MFC of the change of ifi_epoch from wall clock time to uptime. 503104 5.4-PRERELEASE after the MFC of the fix of EOVERFLOW check in vswprintf(3). 503105 5.4-RELEASE. 504000 5.4-STABLE after branching for RELENG_5_4 504100 5.4-STABLE after increasing the default thread stacksizes 504101 5.4-STABLE after the addition of sha256 504102 5.4-STABLE after the MFC of if_bridge 504103 5.4-STABLE after the MFC of bsdiff and portsnap 504104 5.4-STABLE after MFC of ldconfig_local_dirs change. 504105 5.5-RELEASE. 505000 5.5-STABLE after branching for RELENG_5_5 505100 6.0-CURRENT 600000 6.0-CURRENT after permanently enabling PFIL_HOOKS in the kernel. 600001 6.0-CURRENT after initial addition of ifi_epoch to struct if_data. Backed out after a few days. Do not use this value. 600002 6.0-CURRENT after the re-addition of the ifi_epoch member of struct if_data. 600003 6.0-CURRENT after addition of the struct inpcb argument to the pfil API. 600004 6.0-CURRENT after addition of the "-d DESTDIR" argument to newsyslog. 600005 6.0-CURRENT after addition of glibc style &man.strftime.3; padding options. 600006 6.0-CURRENT after addition of 802.11 framework updates. 600007 6.0-CURRENT after changes to VOP_*VOBJECT() functions and introduction of MNTK_MPSAFE flag for Giantfree filesystems. 600008 6.0-CURRENT after addition of the cpufreq framework and drivers. 600009 6.0-CURRENT after importing OpenBSD's nc(1). 600010 6.0-CURRENT after removing semblance of SVID2 matherr() support. 600011 6.0-CURRENT after increase of default thread stacks' size. 600012 6.0-CURRENT after fixes in <src/include/stdbool.h> and <src/sys/i386/include/_types.h> for using the GCC-compatibility of the Intel C/C++ compiler. 600013 6.0-CURRENT after EOVERFLOW checks in vswprintf(3) fixed. 600014 6.0-CURRENT after changing the struct if_data member, ifi_epoch, from wall clock time to uptime. 600015 6.0-CURRENT after LC_CTYPE disk format changed. 600016 6.0-CURRENT after NLS catalogs disk format changed. 600017 6.0-CURRENT after LC_COLLATE disk format changed. 600018 Installation of acpica includes into /usr/include. 600019 Addition of MSG_NOSIGNAL flag to send(2) API. 600020 Addition of fields to cdevsw 600021 Removed gtar from base system. 600022 LOCAL_CREDS, LOCAL_CONNWAIT socket options added to unix(4). 600023 &man.hwpmc.4; and related tools added to 6.0-CURRENT. 600024 struct icmphdr added to 6.0-CURRENT. 600025 pf updated to 3.7. 600026 Kernel libalias and ng_nat introduced. 600027 POSIX ttyname_r(3) made available through unistd.h and libc. 600028 6.0-CURRENT after libpcap updated to v0.9.1 alpha 096. 600029 6.0-CURRENT after importing NetBSD's if_bridge(4). 600030 6.0-CURRENT after struct ifnet was broken out of the driver softcs. 600031 6.0-CURRENT after the import of libpcap v0.9.1. 600032 6.0-STABLE after bump of all shared library versions that had not been changed since RELENG_5. 600033 6.0-STABLE after credential argument is added to dev_clone event handler. 6.0-RELEASE. 600034 6.0-STABLE after 6.0-RELEASE 600100 6.0-STABLE after incorporating scripts from the local_startup directories into the base &man.rcorder.8;. 600101 6.0-STABLE after updating the ELF types and constants. 600102 6.0-STABLE after MFC of pidfile(3) API. 600103 6.0-STABLE after MFC of ldconfig_local_dirs change. 600104 6.0-STABLE after NLS catalog support of csh(1). 600105 6.1-RELEASE 601000 6.1-STABLE after 6.1-RELEASE. 601100 6.1-STABLE after the import of csup. 601101 6.1-STABLE after the iwi(4) update. 601102 6.1-STABLE after the resolver update to BIND9, and exposure of reentrant version of netdb functions. 601103 6.1-STABLE after DSO (dynamic shared objects) support has been enabled in OpenSSL. 601104 6.1-STABLE after 802.11 fixups changed the api for the IEEE80211_IOC_STA_INFO ioctl. 601104 6.2-RELEASE 602000 6.2-STABLE after 6.2-RELEASE. 602100 6.2-STABLE after the addition of Wi-Spy quirk. 602101 6.2-STABLE after pci_find_extcap() addition. 602102 6.2-STABLE after MFC of dlsym change to look for a requested symbol both in specified dso and its implicit dependencies. 602103 6.2-STABLE after MFC of ng_deflate(4) and ng_pred1(4) netgraph nodes and new compression and encryption modes for ng_ppp(4) node. 602104 6.2-STABLE after MFC of BSD licensed version of &man.gzip.1; ported from NetBSD. 602105 6.2-STABLE after MFC of PCI MSI and MSI-X support. 602106 6.2-STABLE after MFC of ncurses 5.6 and wide character support. 602107 6.2-STABLE after MFC of CAM 'SG' peripheral device, which implements a subset of Linux SCSI SG passthrough device API. 602108 6.2-STABLE after MFC of readline 5.2 patchset 002. 602109 6.2-STABLE after MFC of pmap_invalidate_cache(), pmap_change_attr(), pmap_mapbios(), pmap_mapdev_attr(), and pmap_unmapbios() for amd64 and i386. 602110 6.2-STABLE after MFC of BOP_BDFLUSH and caused breakage of the filesystem modules KBI. 602111 6.2-STABLE after libutil(3) MFC's. 602112 7.0-CURRENT. 700000 7.0-CURRENT after bump of all shared library versions that had not been changed since RELENG_5. 700001 7.0-CURRENT after credential argument is added to dev_clone event handler. 700002 7.0-CURRENT after memmem(3) is added to libc. 700003 7.0-CURRENT after solisten(9) kernel arguments are modified to accept a backlog parameter. 700004 7.0-CURRENT after IFP2ENADDR() was changed to return a pointer to IF_LLADDR(). 700005 7.0-CURRENT after addition of if_addr member to struct ifnet and IFP2ENADDR() removal. 700006 7.0-CURRENT after incorporating scripts from the local_startup directories into the base &man.rcorder.8;. 700007 7.0-CURRENT after removal of MNT_NODEV mount option. 700008 7.0-CURRENT after ELF-64 type changes and symbol versioning. 700009 7.0-CURRENT after addition of hostb and vgapci drivers, addition of pci_find_extcap(), and changing the AGP drivers to no longer map the aperture. 700010 7.0-CURRENT after tv_sec was made time_t on all platforms but Alpha. 700011 7.0-CURRENT after ldconfig_local_dirs change. 700012 7.0-CURRENT after changes to /etc/rc.d/abi to support /compat/linux/etc/ld.so.cache being a symlink in a readonly filesystem. 700013 7.0-CURRENT after pts import. 700014 7.0-CURRENT after the introduction of version 2 of &man.hwpmc.4;'s ABI. 700015 7.0-CURRENT after addition of &man.fcloseall.3; to libc. 700016 7.0-CURRENT after removal of ip6fw. 700017 7.0-CURRENT after import of snd_emu10kx. 700018 7.0-CURRENT after import of OpenSSL 0.9.8b. 700019 7.0-CURRENT after addition of bus_dma_get_tag function 700020 7.0-CURRENT after libpcap 0.9.4 and tcpdump 3.9.4 import. 700021 7.0-CURRENT after dlsym change to look for a requested symbol both in specified dso and its implicit dependencies. 700022 7.0-CURRENT after adding new sound IOCTLs. 700023 7.0-CURRENT after import of OpenSSL 0.9.8d. 700024 7.0-CURRENT after the addition of libelf. 700025 7.0-CURRENT after major changes on sound sysctls. 700026 7.0-CURRENT after the addition of Wi-Spy quirk. 700027 7.0-CURRENT after the addition of sctp calls to libc 700028 7.0-CURRENT after the GNU &man.gzip.1; implementation was replaced with a BSD licensed version ported from NetBSD. 700029 7.0-CURRENT after the removal of IPIP tunnel encapsulation (VIFF_TUNNEL) from the IPv4 multicast forwarding code. 700030 7.0-CURRENT after the modification of bus_setup_intr() (newbus). 700031 7.0-CURRENT after the inclusion of ipw(4) and iwi(4) firmwares. 700032 7.0-CURRENT after the inclusion of ncurses wide character support. 700033 7.0-CURRENT after changes to how insmntque(), getnewvnode(), and vfs_hash_insert() work. 700034 7.0-CURRENT after addition of a notify mechanism for CPU frequency changes. 700035 7.0-CURRENT after import of the ZFS filesystem. 700036 7.0-CURRENT after addition of CAM 'SG' peripheral device, which implements a subset of Linux SCSI SG passthrough device API. 700037 7.0-CURRENT after changing &man.getenv.3;, &man.putenv.3;, &man.setenv.3; and &man.unsetenv.3; to be POSIX conformant. 700038 7.0-CURRENT after the changes in 700038 were backed out. 700039 7.0-CURRENT after the addition of &man.flopen.3; to libutil. 700040 7.0-CURRENT after enabling symbol versioning, and changing the default thread library to libthr. 700041 7.0-CURRENT after the import of gcc 4.2.0. 700042 7.0-CURRENT after bump of all shared library versions that had not been changed since RELENG_6. 700043 7.0-CURRENT after changing the argument for vn_open()/VOP_OPEN() from filedescriptor index to the struct file *. 700044 7.0-CURRENT after changing &man.pam.nologin.8; to provide an account management function instead of an authentication function to the PAM framework. 700045 7.0-CURRENT after updated 802.11 wireless support. 700046 7.0-CURRENT after adding TCP LRO interface capabilities. 700047 7.0-CURRENT after RFC 3678 API support added to the IPv4 stack. Legacy RFC 1724 behaviour of the IP_MULTICAST_IF ioctl has now been removed; 0.0.0.0/8 may no longer be used to specify an interface index. struct ipmreqn should be used instead. 700048 7.0-CURRENT after importing pf from OpenBSD 4.1 700049 7.0-CURRENT after adding IPv6 support for FAST_IPSEC, deleting KAME IPSEC, and renaming FAST_IPSEC to IPSEC. (not changed) 7.0-CURRENT after converting setenv/putenv/etc. calls from traditional BSD to POSIX. 700050 7.0-CURRENT after adding new mmap/lseek/etc syscalls. 700051 7.0-CURRENT after moving I4B headers to include/i4b. 700052 7.0-CURRENT after the addition of support for PCI domains 700053 8.0-CURRENT. 800000
Note that 2.2-STABLE sometimes identifies itself as 2.2.5-STABLE after the 2.2.5-RELEASE. The pattern used to be year followed by the month, but we decided to change it to a more straightforward major/minor system starting from 2.2. This is because the parallel development on several branches made it infeasible to classify the releases simply by their real release dates. If you are making a port now, you do not have to worry about old -CURRENTs; they are listed here just for your reference.
Writing something after <filename>bsd.port.mk</filename> Do not write anything after the .include <bsd.port.mk> line. It usually can be avoided by including bsd.port.pre.mk somewhere in the middle of your Makefile and bsd.port.post.mk at the end. You need to include either the bsd.port.pre.mk/bsd.port.post.mk pair or bsd.port.mk only; do not mix these two usages. bsd.port.pre.mk only defines a few variables, which can be used in tests in the Makefile, bsd.port.post.mk defines the rest. Here are some important variables defined in bsd.port.pre.mk (this is not the complete list, please read bsd.port.mk for the complete list). Variable Description ARCH The architecture as returned by uname -m (e.g., i386) OPSYS The operating system type, as returned by uname -s (e.g., FreeBSD) OSREL The release version of the operating system (e.g., 2.1.5 or 2.2.7) OSVERSION The numeric version of the operating system; the same as __FreeBSD_version. PORTOBJFORMAT The object format of the system (elf or aout; note that for modern versions of FreeBSD, aout is deprecated.) LOCALBASE The base of the local tree (e.g., /usr/local/) X11BASE The base of the X11 tree (e.g., /usr/X11R6) PREFIX Where the port installs itself (see more on PREFIX). If you have to define the variables USE_IMAKE, USE_X_PREFIX, or MASTERDIR, do so before including bsd.port.pre.mk. Here are some examples of things you can write after bsd.port.pre.mk: # no need to compile lang/perl5 if perl5 is already in system .if ${OSVERSION} > 300003 BROKEN= perl is in system .endif # only one shlib version number for ELF .if ${PORTOBJFORMAT} == "elf" TCL_LIB_FILE= ${TCL_LIB}.${SHLIB_MAJOR} .else TCL_LIB_FILE= ${TCL_LIB}.${SHLIB_MAJOR}.${SHLIB_MINOR} .endif # software already makes link for ELF, but not for a.out post-install: .if ${PORTOBJFORMAT} == "aout" ${LN} -sf liblinpack.so.1.0 ${PREFIX}/lib/liblinpack.so .endif You did remember to use tab instead of spaces after BROKEN= and TCL_LIB_FILE=, did you not? :-). 在 wrapper scripts 中使用 <function>exec</function> 述句 若某 port 為了執行其他程式而安裝了一個 shell script, 而該程式同時也是該 script 最後一個動作,那麼需要確定該 script 是用 exec 述句(statement),舉例而言: #!/bin/sh exec %%LOCALBASE%%/bin/java -jar %%DATADIR%%/foo.jar "$@" exec 述句以所指定的程式取代了該 shell 的程序。 若省略 exec ,那麼該 shell 程序 將會在程式執行中一直存在於記憶體,這無疑地浪費了系統資源。 UIDs 及 GIDs The current list of reserved UIDs and GIDs can be found in ports/UIDs and ports/GIDs. If your port requires a certain user to be on the installed system, let the pkg-install script call pw to create it automatically. Look at net/cvsup-mirror for an example. Please note that this is strongly discouraged, please register user/group ID numbers as stated below. If your port must use the same user/group ID number when it is installed as a binary package as when it was compiled, then you must choose a free UID from 50 to 999 and register it either in ports/UIDs (for users) or in ports/GIDs (for groups). Look at japanese/Wnn6 for an example. Make sure you do not use a UID already used by the system or other ports. Please include a patch against these two files when you require a new user or group to be created for your port. Do things rationally The Makefile should do things simply and reasonably. If you can make it a couple of lines shorter or more readable, then do so. Examples include using a make .if construct instead of a shell if construct, not redefining do-extract if you can redefine EXTRACT* instead, and using GNU_CONFIGURE instead of CONFIGURE_ARGS += --prefix=${PREFIX}. If you find yourself having to write a lot of new code to try to do something, please go back and review bsd.port.mk to see if it contains an existing implementation of what you are trying to do. While hard to read, there are a great many seemingly-hard problems for which bsd.port.mk already provides a shorthand solution. Respect both <makevar>CC</makevar> and <makevar>CXX</makevar> The port should respect both CC and CXX variables. What we mean by this is that the port should not set the values of these variables absolutely, overriding existing values; instead, it should append whatever values it needs to the existing values. This is so that build options that affect all ports can be set globally. If the port does not respect these variables, please add NO_PACKAGE=ignores either cc or cxx to the Makefile. An example of a Makefile respecting both CC and CXX variables follows. Note the ?=: CC?= gcc CXX?= g++ Here is an example which respects neither CC nor CXX variables: CC= gcc CXX= g++ Both CC and CXX variables can be defined on FreeBSD systems in /etc/make.conf. The first example defines a value if it was not previously set in /etc/make.conf, preserving any system-wide definitions. The second example clobbers anything previously defined. Respect <makevar>CFLAGS</makevar> The port should respect the CFLAGS variable. What we mean by this is that the port should not set the value of this variable absolutely, overriding the existing value; instead, it should append whatever values it needs to the existing value. This is so that build options that affect all ports can be set globally. If it does not, please add NO_PACKAGE=ignores cflags to the Makefile. An example of a Makefile respecting the CFLAGS variable follows. Note the +=: CFLAGS+= -Wall -Werror Here is an example which does not respect the CFLAGS variable: CFLAGS= -Wall -Werror The CFLAGS variable is defined on FreeBSD systems in /etc/make.conf. The first example appends additional flags to the CFLAGS variable, preserving any system-wide definitions. The second example clobbers anything previously defined. You should remove optimization flags from the third party Makefiles. System CFLAGS contains system-wide optimization flags. An example from an unmodified Makefile: CFLAGS= -O3 -funroll-loops -DHAVE_SOUND Using system optimization flags, the Makefile would look similar to the following example: CFLAGS+= -DHAVE_SOUND Threading libraries The threading library must be linked to the binaries using a special linker flag -pthread on &os;. If a port insists on linking -lpthread or -lc_r directly, patch it to use PTHREAD_LIBS variable provided by the ports framework. This variable usually has the value of -pthread, but on certain architectures and &os; versions it can have different values, so do not just hardcode -pthread into patches and always use PTHREAD_LIBS. If building the port errors out with unrecognized option '-pthread' when setting PTHREAD_LIBS, it may be desirable to use gcc as linker by setting CONFIGURE_ENV to LD=${CC}. The -pthread option is not supported by ld directly. Feedback Do send applicable changes/patches to the original author/maintainer for inclusion in next release of the code. This will only make your job that much easier for the next release. <filename>README.html</filename> Do not include the README.html file. This file is not part of the cvs collection but is generated using the make readme command. Marking a port not installable with <makevar>BROKEN</makevar>, <makevar>FORBIDDEN</makevar>, or <makevar>IGNORE</makevar> In certain cases users should be prevented from installing a port. To tell a user that a port should not be installed, there are several make variables that can be used in a port's Makefile. The value of the following make variables will be the reason that is given back to users for why the port refuses to install itself. Please use the correct make variable as each make variable conveys radically different meanings to both users, and to automated systems that depend on the Makefiles, such as the ports build cluster, FreshPorts, and portsmon. Variables BROKEN is reserved for ports that currently do not compile, install, or deinstall correctly. It should be used for ports where the problem is believed to be temporary. If instructed, the build cluster will still attempt to try to build them to see if the underlying problem has been resolved. (However, in general, the cluster is run without this.) For instance, use BROKEN when a port: does not compile fails its configuration or installation process installs files outside of ${LOCALBASE} and ${X11BASE} does not remove all its files cleanly upon deinstall (however, it may be acceptable, and desirable, for the port to leave user-modified files behind) FORBIDDEN is used for ports that do contain a security vulnerability or induce grave concern regarding the security of a FreeBSD system with a given port installed (ex: a reputably insecure program or a program that provides easily exploitable services). Ports should be marked as FORBIDDEN as soon as a particular piece of software has a vulnerability and there is no released upgrade. Ideally ports should be upgraded as soon as possible when a security vulnerability is discovered so as to reduce the number of vulnerable FreeBSD hosts (we like being known for being secure), however sometimes there is a noticeable time gap between disclosure of a vulnerability and an updated release of the vulnerable software. Do not mark a port FORBIDDEN for any reason other than security. IGNORE is reserved for ports that should not be built for some other reason. It should be used for ports where the problem is believed to be structural. The build cluster will not, under any circumstances, build ports marked as IGNORE. For instance, use IGNORE when a port: compiles but does not run properly does not work on the installed version of &os; requires &os; kernel sources to build, but the user does not have them installed has a distfile which may not be automatically fetched due to licensing restrictions does not work with some other currently installed port (for instance, the port depends on www/apache21 but www/apache13 is installed) If a port would conflict with a currently installed port (for example, if they install a file in the same place that perfoms a different function), use CONFLICTS instead. CONFLICTS will set IGNORE by itself. If a port should be marked IGNORE only on certain architectures, there are two other convenience variables that will automatically set IGNORE for you: ONLY_FOR_ARCHS and NOT_FOR_ARCHS. Examples: ONLY_FOR_ARCHS= i386 amd64 NOT_FOR_ARCHS= alpha ia64 sparc64 A custom IGNORE message can be set using ONLY_FOR_ARCHS_REASON and NOT_FOR_ARCHS_REASON. Per architecture entries are possible with ONLY_FOR_ARCHS_REASON_ARCH and NOT_FOR_ARCHS_REASON_ARCH. If a port fetches i386 binaries and installs them, IA32_BINARY_PORT should be set. If this variable is set, it will be checked whether the /usr/lib32 directory is available for IA32 versions of libraries and whether the kernel has IA32 compatibility compiled in. If one of these two dependencies is not satisfied, IGNORE will be set automatically. Implementation Notes The strings should not be quoted. Also, the wording of the string should be somewhat different due to the way the information is shown to the user. Examples: BROKEN= this port is unsupported on FreeBSD 5.x IGNORE= is unsupported on FreeBSD 5.x resulting in the following output from make describe: ===> foobar-0.1 is marked as broken: this port is unsupported on FreeBSD 5.x. ===> foobar-0.1 is unsupported on FreeBSD 5.x. Marking a port for removal with <makevar>DEPRECATED</makevar> or <makevar>EXPIRATION_DATE</makevar> Do remember that BROKEN and FORBIDDEN are to be used as a temporary resort if a port is not working. Permanently broken ports should be removed from the tree entirely. When it makes sense to do so, users can be warned about a pending port removal with DEPRECATED and EXPIRATION_DATE. The former is simply a string stating why the port is scheduled for removal; the latter is a string in ISO 8601 format (YYYY-MM-DD). Both will be shown to the user. It is possible to set DEPRECATED without an EXPIRATION_DATE (for instance, recommending a newer version of the port), but the converse does not make any sense. There is no set policy on how much notice to give. Current practice seems to be one month for security-related issues and two months for build issues. This also gives any interested committers a little time to fix the problems. Avoid use of the <literal>.error</literal> construct The correct way for a Makefile to signal that the port can not be installed due to some external factor (for instance, the user has specified an illegal combination of build options) is to set a nonblank value to IGNORE. This value will be formatted and shown to the user by make install. It is a common mistake to use .error for this purpose. The problem with this is that many automated tools that work with the ports tree will fail in this situation. The most common occurrence of this is seen when trying to build /usr/ports/INDEX (see ). However, even more trivial commands such as make -V maintainer also fail in this scenario. This is not acceptable. How to avoid using <literal>.error</literal> Assume that someone has the line USE_POINTYHAT=yes in make.conf. The first of the next two Makefile snippets will cause make index to fail, while the second one will not: .if USE_POINTYHAT .error "POINTYHAT is not supported" .endif .if USE_POINTYHAT IGNORE=POINTYHAT is not supported .endif <filename>sysctl</filename> 使用時機 sysctl 除了在 targets 之外,都不鼓勵使用。 這是因為任何 makevar 的評估都有可能會使得程序執行速度變慢。例如在 make index 的過程中就會需要用到 sysctl 若要使用 &man.sysctl.8; 則必須透過 SYSCTL 此一變數才可,因為這樣才會包含完整路徑, 同時也可以隨時因應使用者需求而替換為其他路徑。 Rerolling distfiles Sometimes the authors of software change the content of released distfiles without changing the file's name. You have to verify that the changes are official and have been performed by the author. It has happened in the past that the distfile was silently altered on the download servers with the intent to cause harm or compromise end user security. Put the old distfile aside, download the new one, unpack them and compare the content with &man.diff.1;. If you see nothing suspicious, you can update distinfo. Be sure to summarize the differences in your PR or commit log, so that other people know that you have taken care to ensure that nothing bad has happened. You might also want to contact the authors of the software and confirm the changes with them. Necessary workarounds Sometimes it is necessary to work around bugs in software included with older versions of &os;. Some versions of &man.make.1; were broken on at least 4.8 and 5.0 with respect to handling comparisons based on OSVERSION. This would often lead to failures during make describe (and thus, the overall ports make index). The workaround is to enclose the conditional comparison in spaces, e.g.: if ( ${OSVERSION} > 500023 ) Be aware that test-installing a port on 4.9 or 5.2 will not detect this problem. Miscellanea The files pkg-descr and pkg-plist should each be double-checked. If you are reviewing a port and feel they can be worded better, do so. Do not copy more copies of the GNU General Public License into our system, please. Please be careful to note any legal issues! Do not let us illegally distribute software!
A Sample <filename>Makefile</filename> Here is a sample Makefile that you can use to create a new port. Make sure you remove all the extra comments (ones between brackets)! It is recommended that you follow this format (ordering of variables, empty lines between sections, etc.). This format is designed so that the most important information is easy to locate. We recommend that you use portlint to check the Makefile. [the header...just to make it easier for us to identify the ports.] # New ports collection makefile for: xdvi [the "version required" line is only needed when the PORTVERSION variable is not specific enough to describe the port.] # Date created: 26 May 1995 [this is the person who did the original port to FreeBSD, in particular, the person who wrote the first version of this Makefile. Remember, this should not be changed when upgrading the port later.] # Whom: Satoshi Asami <asami@FreeBSD.org> # # $FreeBSD$ [ ^^^^^^^^^ This will be automatically replaced with RCS ID string by CVS when it is committed to our repository. If upgrading a port, do not alter this line back to "$FreeBSD$". CVS deals with it automatically.] # [section to describe the port itself and the master site - PORTNAME and PORTVERSION are always first, followed by CATEGORIES, and then MASTER_SITES, which can be followed by MASTER_SITE_SUBDIR. PKGNAMEPREFIX and PKGNAMESUFFIX, if needed, will be after that. Then comes DISTNAME, EXTRACT_SUFX and/or DISTFILES, and then EXTRACT_ONLY, as necessary.] PORTNAME= xdvi PORTVERSION= 18.2 CATEGORIES= print [do not forget the trailing slash ("/")! if you are not using MASTER_SITE_* macros] MASTER_SITES= ${MASTER_SITE_XCONTRIB} MASTER_SITE_SUBDIR= applications PKGNAMEPREFIX= ja- DISTNAME= xdvi-pl18 [set this if the source is not in the standard ".tar.gz" form] EXTRACT_SUFX= .tar.Z [section for distributed patches -- can be empty] PATCH_SITES= ftp://ftp.sra.co.jp/pub/X11/japanese/ PATCHFILES= xdvi-18.patch1.gz xdvi-18.patch2.gz [maintainer; *mandatory*! This is the person who is volunteering to handle port updates, build breakages, and to whom a users can direct questions and bug reports. To keep the quality of the Ports Collection as high as possible, we no longer accept new ports that are assigned to "ports@FreeBSD.org".] MAINTAINER= asami@FreeBSD.org COMMENT= A DVI Previewer for the X Window System [dependencies -- can be empty] RUN_DEPENDS= gs:${PORTSDIR}/print/ghostscript LIB_DEPENDS= Xpm.5:${PORTSDIR}/graphics/xpm [this section is for other standard bsd.port.mk variables that do not belong to any of the above] [If it asks questions during configure, build, install...] IS_INTERACTIVE= yes [If it extracts to a directory other than ${DISTNAME}...] WRKSRC= ${WRKDIR}/xdvi-new [If the distributed patches were not made relative to ${WRKSRC}, you may need to tweak this] PATCH_DIST_STRIP= -p1 [If it requires a "configure" script generated by GNU autoconf to be run] GNU_CONFIGURE= yes [If it requires GNU make, not /usr/bin/make, to build...] USE_GMAKE= yes [If it is an X application and requires "xmkmf -a" to be run...] USE_IMAKE= yes [et cetera.] [non-standard variables to be used in the rules below] MY_FAVORITE_RESPONSE= "yeah, right" [then the special rules, in the order they are called] pre-fetch: i go fetch something, yeah post-patch: i need to do something after patch, great pre-install: and then some more stuff before installing, wow [and then the epilogue] .include <bsd.port.mk> Keeping Up The &os; Ports Collection is constantly changing. Here is some information on how to keep up. FreshPorts One of the easiest ways to learn about updates that have already been committed is by subscribing to FreshPorts. You can select multiple ports to monitor. Maintainers are strongly encouraged to subscribe, because they will receive notification of not only their own changes, but also any changes that any other &os; committer has made. (These are often necessary to keep up with changes in the underlying ports framework—although it would be most polite to receive an advance heads-up from those committing such changes, sometimes this is overlooked or just simply impractical. Also, in some cases, the changes are very minor in nature. We expect everyone to use their best judgement in these cases.) If you wish to use FreshPorts, all you need is an account. If your registered email address is @FreeBSD.org, you will see the opt-in link on the right hand side of the webpages. For those of you who already have a FreshPorts account, but are not using your @FreeBSD.org email address, just change your email to @FreeBSD.org, subscribe, then change it back again. FreshPorts also has a sanity test feature which automatically tests each commit to the FreeBSD ports tree. If subscribed to this service, you will be notified of any errors which FreshPorts detects during sanity testing of your commits. The Web Interface to the Source Repository It is possible to browse the files in the source repository by using a web interface. Changes that affect the entire port system are now documented in the CHANGES file. Changes that affect individual ports are now documented in the UPDATING file. However, the definitive answer to any question is undoubtedly to read the source code of bsd.port.mk, and associated files. The &os; Ports Mailing List If you maintain ports, you should consider following the &a.ports;. Important changes to the way ports work will be announced there, and then committed to CHANGES. The &os; Port Building Cluster on <hostid role="hostname">pointyhat.FreeBSD.org</hostid> One of the least-publicized strengths of &os; is that an entire cluster of machines is dedicated to continually building the Ports Collection, for each of the major OS releases and for each Tier-1 architecture. You can find the results of these builds at package building logs and errors. Individual ports are built unless they are specifically marked with IGNORE. Ports that are marked with BROKEN will still be attempted, to see if the underlying problem has been resolved. (This is done by passing TRYBROKEN to the port's Makefile.) The &os; Port Distfile Survey The build cluster is dedicated to building the latest release of each port with distfiles that have already been fetched. However, as the Internet continually changes, distfiles can quickly go missing. The FreeBSD Ports distfiles survey attempts to query every download site for every port to find out if each distfile is still currently available. Maintainers are asked to check this report periodically, not only to speed up the building process for users, but to help avoid wasting bandwidth of the sites that volunteer to host all these distfiles. The &os; Ports Monitoring System Another handy resource is the FreeBSD Ports Monitoring System (also known as portsmon). This system comprises a database that processes information from several sources and allows its to be browsed via a web interface. Currently, the ports Problem Reports (PRs), the error logs from the build cluster, and individual files from the ports collection are used. In the future, this will be expanded to include the distfile survey, as well as other sources. To get started, you can view all information about a particular port by using the Overview of One Port. As of this writing, this is the only resource available that maps GNATS PR entries to portnames. (PR submitters do not always include the portname in their Synopsis, although we would prefer that they did.) So, portsmon is a good place to start if you want to find out whether an existing port has any PRs filed against it and/or any build errors; or, to find out if a new port that you may be thinking about creating has already been submitted.