之前分享了不少脚本中的使用的小技巧,今天拿出点实打实的东西来,在我的 github https://github.com/SmartLyu/shell 里有 nginx 的一个安装配置包,还有一个关于安装 nginx 的脚本,今天就来和大家分享一下我写的nginx相关的脚本,大致分为  安装脚本、服务控制脚本、自动同步等。

先来说说安装脚本nginx_install
     大家解压我的nginx软件包就可以看到使用手册,具体的脚本如何使用就不和大家一一赘述了,我就来和大家分享一下,脚本编写的过程,和大家聊聊我是怎么写出这个脚本的,希望大家看完后能有所收益。
     里面有进度条等用于美化的操作,我就不做介绍了,我就讲讲里面的核心部分,最核心的当然就是解压编译安装了,我们用命令如何做呢,tar解压后用configure配置再是make编译最后make install进行安装,那脚本中也这么写,不过有个小问题,就是我们配置或者编译安装都需要到解压出的目录下,如何做到呢?一般压缩包命名是在被压缩的目录名后添加上应该添加的后缀 如.tar.gz,而目录命令规范中目录名中没有 . ,那么我们就可以以 . 为分隔的标识,然后进行去尾操作,这样就可以得到目录名了,这样用 ${file%%.*}就可以得到目录名了,但是这时候解压的问题来了,我怎么知道这是什么压缩的,如何分辨呢?总不能用tar解压zip压缩包吧,那我们就获取一下压缩包的后缀名判断一下好了[ ${file##*.} == 'zip' ],默认是tar包,如果是zip包再特殊处理。进入目录后就可以进行配置编译安装了,最后判断一下nginx有没有安装好,看一下目标位置下所以,基本的主框架就出来了:

file=压缩包名
nginx_path=选择nginx安装位置
w=需要nginx具备的模块
[ ${file##*.} == 'zip' ]  && unzip $file -d $path || tar -xf $file -C $path
cd ${file%.*.*}
useradd -s /sbin/nologin nginx
./configure --prefix=$nginx_path --user=nginx --group=nginx $w &>/dev/null
[ $? -ne 0 ] && echo 'configure has problem' && kill $! && exit 4
make &>/dev/null
[ $? -ne 0 ] && echo 'make has problem' && kill $! && exit 5
make install &>/dev/null
[ ! -e $nginx_path/sbin/nginx ] && echo -e "\nnginx has problem" && exit 6

     这样的脚本已经初步完成的既定的功能,不过,还有不少问题,首先,很多时候我们不是要安装nginx,有的时候是要升级,那么我们这个脚本能不能兼顾完成升级操作呢?当然是可以的,首先我们先清除,什么时候应该升级,怎么升级,先回答第一个问题,什么时候升级,答案就是当nginx已经被安装了,我们就检查一下,nginx目录下有没有基本的文件,有就说明要升级,没有就是安装,用着判断解决:[ -e $nginx_path/sbin/nginx ]  ,再看怎么升级,升级和安装唯一的区别就是最后一步,安装是make install 升级是吧原来sbin下的文件删掉,把新的复制过去即可,那就简单了,我们只需要把刚刚make install 一步改一下,即可:

if [ -e $nginx_path/sbin/nginx ];then
  rm -f $nginx_path/sbin/nginx
  cp objs/nginx $nginx_path/sbin/
else
  make install &>/dev/null
fi

     现在功能是很全面了,可以兼顾升级安装了,下面我们就要再加功能了,我们希望我们的脚本可变通更多一点,那我们就希望用户可以通过变量来控制,这时候问题来了,我们有三个类型参数,压缩包、安装位置、需要安装的模块,那么问题来了,每个都是有一定默认值的,用户不输入,我们就按默认值来,但是,我们怎么知道用户输入的是哪个类型参数呢?按照位置来肯定不行,因为加入我们第一个位置设置为压缩包,第二个是安装位置,后面都是安装模块,看似可行,可问题也很大,那就是用户必须每次都具体写清楚压缩包是什么,安装位置是哪里,安装模块是什么,默认值也就无稽之谈了,因为如果用户不写压缩包,那用户写的安装位置就被计算机当成了压缩包的位置,导致程序崩溃,这肯定是不可以的,这该怎么办呢,我们人能分出那个是哪个,那我们想办法让计算机也能分出来,具体操作其实很简单,还是按照一般算法的思维考虑,从问题出发,如何让计算机分出这参数属于什么类型,试问人是怎么分的呢?我们看到 -- 开头的就知道这是模块,不是 -- 开头的就是一个路径,有 / 开头的就是绝对路径,没有就是相对路径,而压缩包一定是 路径/包名 ,安装位置一定是一个路径,那就好办了,我们也这么让计算机判断,吧所有参数进行识别,用 for 循环吧 $* 中所有参数依次进行检测, 如果是--开头的就追加到 w 后面,反正我们配置的时候多个模块间用空格分隔,我们也这么写 w 参数即可,把多个模块写到一个参数中就是了,如果是绝对路径就判断,该参数是否代表一个文件,不是那就当做安装路径,最后就可以得到筛选审核参数的代码:

w=''
for i in $*
do
  echo $i | grep '\-\-.*' &>/dev/null
  if [ $? -eq 0 ];then
    w=$w' '$i
  else
    [ -f $i ] && a=$i && continue
    nginx_path=$i
    echo $nginx_path | grep '^/' &>/dev/null
    [ $? -ne 0 ] && nginx_path=$PWD/$nginx_path
  fi
done

     再之就是之前我blog中写的,一般脚本不单单是自己一个脚本完成的,还有其他的脚本,可能要相互协作,如果用户自定义了自己nginx的位置,而我又写了一些控制服务啊什么的脚本,这些脚本就需要修改里面的nginx安装位置,这时候就需要获取脚本所在位置,这个大家可以参考我的一个专门的blog 《获取执行的脚本所在目录的位置》--> https://blog.csdn.net/Yu1543376365/article/details/82937512
然后获取位置后,我们就可以修改我们其他的一些服务的脚本中nginx的安装位置了,用sed进行修改,具体怎么修改涉及到其他脚本的撰写,大家可以阅读我的脚本代码然后进行理解分析。

     最后还有检查yum,检查安装包是否存在等等基本操作,因为没有复杂算法,在之前的blog中都有具体赘述,就不在这里详细描绘了。


再来说说nginx的服务控制脚本
    首先我们要先了解服务控制脚本一般怎么写,一般格式是

start(){ 脚本启动 }
stop(){ 脚本关闭 }

choice=${1:-0}
case $choice in
start)
  start ;;
stop)
  stop ;;
restart)
  stop 
  start ;;
*)
  echo 'Error'
  exit 6
esac

     其中用户输入要做什么操作,一般而言,这个服务控制是一定要用户做出选择的,所以,理论上讲,我们需要在脚本开始做一次判断,然后报错,但是我没有这么做,我思考了一下,发现,用户没输入和输入不合法,都要报错,他只能输入start、stop这样的关键词,如果输入错了,我们也要报错提示他这么输入,不输入也是一样,那我们为什么不一起处理呢,我就把没输入变成输错了就是了,所以,我给输入设置了一个初始值,这初始值就是一个随便的不合法输入,然后就简化了脚本。

     然后具体如何启动关闭nginx就不详细赘述了,我来说两个问题,第一个,如何判断nginx有没有启动,第二个启动nginx必须要求80端口是空闲的,如何检查,并且释放80端口

     先解决如何判断nginx是否启动,正如大家所知道的Linux中所有的程序都是以进程的形式展现出来的,那我们检查有没有nginx这个进程即可,有就说明已经开启,反之没有开启,那命令就是
netstat -ntlup,也可以用 ss -ntlup,前者是用于rhel6的,后者是rhel7开始使用的,现在两个都还是可以用的,我们只要从中过滤nginx,如果有就说明开了,没有就说明没有开启,那就好办了。

     再看第二个问题,检查80端口很简单,用刚刚命令检索80即可,可是怎么关闭,我们都知道结束进程用命令kill或者killall ,那我们要获取80端口的进程名,怎么办呢,可以用awk,也可以用去尾法,吧进程名抠出来,port80=$(netstat -ntulp | egrep ':80\b') ;[ $? -eq 0 ] && killall ${port80##*/} 这样就好了,设置了一个path用来记录nginx的安装位置,这就和nginx_install遥相呼应了。

path=/usr/local/nginx
start(){

   # check nginx
   netstat -ntlup | grep -q nginx
   [ $? -eq 0 ] && status && exit 0

   # check httpd 
   port80=$(netstat -ntulp | egrep ':80\b')
   [ $? -eq 0 ] && killall ${port80##*/} && echo if you want to start ngix you need to stop apache , now I try to stop it || echo 'port 80 is ready'

   # 只有当apache启动了,但是关不了的时候会执行下面的命令
   [ $? -ne 0 ] && echo 'your port cannot be stopped' && exit 1

   # start nginx
   sleep 0.5
   $path/sbin/nginx

   status
}

stop(){
   # stop nginx
   netstat -ntlup | grep -q nginx
   [ $? -eq 0 ] && $path/sbin/nginx -s stop
}

choice=${1:-0}
case $choice in
start)
  start ;;
stop)
  stop ;;
restart)
  stop 
  start ;;
*)
  echo 'Error: you can try nginx_server start|stop|restart|status|virsion|test'
  exit 6
esac

 

10-05 17:20