在完成
Apache 2.2 + Tomcat 6.0 + JK 1.2安裝後,接下來便是要如何新增網站(即虛擬主機)了。
我們的設計理念是:
1.為便於管理,我們將以/var/webapps作為所有網站應用程式的起始目錄,每個網站對應到/var/webapps底下的一個和網域名稱同名的目錄(實際上是一個符號連結,連結到一個OS使用者帳號的www目錄),例如DNS名稱為www.andowson.com就對應到目錄/var/webapps/www.andowson.com,Apache和Tomcat都會將網域名稱對應到這個目錄名稱。
www.andowson.com: /var/webapps/www.andowson.com->/home/andowson/www
2.Apache使用Name-based Virtual Host方式,httpd.conf裡面的設定如下:
UseCanonicalName Off
VirtualDocumentRoot /var/webapps/%0
3.Tomcat則是透過<Host>標籤來達成Virtual Host,在此我們將appBase屬性設定為"",內層包含一個網站根目錄的設定<Context path="" docBase="webapps/www.andowson.com" />。
4.為便於維護及升級Tomcat, 我們將Tomcat分為安裝目錄(放程式)及設定目錄(放資料),安裝目錄在/var下,如/var/apache-tomcat-6.0.18,我們建立一個符號連結/var/tomcat6來指向它,日後如更新版本,便只需將此符號連結指向新的安裝目錄即可。
設定目錄在/var/robust目錄下,如需要執行多部Tomcat(為日後做Cluster準備),我們可建立多個worker目錄在/var/robust目錄下,在每個worker目錄下建立conf, logs, temp, work目錄,及一個webapps的符號連結指向/var/webapps。如此一來,/var/robust/worker1/webapps及/var/robust/worker2/webapps下的內容和/var/webapps下的內容是相同的,也就是說我們只需在/var/webapps下新增新的網域名稱,每個worker就都可以存取到同樣一份的內容了。分成安裝目錄及設定目錄兩個不同路徑的好處是,日後,升級Tomcat版本時,只需將/var/tomcat6的符號連結指向新的安裝目錄,如/var/apache-tomcat-6.0.20即可,便不需要去搬移/var/apache-tomcat-6.0.18/webapps的內容。
/var/tomcat6->/var/apache-tomcat-6.0.18
/var/robust/worker1/webapps->/var/webapps
/var/robust/worker2/webapps->/var/webapps
5.接著我們讓網站的實際內容對應到一個OS使用者家目錄下的www目錄,即
/var/webapps/www.andowson.com->/home/andowson/www,
故新增一個網站時,需要新增一個OS使用者帳號,並設定好一個符號連結到該使用者的www目錄下。如果該網站有多個網址,我們只需要再多建立幾個符號連結即可,例如用andowson.com也要可以連到和www.andowson.com的內容。
andowson.com: /var/webapps/andowson.com->/home/andowson/www
6.為了安全起見,我們讓虛擬主機的使用者帳號只能透過FTP連進來更新檔案,不能透過SSH登入進來,我們可以將使用者帳號設定為/sbin/nologin。另外我們可以將該使用者帳號的群組指定為tomcat,以便Tomcat可以順利讀取該使用者目錄下的檔案。
7.為便於網站的開發和除錯,我們需要觀看網站的記錄檔,這點可以透過設定log4j將屬於該虛擬主機的記錄檔寫到其相對應的OS使用者家目錄下的logs目錄(如/home/andowson/logs)來。如果要讓使用者也可以看到網站的存取紀錄,我們可以將Tomcat的access log的目錄也指定到/home/andowson/logs下。這裡需將/home/andowson/logs設定為tomcat群組可以寫入的權限。
8.因為每次建立使用者時都需要新增www和logs的目錄,故我們可以透過在/etc/skel的目錄下建立好www和logs目錄來自動完成這個動作,我們也順便在www目錄下放一個index.html檔案作為網站的預設首頁,內容可以簡單的輸入Under construction或建置中等文字。
mkdir /etc/skel/www
mkdir /etc/skel/logs
echo "Under construction" > /etc/skel/www/index.html
9.[Optional]如果需要流量統計時,可以在新增站台時同時設定好AWStats的流量統計設定檔
新增站台
除了手動去編輯server.xml檔外,為便於動態新增站台,我們可將Tomcat的server.xml拆開成三個檔案,server.header, server.host, server.footer,存放於每個worker目錄下的conf目錄中。拆的方式主要是將第一個<Host>到最後一個</Host>的部分切割出來成為server.host,在第一個<Host>之前的部分就變成server.header,在最後一個</Host>之後的部分就變成server.footer了。接下來我們設計一個新增站台的template檔,透過取代變數的方式,將這個template檔的內容取代後合併回去到server.host,然後再將server.header, server.host, server.footer合併為server.xml。
這個template檔我們取名為server.newhost,內容如下:
<Host name="yourdomain" appBase=""
unpackWARs="true" autoDeploy="true">
<Valve className="org.apache.catalina.valves.AccessLogValve"
directory="/home/username/logs" prefix="yourdomain_access_log." suffix=".txt"
pattern="combined" resolveHosts="false"/>
<Context path="" docBase="webapps/yourdomain" reloadable="false" />
</Host>
針對網站記錄檔的template我們取名為log4.newhost,內容如下:
# VH begin: yourdomain
log4j.appender.username=org.apache.log4j.RollingFileAppender
log4j.appender.username.File=/home/username/logs/tomcat.log
log4j.appender.username.MaxFileSize=10MB
log4j.appender.username.MaxBackupIndex=10
log4j.appender.username.layout=org.apache.log4j.PatternLayout
log4j.appender.username.layout.ConversionPattern=%d - %5p (%C:%L) - %m%n
log4j.logger.org.apache.catalina.core.ContainerBase.[Catalina].[yourdomain]=INFO, username
log4j.additivity.org.apache.catalina.core.ContainerBase.[Catalina].[yourdomain]=false
# VH end: yourdomain
新增站台shell script的檔就很簡單了,只需要傳入三個參數(使用者名稱,密碼,網域名稱)就會自動建立一個網站出來
newsite.sh:
#!/bin/bash
# Name: Tomcat newsite.sh
# Author: Andowson Chang (andowson [at] gmail [dot] com)
# Version: 1.5
# Last Modified: 2009-03-29
CATALINA_HOME=/var/tomcat6
WORKER_ROOT="/var/robust"
WORKER_LIST=( worker1 worker2 )
username=$1
password=$2
yourdomain=$3
useradd -s /sbin/nologin -g tomcat ${username}
echo "${username}:${password}" | chpasswd
ln -s /home/${username}/www /var/webapps/${yourdomain}
chmod 755 /home/${username}
mkdir /home/${username}/logs
chmod 775 /home/${username}/logs
# for Tomcat5
#sed -e "s/yourdomain/${yourdomain}/g" -e "s/username/${username}/g" /root/newsite/log4j.newhost >> ${CATALINA_HOME}/common/classes/log4j.properties
# for Tomcat6
sed -e "s/yourdomain/${yourdomain}/g" -e "s/username/${username}/g" /root/newsite/log4j.newhost >> ${CATALINA_HOME}/lib/log4j.properties
for (( i = 0 ; i < ${#WORKER_LIST[@]} ; i++ ))
do
mkdir -p ${WORKER_ROOT}/${WORKER_LIST[i]}/conf/Catalina/${yourdomain}
# for Tomcat5
#cp -rf ${CATALINA_HOME}/server/webapps/manager/manager.xml ${WORKER_ROOT}/${WORKER_LIST[i]}/conf/Catalina/${yourdomain}/.
# for Tomcat6
cp -rf ${CATALINA_HOME}/webapps/host-manager/manager.xml ${WORKER_ROOT}/${WORKER_LIST[i]}/conf/Catalina/${yourdomain}/.
sed -e "s/yourdomain/${yourdomain}/g" -e "s/username/${username}/g" /root/newsite/server.newhost >> ${WORKER_ROOT}/${WORKER_LIST[i]}/conf/server.host
cd ${WORKER_ROOT}/${WORKER_LIST[i]}/conf
cat server.header server.host server.footer > server.xml
done
sed -e "s/yourdomain/${yourdomain}/g" /root/newsite/awstats.newhost > /etc/awstats/awstats.${yourdomain}.conf
注意:
1.使用前,請先將server.newhost, log4j.newhost, awstats.newhost及newsite.sh下載後存到/root/newsite目錄下,將newsite.sh設定為可執行,如果是使用Tomcat5.5的人,需自行相改對應的部分。
執行範例:
./newsite.sh andowson password www.andowson.com
2.如果遇到有多個網域名稱的狀況,就需要手動修改server.host加上Alias設定,然後再合併一次server.header, server.host, server.footer,產生server.xml,並手動建立第二個以上的域名的symbolic link。例如,假設還有一個網址andowson.com也要連到www.andowson.com:
ln -s /home/andowson/www /var/webapps/andowson.com
刪除站台
刪除網站則需要將我們先前產生的目錄或檔案回復原狀,主要就是刪除掉使用者目錄,worker內的目錄及server.xml中的設定。
使用刪除站台的shell script也是很簡單只需要輸入兩個參數(使用者名稱,網域名稱),即可
delsite.sh:
#!/bin/bash
# Name: Tomcat delsite.sh
# Author: Andowson Chang (andowson [at] gmail [dot] com)
# Version: 1.2
# Last Modified: 2009-03-29
CATALINA_HOME=/var/tomcat6
WORKER_ROOT="/var/robust"
WORKER_LIST=( worker1 worker2 )
username=$1
yourdomain=$2
userdel -r ${username}
rm -rf /var/webapps/${yourdomain}
# for Tomcat5
#sed -i -e "s/${yourdomain}/yourdomain/g" -e '/# VH begin: yourdomain/,/end: yourdomain>/d' ${CATALINA_HOME}/common/classes/log4j.properties
# for Tomcat6
sed -i -e "s/${yourdomain}/yourdomain/g" -e '/# VH begin: yourdomain/,/end: yourdomain>/d' ${CATALINA_HOME}/lib/log4j.properties
for (( i = 0 ; i < ${#WORKER_LIST[@]} ; i++ ))
do
rm -rf ${WORKER_ROOT}/${WORKER_LIST[i]}/conf/Catalina/${yourdomain}
#sed -i '/<Host name="${yourdomain}"/,/Host>/d' ${WORKER_ROOT}/${WORKER_LIST[i]}/conf/server.host
sed -i -e "s/${yourdomain}/yourdomain/g" -e '/<Host name="yourdomain"/,/Host>/d' ${WORKER_ROOT}/${WORKER_LIST[i]}/conf/server.host
cd ${WORKER_ROOT}/${WORKER_LIST[i]}/conf
cat server.header server.host server.footer > server.xml
done
rm -rf /etc/awstats/awstats.${yourdomain}.conf
注意:
1.使用範例:
./delsite.sh andowson www.andowson.com
2.由於sed無法直接刪除<Host="${yourdomain}">到</Host>這樣的變動的pattern,但固定的pattern卻可以。故我改成先將原來的${yourdomain}替換成yourdomain,再將它刪除。
3.刪除一個站台後會留下一行空行,如果覺得礙眼,日後可以找時間再一次手動刪除。
4.如果遇到有多域名的狀況,就需要手動刪除第二個以上的域名的symbolic link。
rm -rf /var/webapps/andowson.com
記得:修改完server.xml均需要重新啟動Tomcat才會生效!
service tomcat restart
我們可以寫個自動偵測Tomcat設定檔有沒有變動內容的shell script掛在cron來自動完成這個任務,例如我們每15分鐘檢查一次:
tomcat_conf_check.sh:
#!/bin/bash
RETVAL=0
WORKER_ROOT=/var/robust
CONF_CHANGED=`find ${WORKER_ROOT}/worker1/conf/*.xml -mmin -15 | grep -v tomcat-users.xml | wc -l`
if [ $CONF_CHANGED != 0 ]; then
echo "Tomcat restart began at `date`"
/etc/init.d/tomcat restart
echo "Tomcat restart ended at `date`"
fi
exit $RETVAL
chmod 755 /root/newsite/tomcat_conf_check.sh
然後在/etc/crontab中設定:
# check Tomcat config change and restart (2009.04.29)
*/15 * * * * root /root/newsite/tomcat_conf_check.sh >>/var/log/tomcat_conf_check.log
參考資料:
http://tomcat.apache.org/tomcat-6.0-doc/virtual-hosting-howto.html
http://tomcat.apache.org/tomcat-6.0-doc/logging.html