誰一開始寫shell腳本不是從流水賬開始的?寫著寫著你就會發現,需要在哪里加判斷,在哪里拋出異常。寫著寫著就知道何時用函數,何時用變量。寫著寫著你就會說,shell腳本也就那么回事。
【需求】
將如下部署文檔用一個shell腳本實現。
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服務管理腳本
?
sudo vi /lib/systemd/system/nginx.service #寫入如下內容 [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)加載服務
?
sudo systemctl daemon-reload
?
8)啟動服務
?
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 "當前目錄已經存在nginx-1.23.0.tar.gz" echo "檢測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已經安裝" 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已經安裝" 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服務管理腳本" cat > /tmp/nginx.service <?
【解析】
其實腳本思路,大家也都沒啥問題,畢竟給出了文檔。有的同學,直接將文檔,改成了腳本,這沒錯啊,shell腳本就是這樣,將手動的操作改成自動。
但是,大家也要考慮,每一步執行中是否遇到問題,遇到問題了,你怎么去處理。腳本寫的好不好,就在于細節你處理是否到位,很有可能一個小細節,那就是非常大的bug。
比如,變量獲取值和我們預期不符合,然而你卻拿這個不符合預期的值進行了比較或者判斷,那最終結果肯定也會不符合我們的預期,甚至是會報錯。
腳本分成了幾個函數,其中有一個專門用來判斷上一步有沒有錯的,就是這個ck_ok 。為什么將它包裝成了函數呢,因為整個腳本里,很多地方都需要做判斷。
下載包,這里,需要判斷是否已經下載過了,而如果下載過了,還要判斷下載的包是不是我們想要的,怎么判斷呢?
用 [ -f filename ]來判斷文件是否存在,文件存在,還需要計算它的md5值來判斷是否符合我們的預期。所以,這里有一個點就是說,你必須要知道正確文件的md5值。
當然,有的官網會給出文件的正確md5。下載過,就不要重復下載了,因為下載文件不僅耗費時間還耗費帶寬。
你腳本執行過程中出現了問題可能需要反復執行多次腳本,如果不判斷是否下載過,那豈不是每次都要下載一次了。下載后,就需要安裝啦。??
安裝過程,根據文檔,其實核心就三個大的步驟:configure,make,make instal。
每一步都需要判斷是否正確執行,因為它們是環環相扣的。為了讓腳本更加完美 ,最好是每一個關鍵步驟都需要去做一個判斷。
文檔里有一步,是需要安裝依賴的。為了讓腳本更加通用,所以你最好是根據系統來判斷是使用yum還是apt來安裝對應的包。
我這里偷懶了,直接判斷是否有yum或者apt命令,但實際上這樣并不是最優的方案。最優方案是需要根據特定命令來判定系統是啥。??
比如是 CentOS,是 RHEL,還是Rocky?當然,甚至連它們的版本也要做判斷。不過話說回來,我們還不需要搞到那么那么完美。包括大家以后工作中寫腳本時,肯定是需要有一個前提的,比如,針對CentOS7寫的腳本,或者針對Rocky8寫的腳本。所以呢,腳本就不需要整那么復雜了。
說到安裝依賴,和下載包一樣 ,也需要考慮 是否已經安裝過。所以,這一步需要大家先判斷對應的包是不是已經安裝過了,安裝過就不需要再安裝。
我腳本里其實也有缺陷,比如安裝完包后沒有去檢測這個包是否安裝成功。其實,這是有必要做的,因為依賴包安裝不成功,直接影響到了能否make成功。
make 和 make instll?兩個可以合并,比如:make ?&&? make ?install。寫成一行也是可以的,最終只做一個判斷。?
install完成后,就該編輯systemd服務管理腳本里,這里有好幾個同學都有問題,大家有的使用echo有的使用?EOF這種,都可以實現。??
但是,大家忽略了一個問題,就是你echo的文本里是有$符號的。它在shell腳本里是會被當成調用變量的符號的。所以,這里需要特殊處理一下,加個?,即$,它會將$符號脫義。
再往后就是daemon-reload和start服務了,這里同樣也要做個檢測。審核編輯:湯梓紅
?
評論
查看更多