誰一開始寫shell腳本不是從流水賬開始的?寫著寫著你就會(huì)發(fā)現(xiàn),需要在哪里加判斷,在哪里拋出異常。寫著寫著就知道何時(shí)用函數(shù),何時(shí)用變量。寫著寫著你就會(huì)說,shell腳本也就那么回事。
【需求】
將如下部署文檔用一個(gè)shell腳本實(shí)現(xiàn)。
1)下載源碼
?
cd /usr/local/src sudo curl -O http://nginx.org/download/nginx-1.23.0.tar.gz
?
2)解壓
?
sudo tar zxf nginx-1.23.0.tar.gz cd nginx-1.23.0
?
3)安裝依賴
?
## RHEL/Rocky sudo yum install -y gcc make pcre-devel zlib-devel openssl-devel ##ubuntu sudo apt install -y gcc make libpcre++-dev libssl-dev zlib1g-dev
?
4)配置
?
sudo ./configure --prefix=/usr/local/nginx --with-http_ssl_module
?
5)編譯和安裝
?
sudo make && sudo make install
?
6)編輯system服務(wù)管理腳本
?
sudo vi /lib/systemd/system/nginx.service #寫入如下內(nèi)容 [Unit] Description=nginx - high performance web server Documentation=http://nginx.org/en/docs/ After=network-online.target remote-fs.target nss-lookup.target Wants=network-online.target [Service] Type=forking PIDFile=/usr/local/nginx/logs/nginx.pid ExecStart=/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf ExecReload=/bin/sh -c "/bin/kill -s HUP $(/bin/cat /usr/local/nginx/logs/nginx.pid)" ExecStop=/bin/sh -c "/bin/kill -s TERM $(/bin/cat /usr/local/nginx/logs/nginx.pid)" [Install] WantedBy=multi-user.target
?
7)加載服務(wù)
?
sudo systemctl daemon-reload
?
8)啟動(dòng)服務(wù)
?
sudo systemctl start nginx
?
【參考腳本】
?
#!/bin/bash
ck_ok()
{
if [ $? -ne 0 ]
then
echo "$1 error."
exit 1
fi
}
download_ng()
{
cd /usr/local/src
if [ -f nginx-1.23.0.tar.gz ]
then
echo "當(dāng)前目錄已經(jīng)存在nginx-1.23.0.tar.gz"
echo "檢測(cè)md5"
ng_md5=`md5sum nginx-1.23.0.tar.gz|awk '{print $1}'`
if [ ${ng_md5} == 'e8768e388f26fb3d56a3c88055345219' ]
then
return 0
else
sudo /bin/mv nginx-1.23.0.tar.gz nginx-1.23.0.tar.gz.old
fi
????fi
sudo curl -O http://nginx.org/download/nginx-1.23.0.tar.gz
ck_ok "下載Nginx"
}
install_ng()
{
cd /usr/local/src
echo "解壓Nginx"
sudo tar zxf nginx-1.23.0.tar.gz
ck_ok "解壓Nginx"
????cd?nginx-1.23.0
echo "安裝依賴"
if which yum >/dev/null 2>&1
then
## RHEL/Rocky
for pkg in gcc make pcre-devel zlib-devel openssl-devel
do
if ! rpm -q $pkg >/dev/null 2>&1
then
sudo yum install -y $pkg
ck_ok "yum 安裝$pkg"
else
echo "$pkg已經(jīng)安裝"
fi
done
fi
if which apt >/dev/null 2>&1
then
##ubuntu
for pkg in make libpcre++-dev libssl-dev zlib1g-dev
do
if ! dpkg -l $pkg >/dev/null 2>&1
then
sudo apt install -y $pkg
ck_ok "apt 安裝$pkg"
else
echo "$pkg已經(jīng)安裝"
fi
done
fi
echo "configure Nginx"
sudo ./configure --prefix=/usr/local/nginx --with-http_ssl_module
ck_ok "Configure Nginx"
echo "編譯和安裝"
sudo make && sudo make install
ck_ok "編譯和安裝"
????echo?"編輯systemd服務(wù)管理腳本"
cat > /tmp/nginx.service <
?
【解析】
其實(shí)腳本思路,大家也都沒啥問題,畢竟給出了文檔。有的同學(xué),直接將文檔,改成了腳本,這沒錯(cuò)啊,shell腳本就是這樣,將手動(dòng)的操作改成自動(dòng)。
但是,大家也要考慮,每一步執(zhí)行中是否遇到問題,遇到問題了,你怎么去處理。腳本寫的好不好,就在于細(xì)節(jié)你處理是否到位,很有可能一個(gè)小細(xì)節(jié),那就是非常大的bug。
比如,變量獲取值和我們預(yù)期不符合,然而你卻拿這個(gè)不符合預(yù)期的值進(jìn)行了比較或者判斷,那最終結(jié)果肯定也會(huì)不符合我們的預(yù)期,甚至是會(huì)報(bào)錯(cuò)。
腳本分成了幾個(gè)函數(shù),其中有一個(gè)專門用來判斷上一步有沒有錯(cuò)的,就是這個(gè)ck_ok 。為什么將它包裝成了函數(shù)呢,因?yàn)檎麄€(gè)腳本里,很多地方都需要做判斷。
下載包,這里,需要判斷是否已經(jīng)下載過了,而如果下載過了,還要判斷下載的包是不是我們想要的,怎么判斷呢?
用 [ -f filename ]來判斷文件是否存在,文件存在,還需要計(jì)算它的md5值來判斷是否符合我們的預(yù)期。所以,這里有一個(gè)點(diǎn)就是說,你必須要知道正確文件的md5值。
當(dāng)然,有的官網(wǎng)會(huì)給出文件的正確md5。下載過,就不要重復(fù)下載了,因?yàn)橄螺d文件不僅耗費(fèi)時(shí)間還耗費(fèi)帶寬。
你腳本執(zhí)行過程中出現(xiàn)了問題可能需要反復(fù)執(zhí)行多次腳本,如果不判斷是否下載過,那豈不是每次都要下載一次了。下載后,就需要安裝啦。??
安裝過程,根據(jù)文檔,其實(shí)核心就三個(gè)大的步驟:configure,make,make instal。
每一步都需要判斷是否正確執(zhí)行,因?yàn)樗鼈兪黔h(huán)環(huán)相扣的。為了讓腳本更加完美 ,最好是每一個(gè)關(guān)鍵步驟都需要去做一個(gè)判斷。
文檔里有一步,是需要安裝依賴的。為了讓腳本更加通用,所以你最好是根據(jù)系統(tǒng)來判斷是使用yum還是apt來安裝對(duì)應(yīng)的包。
我這里偷懶了,直接判斷是否有yum或者apt命令,但實(shí)際上這樣并不是最優(yōu)的方案。最優(yōu)方案是需要根據(jù)特定命令來判定系統(tǒng)是啥。??
比如是 CentOS,是 RHEL,還是Rocky?當(dāng)然,甚至連它們的版本也要做判斷。不過話說回來,我們還不需要搞到那么那么完美。包括大家以后工作中寫腳本時(shí),肯定是需要有一個(gè)前提的,比如,針對(duì)CentOS7寫的腳本,或者針對(duì)Rocky8寫的腳本。所以呢,腳本就不需要整那么復(fù)雜了。
說到安裝依賴,和下載包一樣 ,也需要考慮 是否已經(jīng)安裝過。所以,這一步需要大家先判斷對(duì)應(yīng)的包是不是已經(jīng)安裝過了,安裝過就不需要再安裝。
我腳本里其實(shí)也有缺陷,比如安裝完包后沒有去檢測(cè)這個(gè)包是否安裝成功。其實(shí),這是有必要做的,因?yàn)橐蕾嚢惭b不成功,直接影響到了能否make成功。
make 和 make instll?兩個(gè)可以合并,比如:make ?&&? make ?install。寫成一行也是可以的,最終只做一個(gè)判斷。?
install完成后,就該編輯systemd服務(wù)管理腳本里,這里有好幾個(gè)同學(xué)都有問題,大家有的使用echo有的使用?EOF這種,都可以實(shí)現(xiàn)。??
但是,大家忽略了一個(gè)問題,就是你echo的文本里是有$符號(hào)的。它在shell腳本里是會(huì)被當(dāng)成調(diào)用變量的符號(hào)的。所以,這里需要特殊處理一下,加個(gè)?,即$,它會(huì)將$符號(hào)脫義。
再往后就是daemon-reload和start服務(wù)了,這里同樣也要做個(gè)檢測(cè)。
審核編輯:湯梓紅
?
電子發(fā)燒友App










評(píng)論