天天看點

給你一篇部署文檔,你能不能寫一個腳本出來

給你一篇部署文檔,你能不能寫一個腳本出來

提醒:本文為合集文章,後續會持續更新!

關注我,持續學習shell腳本,每日提升!

誰一開始寫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 <<EOF
[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
EOF


    sudo /bin/mv /tmp/nginx.service /lib/systemd/system/nginx.service
    ck_ok "編輯nginx.service"


    echo "加載服務"
    sudo systemctl unmask nginx.service
    sudo  systemctl daemon-reload
    sudo systemctl enable nginx
    echo "啟動Nginx"
    sudo systemctl start nginx
    ck_ok "啟動Nginx"
}


download_ng
install_ng           

【解析】

其實腳本思路,大家也都沒啥問題,畢竟給出了文檔。有的同學,直接将文檔,改成了腳本,這沒錯啊,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服務了,這裡同樣也要做個檢測。

關注"阿銘linux",持續提升!