天天看点

给你一篇部署文档,你能不能写一个脚本出来

给你一篇部署文档,你能不能写一个脚本出来

提醒:本文为合集文章,后续会持续更新!

关注我,持续学习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",持续提升!