您已經足夠多地考慮了為單一類型的系統構建開放源代碼應用程序的情形,但是,如果您正在構建的應用程序需要在多種不同的、不兼容的機器上發布,又該怎麼辦呢?這個問題不太容易解決,但是,可以使用一些准則和定制的腳本來簡化這一過程。本文研究的是如何創
您已經足夠多地考慮了為單一類型的系統構建開放源代碼應用程序的情形,但是,如果您正在構建的應用程序需要在多種不同的、不兼容的機器上發布,又該怎麼辦呢?這個問題不太容易解決,但是,可以使用一些准則和定制的腳本來簡化這一過程。本文研究的是如何創建一個構建和發布應用程序的結構,包括高度定制的版本,以及一種能在多種機器上盡可能輕松地傳播應用程序(手工地或者自動地)的簡單途徑。
我總是在自己的系統親自動手構建應用程序,而不去使用可用的二進制文件或 RPM 發行版本。這不是因為我不相信 RPM,而是因為對於很多系統來說,我使用的是一個定制的環境。我可能需要啟用調試,或者需要一個簡化或者特定的擴展名、模塊或者其他選項的集合。有時,我甚至會為一個特定項目創建一個完全不同的目錄結構。
因為復雜的緣故,我使用了大量使用開放源代碼項目的平台,其中包括
Linux™、BSD、OS X,以及各種商業
UNIX® 發行版本。對於其中一些平台,我可能只有一台機器安裝了這種平台;而對另一些平台來說,每種平台可能已經安裝在 10 台、20 台甚至 50 台機器上。當軟件某個部分的新版本開始可用時,手工地去更新每一台機器會是一項工作量極大的任務。實際的構建和安裝過程(假設我們不考慮定制)通常非常簡單,如清單 1 所示:
清單 1. 構建和安裝過程
$ bunzip2 -c latest-release.tar.bz|tar xf -
$ cd latest-release
$ ./configure
$ make
$ make install
如果沒有某些准則,我很可能要在成百上千台機器上手工去做這些工作。有時,感覺這像是一份只不過設法與最新版本(更不用說出於測試目的而使用某些程序包的 beta 和 alpha 版本了)保持同步的全職工作。
幾年前,我決定通過遵循一些簡單的規則並向該過程添加結構,來非常有效地簡化這一過程:
為每種 OS 創建一個目錄。
在每個 OS 目錄中為每一個軟件程序包創建一個目錄。
為每一個版本創建一個目錄。
為每種操作系統構建一次。
在每台機器上多次部署。
您可以先為所有跨
網絡共享的軟件構建一個合適的結構。
創建一個中央構建目錄 第一步是創建一個將通過 NFS 共享的目錄,它將用來保存將要構建的應用程序。一旦完成構建,您就可以使用這個目錄來保存系統所需要的所有內容,包括源文件目錄、配置文件以及其他組件。不過,NFS 是關鍵。要讓系統工作,就要能夠通過網絡,從需要訪問正構建和安裝的應用程序的所有機器訪問這個中央構建目錄。
創建一個頂層結構 首先要為需要在網絡上支持的每一種操作系統創建一個頂層結構。每一個目錄都應該明確對應於一種特定的操作系統、體系結構和版本編號(如果變化顯著的話)。這些目錄應該與您的網絡上的機器是相匹配的。例如,在我的網絡上,有非常多的機器,所以我的頂層目錄結構數量非常大,如清單 2 所示:
清單 2. 操作系統層目錄 in my build environment
total 58
drwxrwxrwx 2 root other 512 Jul 25 12:01 aix/
drwxrwxrwx 2 root other 512 Jul 25 13:14 darwin-ppc/
drwxrwxrwx 2 root other 512 Jul 25 13:14 darwin-x86/
drwxrwxrwx 2 root other 512 Jul 25 12:02 freebsd-x86/
drwxrwxrwx 2 root other 512 Jul 25 13:14 freedbsd-sparc/
drwxrwxrwx 3 root other 1024 Mar 9 2003 incoming/
drwxrwxrwx 2 root other 512 Jul 25 12:02
linux-debian-x86/
drwxrwxrwx 2 root other 512 Jul 25 12:02 linux-fedora-1-x86/
drwxrwxrwx 2 root other 512 Jul 25 12:02 linux-fedora-2-x86/
drwxrwxrwx 11 root other 512 Apr 13 16:56 linux-redhat-9.0-x86/
drwxr-xr-x 3 root root 8192 Feb 6 2002 lost+found/
drwxrwxrwx 13 root other 512 Jun 15 15:02 macosx/
drwxrwxrwx 2 root other 512 Jul 25 12:02
.netbsd-x86/
drwxrwxrwx 2 root other 512 Jul 25 12:02 openbsd/
lrwxrwxrwx 1 root other 12 Jul 25 13:13 solaris -> solaris8-x86/
drwxrwxrwx 2 root other 512 Jul 25 13:13 solaris8-sparc/
drwxrwxrwx 32 root other 1024 Jul 25 13:12 solaris8-x86/
drwxrwxrwx 2 root other 512 Jul 25 13:13 solaris9-sparc/
drwxrwxrwx 2 root other 512 Jul 25 13:13 solaris9-x86/
現在不要過多擔心應用程序。這些操作系統目錄將用來為每一個 OS 修訂版本保存相應的應用程序目錄。對應用程序構建的定制將單獨存放於每個目錄中。
我使用一個單獨的文件系統作為構建目錄,導出為 /export/build。這個文件系統有足夠的空間;對於構建目錄,您需要有足夠的空間來保存應用程序在每一種操作系統上使用每一個配置的完全構建版本。例如,Perl v5.9.0 編譯占用了大約 90 MB 的空間。 Apache 占用了大約 27 MB 的空間。
創建應用程序結構 您需要在每一個操作系統目錄中為想要安裝的每一個應用程序另外創建一個目錄。注意,該目錄是明確對應於每一種 OS 的,您應該只創建實際需要的應用程序目錄。例如,您可能希望在 Fedora 機器上安裝 Perl,但不想在其他機器上安裝它。在清單 3 中可以看到一個示例規劃:
清單 3. 一個 OS 目錄中的應用程序目錄
drwxrwxrwx 4 mc staff 512 May 12 12:30 apache/
drwxrwxrwx 4 root other 512 Apr 16 2003 assassin/
drwxrwxrwx 3 501 other 512 Jun 11 10:11 bind/
drwxrwxrwx 3 root other 512 Jul 24 15:37 ccache/
drwxrwxrwx 5 root other 512 Jun 21 17:12 clamav/
drwxrwxrwx 6 root other 512 Jul 25 15:28 cpan/
drwxrwxrwx 4 root other 512 Jul 25 12:35 cpanplus/
drwxrwxrwx 4 root other 512 Sep 6 2003 cyrus/
drwxrwxrwx 3 root other 512 Jun 6 16:29 dhcp/
drwxrwxrwx 3 root other 512 Apr 11 15:42 distcc/
drwxrwxrwx 3 root other 512 May 11 10:39 eggdrop/
drwxrwxrwx 3 root other 512 Apr 9 05:50 ethereal/
drwxrwxrwx 5 root other 512 Jun 8 19:12 gawk/
drwxrwxrwx 2 root other 512 May 15 08:19 gcc/
drwxrwxrwx 4 root other 512 Jul 28 2003 ircd/
drwxrwxrwx 4 root other 512 Apr 9 05:44 libpcap/
drwxrwxrwx 5 root other 512 Jul 25 13:22
mysql/
drwxrwxrwx 3 root other 512 Mar 25 13:07 nmap/
drwxrwxrwx 3 root other 512 Nov 21 2003 ogsi-lite/
drwxrwxrwx 6 root other 512 Jul 25 13:33 perl/
drwxrwxrwx 3 root other 512 Aug 19 2003
php/
drwxrwxrwx 6 root other 512 Mar 5 15:09 ppro/
drwxrwxrwx 3 root other 512 May 15 09:02 python/
drwxrwxrwx 4 root other 512 Apr 22 06:06 razor/
drwxrwxrwx 3 root other 512 Aug 24 2003 razorsdk/
drwxrwxrwx 4 root other 512 Dec 4 2003 sendmail/
drwxrwxrwx 3 root other 512 May 23 09:37 ssh/
drwxrwxrwx 4 root other 512 May 11 10:25 tcl/
drwxrwxrwx 3 root other 512 Dec 22 2003 tcpwrappers/
drwxrwxrwx 6 root other 512 Apr 24 07:13 xmltv/
您需要再在每一個目錄中創建一個或兩個結構,這取決於應用程序以及組織和配置您的單獨構建的選項。創建的每一個目錄將用來保存 live 應用程序(已配置和構建的應用程序版本)。您可以以兩種方式進行組織:使用對應每個版本的目錄,或者直接使用應用程序版本。
對應每個版本的目錄:對應於應用程序每個版本的另外一層目錄。對那些想要每一個版本創建很多不同構建配置的應用程序來說,這很實用。例如,您可能會創建一個名為 perl-5.9.0/de
bug-build 的目錄,以及另一個名為 perl-5.9.0/s
td-build 的目錄。
直接版本目錄:目錄中的每個子目錄都是原始 tarball 所創建的。如果您在所有機器上對給定的 OS 使用相同的配置,那麼您可以這樣進行組織。
根據您想如何構建和部署應用程序,可以使用任意一種結構,或者兩者都用。只是需要確保您知道每種情況下的結構,因為在開始部署時,您應該知道目錄的規劃。例如,對於 Apache,我可能要為每個版本創建三四個目錄,用來保存調試的不同配置,同時還要有一些用於
開發、階段測試(staging)和產品版本的安裝目錄。這樣得到了如清單 4 中所示的一個規劃:
清單 4. 支持不同活動配置的 Apache 規劃
./httpd-2.0.46
./httpd-2.0.46/staging-build
./httpd-2.0.46/devel-build
./httpd-2.0.46/prod-build
./httpd-2.0.49
./httpd-2.0.49/staging-build
./httpd-2.0.49/devel-build
devel-build 目錄中包含的目錄與解開原始 tarball 時創建的目錄相同。通過比較,清單 5 展示了開發機器上的 Perl 的布局,在這台機器上,Perl 的每一個版本都是以標准構建方式安裝的。從清單中可以看出,我們有了一個更簡單的結構。
清單 5. 直接版本應用程序目錄
./perl/
./perl/perl-5.8.2
./perl/perl-5.8.3
./perl/perl-5.8.5
./perl/perl-5.9.0
這些目錄都准備就緒後,您就可以開始為想要支持的每種操作系統和配置進行每個應用程序的一次構建了。對每個應用程序/配置進行一次構建後,將其部署到多個操作系統中應該是相對簡單和直觀的。實際上,您也可以簡化這一過程,只是需要進行一些深入的考慮。
配置單獨的構建 支持多種不同應用程序和不同配置的另一個問題在於,容易忘記用於給定應用程序和情形的具體配置。例如,構建 Apache 時,我指定了另一個部署目錄,以及我想要支持的模塊和組件的一個顯式列表。在第一次完成我所期望的任務時,記住這些配置沒什麼問題,但是,當三個月之後,我要再進行這個過程,並決定對最新修訂版本進行新一次構建時,讓我再回憶起該配置的某些方面無異於一個夢魇。
為了解決這一問題,我使用了只結合了一些簡單的、單行的腳本而創建的目錄結構,我通常將這些腳本中的行用於配置方面。例如,我為 Apache 階段測試
服務器(staging servers)使用了如清單 6 所示的腳本:
清單 6. Apache 階段
測試服務器的腳本
./configure --enable-so --enable-mods-shared=most --prefix=/export/httpd2/staging
您可以將這個行放入到一個腳本中,賦予其合適的名稱,並將其存放於應用程序的目錄中。此外,您既可以基於每版本使用此方法(對那些配置系統發生了變化的應用程序來說至關重要,比如從 Apache 1.3.x 到 Apache 2.x),也可將此方法用於普通的應用程序目錄。例如,我可以將這個文件命名為 apache/staging-config,以指明我可以在任何版本和構建目錄中使用它來配置 Apache 階段測試服務器。
需要根據給定的操作系統、應用程序和配置實際執行配置時,我可以如下進行:
清單 7. 執行配置和構建
$ cd redhat-linux-9.0/apache/httpd-2.0.46/staging-build
$ ../../staging-config
$ make
自動化安裝 一旦有了針對某個操作系統的應用程序的首次編譯版和准備安裝版(ready-to-install version),在網絡中的不同機器上實際發布和安裝這個應用程序就會變得非常容易。您不必再在每台機器上單獨運行配置/構建過程 —— 倘若機器是相同的。所有您需要運行的只是 make install。
通過在每個操作系統目錄中創建了一個文件,其中包含我想要在每台機器上安裝的應用程序列表,我逐個系統(system-by-system)地自動化了這一過程。對於其中一些操作系統,我甚至創建了大量不同的文件,來處理我必須進行的所有不同類型的安裝。該文件只是應用程序構建目錄的一個列表,如清單 8 所示:
清單 8. 操作系統應用程序選擇
perl/perl-5.9.0
python/Python-2.3
ccache/ccache-2.3
distcc/distcc-2.13
這個文件由清單 9 中所示的腳本處理。這裡沒有任何技巧;只需遍歷列出的每一個目錄並在其中運行 make install 命令即可。
清單 9. 自動安裝腳本
#!/bin/sh
os=$1
src=$2
currentdir=`pwd`
basedir=/export/build
if [ -z "$os" ]
then
echo "No operating system definition specified"
exit 1
fi
if [ -z "$src" ]
then
echo "No application definition specified"
exit 1
fi
cd $basedir
if [ -r "$basedir/$os/$src" ]
then
for dir in `cat $os/$src`
do
cd $basedir/$os/$dir
make install
done
else
echo "No application definition specified"
exit 1
fi
現在,要在一台機器上安裝一組特定的應用程序,所有您需要做的就是運行這個腳本,並給出操作系統文件夾和應用程序選擇文件,如清單 10 所示:
清單 10. 在一台機器上安裝一組特定的應用程序
$ appinstall.sh solaris8-x86 standard
腳本以及精心構造的目錄結構將完成其余的任務。
結束語 使用這個方法來安裝和發布應用程序,需要一些時間來進行設置和熟悉,但是,一旦開始運轉,它幾乎是自動進行的。實際上,因為您使用可以安裝哪些應用程序的信息來填充文件,所以,通過將該腳本作為 cron 作業運行,您還可以使用同一個系統來自動更新網絡上的機器。我每周運行一次我的腳本,不過您可以一個月才運行一次。對於 99% 的安裝器來說,當前版本與將要安裝的版本是否相同沒有關系。所有安裝程序要做的只是覆蓋上一次運行安裝程序時可能用到的文件的相同副本。
如果您使用這個自動化的方法,那麼將您的所有機器更新至最新將會是一件非常簡單的事,只需使用最新版本的構建目錄來更新應用程序選擇文件即可,這太棒了!您所有的機器在預定的更新過程中將安裝最新的安裝(installation)。不需要特別的腳本,也不需要使用 rsync、ssh 或者 rsh。您可以開始根據需要配置和定制您的應用程序,並允許不同的機器使用不同的應用程序設置。