章 20. Ports and Packages 常見問題

Yi-Feng Tzeng
20.1. 如何只抓取 tarball?
20.2. 如何僅做到解開 tarball的步驟?
20.3. 如何僅做到解開 tarball 並補上官方提供的 patch ?
20.4. 如何安裝一個新的 port?
20.5. 如何安裝一個新的 port,並打包(package)起來?
20.6. 如何打包一個 port,並將其所有相依的 ports 也打包起來?
20.7. 如何對一個已經安裝的 port 打包?
20.8. 如何清理 ports 編輯期間所產生的暫存資料?
20.9. 如何清理 ports 編輯期間所產生的暫存資料,以及 tarball 檔?
20.10. 如何在安裝 ports 前查詢所依賴的相關套件?
20.11. 如何移除已安裝的 ports?
20.12. 如何一併移除所相依的 ports?
20.13. 如何重新安裝已安裝過的 ports?
20.14. 如何以關鍵字搜尋 ports?
20.15. 如何升級已安裝的 ports?
20.16. 如何查詢目前系統安裝了哪些套件?
20.17. 如何查詢目前系統有沒有安裝這個關鍵字的套件?
20.18. 如何查詢某個檔案是屬於哪些套件?
20.19. 如何查詢某個套件安裝了哪些檔案?
20.20. 如何安裝舊版的 ports?
20.21. 如何更新 ports Mk?
20.22. 如何解決安裝 ports 時出現 sed -i 的錯誤?
20.23. 如何列出所有可以升級的 ports?
20.24. 如何得知 ports 所提供的編譯參數?
20.25. 如何手動加入編譯 ports 的參數?
20.26. 如何指定 ports 的安裝路徑?
20.27. 安裝 ports 出現 FORCE_PKG_REGISTER 的錯誤訊息
20.28. 安裝 ports 出現 Shared object libintl.so.X not found 的錯誤訊息
20.29. 如何安裝 packages?
20.30. 如何強制安裝 packages?
20.31. 如何查詢 packages 與其他 packages 之間的相依性?
20.32. 如何安裝遠端的 packages?
20.33. 如何更新 INDEX 對照表?
20.34. 如何更新 INDEX HTML?
20.35. 如何針對某些 ports 不做 ports update?
20.36. make deinstall 與 pkg_delete 有什麼不同?

20.1. 如何只抓取 tarball?

如果只希望抓取 tarball 下來的話,僅需輸入以下指令即可:

# make fetch
如果是要抓取單一的 port,以 editors/joe 為例:

# cd /usr/ports/editors/joe
# make fetch

那麼,預設會將 editors/joe 的 tarball 下載至 /usr/ports/distfiles 目錄下。

如果是希望抓取安裝此 ports 所有相關相依 ports 的 tarball,以 systuils/portupgrade 為例的話, 則:

# cd /usr/ports/systuils/portupgrade
# make fetch-recursive

預設會將此 port 與所有需要的其他 port 的 tarball,下載至 /usr/ports/distfiles 目錄下。

如果是希望抓取全部所有 ports 的 tarball ,則:

# cd /usr/ports
# make fetch

則會所將全部所有 ports 的 tarball 下載至 /usr/ports/distfiles 目錄下。

如果是希望抓取 ftp 分類下所有 ports 的 tarball ,則:

# cd /usr/ports/ftp
# make fetch-recursive

則會所將 ftp 分類下所有 ports 的 tarball 都下載至 /usr/ports/distfiles 目錄下。

20.2. 如何僅做到解開 tarball的步驟?

有時候習慣自己 patch 原始碼的時候,會很常用到這個功能。以 editors/joe 為例:

# cd /usr/ports/editors/joe
# make extract

會將 tarball解開至 /usr/ports/editors/joe/work 目錄下。

20.3. 如何僅做到解開 tarball 並補上官方提供的 patch ?

此法與 make extract 的方法有一些類似,不同於是先補上官方提供的 patch,再行 patch 自己的修正。 有時候習慣自己 patch 原始碼的時候, 則這個方式正好符合您的需求。 以 editors/joe 為例:

# cd /usr/ports/editors/joe
# make patch

會將 tarball解開至 /usr/ports/editors/joe/work 目錄下 ,並補上官方提供的 patch。

20.4. 如何安裝一個新的 port?

如果系統上未安裝此軟體,則可以選擇安裝一個新的 port。 以 editors/joe 為例的話,則:

# cd /usr/ports/editors/joe
# make install

如此會在系統上安裝一個新的 joe 軟體。 如果需要在安裝完成後,一併清除編輯時期所留下來的暫存目錄,則可配合 make clean 的方法一起使用,如:

# cd /usr/ports/editors/joe
# make clean

如果想要一次清掉所有 ports 產生的暫存資料,則只要回到 ports 的根目錄執行即可:

# cd /usr/ports
# make clean

20.5. 如何安裝一個新的 port,並打包(package)起來?

將安裝完成的軟體打包起來,有許多便利性:包括在叢集系統中,可供其它機器使用, 或將未來此軟體出問題可重新利用此 package 重新快速安裝。 以 editors/joe 為例的話,則:

# cd /usr/ports/editors/joe
# make package

如此會在系統上安裝一個新的 joe 軟體,並將此軟體打包(package)起來。 package 預設會在 /usr/ports/editors/joe 目錄下,如果希望集中管理的話,建議做如下的步驟:

# mkdir -p /usr/ports/packages

以後打包的 packages 都會存放在此目錄下,並且系統會自動做分類,以方便管理。 如果需要在安裝完成後,一併清除編輯時期所留下來的暫存目錄,則可配合 make clean 一起使用,如:

# cd /usr/ports/editors/joe
# make package clean

20.6. 如何打包一個 port,並將其所有相依的 ports 也打包起來?

因為 make package 只有打包單一套件, 中間依賴的 ports 並沒有一起打包,這會出現一個常遇到的問題: 就是如果一個 port 需要依賴其它的 ports,那麼必須將其它 ports 也一起打包,否則安裝 packages 會有相依性的問題。 以 sysutils/portupgrade 為例:

# cd /usr/ports/sysutils/portupgrade
# make DEPENDS_TARGET=package package

如此會對所有 portupgrade 所相依賴的 ports 都一併打包,也包括自己本身。

20.7. 如何對一個已經安裝的 port 打包?

如果安裝好一個套件,事前並未打包,事後想打包的話,則: 以 editors/joe 為例:

# cd /var/db/pkg
# pkg_create -b joe-{版本號}

會將已安裝的 port 打包起來,放在 /var/db/pkg 目錄下。

20.8. 如何清理 ports 編輯期間所產生的暫存資料?

在安裝 port 的時候,會有編譯期間所需要的工作目錄(work),因此通常安裝好一個套件後,會清除此暫存目錄,以節省硬碟空間。 以 editors/joe 為例:

# cd /usr/ports/editors/joe
# make clean

如果是希望清除所有 ports 的暫存目錄,則:

# cd /usr/ports
# make clean

如果是希望清除所有 ftp 分類的暫存目錄,則:

# cd /usr/ports/ftp
# make clean

20.9. 如何清理 ports 編輯期間所產生的暫存資料,以及 tarball 檔?

make clean 僅只是清除編輯期間所需要的工作目錄(work),並沒有將編譯 ports 時一併下載的 tarball 刪除(相對應之 tarball 預設會存放在 /usr/ports/distfiles) 如果想把 tarball 一併清除的話,以 editors/joe 為例:

# cd /usr/ports/editors/joe
# make distclean

make distclean 的步驟包含了 make clean 的功能,也就是說除了會刪除 tarball 外,還會一併清除編譯時的暫存 work 目錄。

如果是希望清除所有 ports 的暫存 work 目錄及 tarball,則:

# cd /usr/ports
# make distclean

而如果是希望清除所有 ftp 分類的 work 目錄及 tarball,則:

# cd /usr/ports/ftp
# make distclean

20.10. 如何在安裝 ports 前查詢所依賴的相關套件?

在安裝 ports 前,可以查詢所依賴的相關套件。 以 mail/p5-Mail-SpamAssassin 為例:

# cd /usr/ports/mail/p5-Mail-SpamAssassin
# make all-depends-list

make all-depends-list 顯示此套件所有相依的套件。

# cd /usr/ports/mail/p5-Mail-SpamAssassin
# make pretty-print-build-depends-list

make all-depends-list 顯示此套件在編譯期間所需要的套件。

# cd /usr/ports/mail/p5-Mail-SpamAssassin
# make pretty-print-run-depends-list

make all-depends-list 顯示此套件要執行時所需要的套件。

20.11. 如何移除已安裝的 ports?

editors/joe 為例:

# cd /usr/ports/editors/joe
# make deinstall

或是使用 pkg_delete

# pkg_delete joe-{version}

有時候套件之間的相依性會導致無法直接移除,如果要強制移除的話,則:

# pkg_delete -f joe-{version}

但請注意:很有可能會導致其它相依到這軟體的套件執行起來出現問題。

至於二者的差別,請參考 make deinstall 與 pkg_delete 有什麼不同

20.12. 如何一併移除所相依的 ports?

sysutils/portupgrade 為例:

# cd /usr/ports/sysutils/portupgrade
# make deinstall-depends

執行此步驟前,請注意是否會移除其他套件也有共同相依的部分。建議先參考 make-depends-list 的方法來檢查。

或是使用

pkg_delete

這樣若仍有相依該套件的話,會先警告而不會移除。除非有另外加了 -f 參數來強制移除。

# pkg_delete -r portupgrade-{version}

至於二者的差別,請參考 make deinstall 與 pkg_delete 有什麼不同

20.13. 如何重新安裝已安裝過的 ports?

重新安裝的前提是:之前有安裝過或目前已安裝。以 editors/joe 為例:

# cd /usr/ports/editors/joe
# make deinstall clean install

或是

# cd /usr/ports/editors/joe
# make reinstall

20.14. 如何以關鍵字搜尋 ports?

如果要從全部的 ports collection 中找尋與關鍵字 "ldap" 有關的 ports,則:

# cd /usr/ports
# make search key=ldap

如果只要從與 ftp 相關的 ports 下找尋與關鍵字 "ldap" 有關的 ports,則:

# cd /usr/ports/ftp
# make search key=ldap

還有另一個用法,方法只是將 key 換成 name。如果已經知道要搜尋 ports 的名稱,或只想找名稱相關的關鍵字 "ldap", 則:

# cd /usr/ports
# make search name=ldap

20.15. 如何升級已安裝的 ports?

如果已經安裝套件,事後欲升級的話,必須先移除舊版的 port。以 editors/joe 為例:

# cd /usr/ports/editors/joe
# make clean reinstall

20.16. 如何查詢目前系統安裝了哪些套件?

查詢目前系統已安裝的全部套件:

# pkg_info

20.17. 如何查詢目前系統有沒有安裝這個關鍵字的套件?

假設要找的關鍵字是 joe 的話:

# pkg_info | grep joe

20.18. 如何查詢某個檔案是屬於哪些套件?

如果想查詢 /usr/local/bin/joe 是屬於哪個套件的話,則:

# pkg_info -W /usr/local/bin/joe

如果沒有回傳任何資訊的話,代表著這個檔案是由 FreeBSD 內建的。

20.19. 如何查詢某個套件安裝了哪些檔案?

如果想查詢目前系統所安裝的 joe 包含了哪些檔案,則:

# pkg_info -L /var/db/pkg/joe-{version}

20.20. 如何安裝舊版的 ports?

有時候會因為相依性,或是新版有問題,而會想裝舊版本的套件。 這裡介紹的方法是利用 CVS 的好處,回歸到以前舊版本存在的日子,以安裝舊版本的套件。

首先,若我們要回復到某一個套件的版本時,需要去查詢 FreeBSD ports CVS repository。 最常見的就是 Freshports 網站、 FreeBSD 的 Mailing FreeBSD cvs 或是 FreeBSD ports cvsweb

查到該套件版本所依存的日子後,就修改 CVS tag。一般預設 ports 的 CVS tag 會寫在 /usr/share/examples/cvsup/ports-supfile ,如要回溯到 2002/10/05 號的話,則:

# vi /usr/share/examples/cvsup/ports-supfile
*default date=2002.10.05.00.00.00  #將 date 改成當日

然後按照一般 CVSup 或 csup 的時候一樣,執行 CVSup 或 csup (make update),此時的 ports collections 就會回到當時的情形,那麼該套件的舊版也會出現在 ports collections 中,只要安裝即可。

如果僅是想回溯某部份的 ports,則必須加上額外的資訊,如僅希望把 lang/perl5.8 回溯, 而我們得知此屬於 lang 中的一支,則:

# vi /usr/share/examples/cvsup/ports-supfile
#ports-all #將 ports-all 標示起來
ports-lang #加入這行

最後,執行 CVSup 或 csup ,並安裝即可。目前若希望單獨回溯單一的 port,則比較麻煩。

20.21. 如何更新 ports Mk?

Mk (/usr/ports/Mk) 是編譯 ports 時所參考的設定,有時若發生 ports collections 太新,而導致 Mk 的內容不符,此時就是應該更新 Mk 的時候了。

# cd /usr/src
# make update
# cd /usr/src/share/mk
# make install

20.22. 如何解決安裝 ports 時出現 sed -i 的錯誤?

因為 BSD style 的 sed ,也就是 BSD 本身自有的 sed ,與一些 ports 編譯期間所執行的 sed 不一致,所以會導致一些語法錯誤。此時先安裝 sed_inplace (textproc/sed_inplace),然後再安裝原本無法安裝的 ports:

# make -DUSE_REINPLACE install

20.23. 如何列出所有可以升級的 ports?

ports collection 的更新速度很快,在每次更新 ports collections 後,往往會出現比目前現 在安裝的套件還新的版本,可以令系統自行整理並提供可升級套件的列表:

# pkg_version -c

20.24. 如何得知 ports 所提供的編譯參數?

所有的 ports collections 中所提供的編譯參數都會在對應的 Makefile 檔案內詳述, 如 sysutils/portupgrade 的話,則是位在 /usr/ports/sysutils/portupgrade/Makefile 檔案下。

# cd /usr/ports/sysutils/portupgrade
# make -DNOPORTDOCS install

那麼安裝此 ports 時,會將 NOPORTDOCS 所對應的相關參數指定進去。

有時候設定較人性化的 ports 會在安裝前提供參數供選擇,但是其實大部份的 ports 都沒有提 供,因此必須自行去搜尋可編譯的參數,在此我提供的方式如下:

# cd /usr/ports/sysutils/portupgrade
# grep defined Makefile

如此幾乎可以知道所有提供的可編譯參數,雖然有時會多出其它的資料,不會這個確實是一個不 錯可參考的方式。

20.25. 如何手動加入編譯 ports 的參數?

前面所述 的方法,是 ports collections 有提供的前提之下,有時候並不是所有該軟體所支援的參數都會收納在 ports collections 中,因此有時候會需要手動加入編譯的參數。

如 ftp/pure-ftpd 中,如果不想把 inetd 的支援編入的選項,並沒有被 ports collections 所納入,因此必須手動加上這個編譯參數,如下:

# cd /usr/ports/ftp/pure-ftpd
# make CONFIGURE_ARGS+="--without-inetd" install

20.26. 如何指定 ports 的安裝路徑?

預設 ports collecions 已安排安裝的路徑 (/usr/local/),如果不想將套件安裝在預設路徑的話,可以手動指定安裝路徑。以 editors/joe 為例,則:

# cd /usr/ports/editors/joe
# make PREFIX=/usr install

那麼 joe 就會將檔案對應在 /usr 目錄下,而不是預設的 /usr/local 目錄下。

20.27. 安裝 ports 出現 FORCE_PKG_REGISTER 的錯誤訊息

請參考 Ohaha 的 FAQ

20.28. 安裝 ports 出現 Shared object libintl.so.X not found 的錯誤訊息

請參考 Ohaha 的 FAQ

20.29. 如何安裝 packages?

目前 FreeBSD 的 packages 是由 .tgz 所打包。如果想安裝一個 packages ,可使用 pkg_add,如安裝一個 joe 的 tgz:

# pkg_add joe-{version}.tgz

20.30. 如何強制安裝 packages?

由於有些 packages 會有與其他 packages 相依性的關係,所以必須先行安裝那些 packages 才 能正常安裝。

如果須要強制安裝 packages ,可以不須安裝那些有相依性 packages ,但要注意的是強制安裝 的結果可能會導致執行或運作的不正常。強制安裝 packages 的指令如下,如強制安裝一個 joe 的 tgz:

# pkg_add -f joe-{version}.tgz

20.31. 如何查詢 packages 與其他 packages 之間的相依性?

由於有些 packages 會有與其他 packages 相依性的關係,所以必須先行安裝那些 packages 才 能正常安裝。

查詢 packages 與其他 packages 之間的相依性的指令如下,如查詢與 portupgrade 相依的其他 packages:

# pkg_info -r portupgrade-{version}.tgz

20.32. 如何安裝遠端的 packages?

有兩種設定方式,首先是 PACKAGEROOT,如:

# setenv PACKAGEROOT ftp://ftp.tw.freebsd.org

另一種方式是設定 PACKAGESITE,好處是若該站台的 packages 倉儲並不是符合官方的設定或你 想自己指定一個路徑。

以 ftp.tw.freebsd.org i386 的 current pakcages 為例:

# setenv PACKAGESITE ftp://ftp.tw.freebsd.org/pub/FreeBSD/ports/i386/packages-current/Latest/

兩種方式選擇其中一種皆可,接下來的步驟都一樣。

往後要安裝 packages 的時候,如 portupgrade 的話,則:

# pkg_add -r portupgrade

則系統會自動於 ftp.tw.freebsd.org 抓取所有與 portupgrade 相依的 packages 並安裝。

20.33. 如何更新 INDEX 對照表?

4.x 的 INDEX 位於 /usr/ports/INDEX,5.x 位於 /usr/ports/INDEX-5,以此類推。

INDEX 是對照 ports 所有相依等資訊的對照表,若長期未更新的話,會導致 ports 對照失敗。 官方有定期更新 INDEX,如果想自行更新的話,則:

# cd /usr/ports
# make index

如果想直接下載官方最新的 INDEX,則:

# cd /usr/ports
# make fetchindex

20.34. 如何更新 INDEX HTML?

FreeBSD 提供了用網頁的方式來觀看 ports collection,即可使用 lynx, w3m, links 或其它可瀏覽網頁的程式來查閱。製作全部 ports collection 的方式如下:

# cd /usr/ports
# make readmes

如果是僅須要做目前目錄下的資訊,或單一更新某一分類下的資訊,如 /usr/ports/ftp 的話,則:

# cd /usr/ports/ftp
# make readme

則僅會更新 /usr/ports/ftp 這個目錄的資訊,其上與其下的目錄皆不會更動到。執行成功後,會在相對應的目錄下產生 README.html 的檔案。

20.35. 如何針對某些 ports 不做 ports update?

若 ports 底下的某些分類完全用不到,則可以在 ports update 時,不做更新,以節省網路頻寬與時間。只要修改 /usr/sup/refuse 這個檔。

# ports/french
# ports/german
# ports/lang/perl5.8

則上列目錄將不會更新。

20.36. make deinstall 與 pkg_delete 有什麼不同?

簡單來說,make deinstall 會移除該 port,並且不會參照其相依的相關套件。

pkg_delete 在移除該 port 前,會參照其相依的相關套件,並且 pkg_delete 有支援 wild card ,如要移除所有 p 開頭的 ports,則:

# cd /var/db/pkg
# pkg_delete p*

要注意的是,如果使用 make deinstall,則最好確定系統目前所安裝的版本,與 ports collection 中顯示的版本符合,否則有可能會出現非預期性錯誤;而 pkg_delete 是因為直接 刪除系統中所安裝的版本,所以沒有此問題。

因此,換句話說,當系統所安裝的版本符合 ports collections 中的版本,則可以使用 make deinstall 或 pkg_delete,否則的話最好用 pkg_delete。

本文及其他文件,可由此下載:ftp://ftp.FreeBSD.org/pub/FreeBSD/doc/

若有 FreeBSD 方面疑問,請先閱讀 FreeBSD 相關文件,如不能解決的話,再洽詢 <questions@FreeBSD.org>。
關於本文件的問題,請洽詢 <doc@FreeBSD.org>。