4. 生产环境下的Shell脚本

4.1. 1.生产环境下的备份类脚本

4.1.1. 1.1 版本控制软件SVN的代码库的备份脚本

#!/bin/sh
SVNDIR=/data/svn
SVNADMIN=/usr/bin/svnadmin
DATE=`date +%Y-%m-%d`
OLDDATE=`date +%Y-%m-%d -d '30 days'`
BACKDIR=/data/backup/svn-backup

[ -d ${BACKDIR} ] || mkdir -p ${BACKDIR}
LogFile=${BACKDIR}/svnbak.log
[ -f ${LogFile} ] || touch ${LogFile}
mkdir ${BACKDIR}/${DATE}


for PROJECT in myproject official analysis mypharma
do
  cd $SVNDIR
  $SVNADMIN hotcopy $PROJECT  $BACKDIR/$DATE/$PROJECT --clean-logs
  cd $BACKDIR/$DATE
  tar zcvf ${PROJECT}_svn_${DATE}.tar.gz $PROJECT  > /dev/null
  rm -rf $PROJECT
sleep 2
done

HOST=192.168.2.112
FTP_USERNAME=svn
FTP_PASSWORD=svn101

cd ${BACKDIR}/${DATE}

ftp -i -n -v << !
open ${HOST}
user ${FTP_USERNAME} ${FTP_PASSWORD}
bin
cd ${OLDDATE}
mdelete *
cd ..
rmdir ${OLDDATE}
mkdir ${DATE}
cd ${DATE}
mput *
bye
!

4.1.2. 1.2 Mysql数据库备份至S3文件系统

#!/bin/bash
#
# Filename:
# backupdatabase.sh
# Description:
# backup cms database and remove backup data before 7 days
# crontab
# 55 23 * * * /bin/sh /yundisk/cms/crontab/backupdatabase.sh >> /yundisk/cms/crontab/backupdatabase.log 2>&1

DATE=`date +%Y-%m-%d`
OLDDATE=`date +%Y-%m-%d -d '-7 days'`

#MYSQL=/usr/local/mysql/bin/mysql
#MYSQLDUMP=/usr/local/mysql/bin/mysqldump
#MYSQLADMIN=/usr/local/mysql/bin/mysqladmin

BACKDIR=/yundisk/cms/database
[ -d ${BACKDIR} ] || mkdir -p ${BACKDIR}
[ -d ${BACKDIR}/${DATE} ] || mkdir ${BACKDIR}/${DATE}
[ ! -d ${BACKDIR}/${OLDDATE} ] || rm -rf ${BACKDIR}/${OLDDATE}

mysqldump --default-character-set=utf8 --no-autocommit --quick --hex-blob --single-transaction -uroot  cms_production  | gzip > ${BACKDIR}/${DATE}/cms-backup-${DATE}.sql.gz
echo "Database cms_production and bbs has been backup successful"
/bin/sleep 5

aws s3 cp ${BACKDIR}/${DATE}/* s3://example-share/cms/databackup/

4.2. 2.生产环境下的统计类脚本

4.2.1. 2.1 统计设备资产明细脚本

#!/bin/bash

#####get cpu info#####
cpu_num=`cat /proc/cpuinfo| grep "physical id"| sort| uniq| wc -l`
cpu_sum=`cat /proc/cpuinfo |grep processor |wc -l`
cpu_hz=`cat /proc/cpuinfo |grep 'model name' |uniq -c |awk '{print $NF}'`

#####get mem info#####
mem_m=0
for i in `dmidecode -t memory |grep Size: |grep -v "No Module Installed" |awk '{print $2}'`
do
    mem_m=`expr $mem_m + $i`
done
mem_sum=`echo $mem_m / 1024 | bc`

#####get nic info#####
qian_num=`lspci |grep Ethernet |egrep -v '10-Gigabit|10 Gigabit' |wc -l`
wan_num=`lspci |grep Ethernet |egrep  '10-Gigabit|10 Gigabit' |wc -l`

#####get disk num#####
B=`date +%s`
ssd_num=0=
sata_num=0
for i in `lsblk |grep "disk"|awk '{print $1}'|egrep -v "ram"|sort`;
do
    code=`cat /sys/block/$i/queue/rotational`
    if [ "$code" = "0" ];then
       ssd_num=`expr $ssd_num + 1` && echo $i >>/tmp/$B.ssd
    else
       sata_num=`expr $sata_num + 1` && echo $i >>/tmp/$B.sata
    fi
done

#####get disk sum#####
C=`date +%N`
ssd_sum=0
sata_sum=0
if [ -f /tmp/$B.ssd ];then
    for n in `cat /tmp/$B.ssd`;do
        fdisk -l /dev/$n >>/tmp/$C.ssd 2>&1
        for x in `grep "Disk /dev" /tmp/$C.ssd |awk '{print $3}'`;do
            u=`echo $x / 1|bc`
        done
     ssd_sum=`expr $ssd_sum + $u + 1`
    done
fi

for m in `cat /tmp/$B.sata`;do
   fdisk -l /dev/$m >>/tmp/$C.sata 2>&1
   for y in `grep "Disk /dev" /tmp/$C.sata |awk '{print $3}'`;do
      v=`echo $y / 1|bc`
   done
   sata_sum=`expr $sata_sum + $v + 1`
done

#####show dev info#####
echo -n "$ip `hostname` $plat $pop $prov "
echo -n "CPU(物理核数,逻辑核数,频率): $cpu_num $cpu_sum $cpu_hz "
echo -n "内存(GB): $mem_sum "
echo -n "网卡数量(千兆,万兆): $qian_num $wan_num "
echo "SSD数量: ${ssd_num} SSD容量: ${ssd_sum}GB SATA数量: ${sata_num} SATA容量 ${sata_sum}GB "

4.2.2. 2.2 统计重要业务程序是否正常运行

#!/bin/bash
sync_redis_status=`ps aux | grep sync_redis.py | grep -v grep | wc -l `
if [ ${sync_redis_status} != 1 ]; then
    echo "Critical! sync_redis is Died"
    exit 2
else
    echo "OK! sync_redis is Alive"
    exit 0
fi

4.2.3. 2.3 统计机器的IP连接数

#!/bin/bash
#脚本的$1和$2报警阀值可以根据业务的实际情况调整。
#$1 = 15000,$2 = 20000
ip_conns=`netstat -an | grep tcp | grep EST | wc -l`
messages=`netstat -ant | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'|tr -s '\n' ',' | sed -r 's/(.*),/\1\n/g' `

if [ $ip_conns -lt $1 ]
then
    echo "$messages,OK -connect counts is $ip_conns"
    exit 0
fi
if [ $ip_conns -gt $1 -a $ip_conns -lt $2 ]
then
    echo "$messages,Warning -connect counts is $ip_conns"
    exit 1
fi
if [ $ip_conns -gt $2 ]
then
    echo "$messages,Critical -connect counts is $ip_conns"
    exit 2
fi

4.3. 3.生产环境下的监控类脚本

4.3.1. 3.1 在Nginx负载均衡器上监控Nginx进程的脚本

#!/bin/bash
while :
do
 nginxpid=`ps -C nginx --no-header | wc -l`
 if [ $nginxpid -eq 0 ];then
    ulimit -SHn 65535
    /usr/local/nginx/sbin/nginx
    sleep 5
   if [ $nginxpid -eq 0 ];then
     /etc/init.d/keepalived stop
   fi
 fi
 sleep 5
done

4.3.2. 3.2 系统文件数打开监控脚本

#!/bin/bash
for pid in `ps aux |grep nginx |grep -v grep|awk '{print $2}'`
do
cat /proc/${pid}/limits | grep 'Max open files'
done

4.3.3. 3.3 监控机器CPU利用率脚本

#!/bin/bash
# CPU Utilization Statistics plugin for Nagios
#
# USAGE     :   ./check_cpu_utili.sh [-w <user,system,iowait>] [-c <user,system,iowait>] ( [ -i <intervals in second> ] [ -n <report number> ])
#
# Exemple: ./check_cpu_utili.sh
#          ./check_cpu_utili.sh -w 70,40,30 -c 90,60,40
#          ./check_cpu_utili.sh -w 70,40,30 -c 90,60,40 -i 3 -n 5
# Paths to commands used in this script.  These may have to be modified to match your system setup.
IOSTAT="/usr/bin/iostat"

# Nagios return codes
STATE_OK=0
STATE_WARNING=1
STATE_CRITICAL=2
STATE_UNKNOWN=3

# Plugin parameters value if not define
LIST_WARNING_THRESHOLD="70,40,30"
LIST_CRITICAL_THRESHOLD="90,60,40"
INTERVAL_SEC=1
NUM_REPORT=1
# Plugin variable description
PROGNAME=$(basename $0)

if [ ! -x $IOSTAT ]; then
    echo "UNKNOWN: iostat not found or is not executable by the nagios user."
    exit $STATE_UNKNOWN
fi

print_usage() {
        echo ""
        echo "$PROGNAME $RELEASE - CPU Utilization check script for Nagios"
        echo ""
        echo "Usage: check_cpu_utili.sh -w -c (-i -n)"
        echo ""
        echo "  -w  Warning threshold in % for warn_user,warn_system,warn_iowait CPU (default : 70,40,30)"
        echo "  Exit with WARNING status if cpu exceeds warn_n"
        echo "  -c  Critical threshold in % for crit_user,crit_system,crit_iowait CPU (default : 90,60,40)"
        echo "  Exit with CRITICAL status if cpu exceeds crit_n"
        echo "  -i  Interval in seconds for iostat (default : 1)"
        echo "  -n  Number report for iostat (default : 3)"
        echo "  -h  Show this page"
        echo ""
    echo "Usage: $PROGNAME"
    echo "Usage: $PROGNAME --help"
    echo ""
    exit 0
}

print_help() {
    print_usage
        echo ""
        echo "This plugin will check cpu utilization (user,system,CPU_Iowait in %)"
        echo ""
    exit 0
}

# Parse parameters
while [ $# -gt 0 ]; do
    case "$1" in
        -h | --help)
            print_help
            exit $STATE_OK
            ;;
        -v | --version)
                print_release
                exit $STATE_OK
                ;;
        -w | --warning)
                shift
                LIST_WARNING_THRESHOLD=$1
                ;;
        -c | --critical)
               shift
                LIST_CRITICAL_THRESHOLD=$1
                ;;
        -i | --interval)
               shift
               INTERVAL_SEC=$1
                ;;
        -n | --number)
               shift
               NUM_REPORT=$1
                ;;
        *)  echo "Unknown argument: $1"
            print_usage
            exit $STATE_UNKNOWN
            ;;
        esac
shift
done

# List to Table for warning threshold (compatibility with
TAB_WARNING_THRESHOLD=(`echo $LIST_WARNING_THRESHOLD | sed 's/,/ /g'`)
if [ "${#TAB_WARNING_THRESHOLD[@]}" -ne "3" ]; then
  echo "ERROR : Bad count parameter in Warning Threshold"
  exit $STATE_WARNING
else
USER_WARNING_THRESHOLD=`echo ${TAB_WARNING_THRESHOLD[0]}`
SYSTEM_WARNING_THRESHOLD=`echo ${TAB_WARNING_THRESHOLD[1]}`
IOWAIT_WARNING_THRESHOLD=`echo ${TAB_WARNING_THRESHOLD[2]}`
fi

# List to Table for critical threshold
TAB_CRITICAL_THRESHOLD=(`echo $LIST_CRITICAL_THRESHOLD | sed 's/,/ /g'`)
if [ "${#TAB_CRITICAL_THRESHOLD[@]}" -ne "3" ]; then
  echo "ERROR : Bad count parameter in CRITICAL Threshold"
  exit $STATE_WARNING
else
USER_CRITICAL_THRESHOLD=`echo ${TAB_CRITICAL_THRESHOLD[0]}`
SYSTEM_CRITICAL_THRESHOLD=`echo ${TAB_CRITICAL_THRESHOLD[1]}`
IOWAIT_CRITICAL_THRESHOLD=`echo ${TAB_CRITICAL_THRESHOLD[2]}`
fi

if [ ${TAB_WARNING_THRESHOLD[0]} -ge ${TAB_CRITICAL_THRESHOLD[0]} -o ${TAB_WARNING_THRESHOLD[1]} -ge ${TAB_CRITICAL_THRESHOLD[1]} -o ${TAB_WARNING_THRESHOLD[2]} -ge ${TAB_CRITICAL_THRESHOLD[2]} ]; then
  echo "ERROR : Critical CPU Threshold lower as Warning CPU Threshold "
  exit $STATE_WARNING
fi

CPU_REPORT=`iostat -c $INTERVAL_SEC $NUM_REPORT | sed -e 's/,/./g' | tr -s ' ' ';' | sed '/^$/d' | tail -1`
CPU_REPORT_SECTIONS=`echo ${CPU_REPORT} | grep ';' -o | wc -l`
CPU_USER=`echo $CPU_REPORT | cut -d ";" -f 2`
CPU_SYSTEM=`echo $CPU_REPORT | cut -d ";" -f 4`
CPU_IOWAIT=`echo $CPU_REPORT | cut -d ";" -f 5`
CPU_STEAL=`echo $CPU_REPORT | cut -d ";" -f 6`
CPU_IDLE=`echo $CPU_REPORT | cut -d ";" -f 7`
NAGIOS_STATUS="user=${CPU_USER}%,system=${CPU_SYSTEM}%,iowait=${CPU_IOWAIT}%,idle=${CPU_IDLE}%"
NAGIOS_DATA="CpuUser=${CPU_USER};${TAB_WARNING_THRESHOLD[0]};${TAB_CRITICAL_THRESHOLD[0]};0"

CPU_USER_MAJOR=`echo $CPU_USER| cut -d "." -f 1`
CPU_SYSTEM_MAJOR=`echo $CPU_SYSTEM | cut -d "." -f 1`
CPU_IOWAIT_MAJOR=`echo $CPU_IOWAIT | cut -d "." -f 1`
CPU_IDLE_MAJOR=`echo $CPU_IDLE | cut -d "." -f 1`



# Return
if [ ${CPU_USER_MAJOR} -ge $USER_CRITICAL_THRESHOLD ]; then
        echo "CPU STATISTICS OK:${NAGIOS_STATUS} | CPU_USER=${CPU_USER}%;70;90;0;100"
        exit $STATE_CRITICAL
    elif [ ${CPU_SYSTEM_MAJOR} -ge $SYSTEM_CRITICAL_THRESHOLD ]; then
        echo "CPU STATISTICS OK:${NAGIOS_STATUS} | CPU_USER=${CPU_USER}%;70;90;0;100"
        exit $STATE_CRITICAL
    elif [ ${CPU_IOWAIT_MAJOR} -ge $IOWAIT_CRITICAL_THRESHOLD ]; then
        echo "CPU STATISTICS OK:${NAGIOS_STATUS} | CPU_USER=${CPU_USER}%;70;90;0;100"
        exit $STATE_CRITICAL
    elif [ ${CPU_USER_MAJOR} -ge $USER_WARNING_THRESHOLD ] && [ ${CPU_USER_MAJOR} -lt $USER_CRITICAL_THRESHOLD ]; then
        echo "CPU STATISTICS OK:${NAGIOS_STATUS} | CPU_USER=${CPU_USER}%;70;90;0;100"
        exit $STATE_WARNING
      elif [ ${CPU_SYSTEM_MAJOR} -ge $SYSTEM_WARNING_THRESHOLD ] && [ ${CPU_SYSTEM_MAJOR} -lt $SYSTEM_CRITICAL_THRESHOLD ]; then
        echo "CPU STATISTICS OK:${NAGIOS_STATUS} | CPU_USER=${CPU_USER}%;70;90;0;100"
        exit $STATE_WARNING
      elif  [ ${CPU_IOWAIT_MAJOR} -ge $IOWAIT_WARNING_THRESHOLD ] && [ ${CPU_IOWAIT_MAJOR} -lt $IOWAIT_CRITICAL_THRESHOLD ]; then
        echo "CPU STATISTICS OK:${NAGIOS_STATUS} | CPU_USER=${CPU_USER}%;70;90;0;100"
        exit $STATE_WARNING
else

        echo "CPU STATISTICS OK:${NAGIOS_STATUS} | CPU_USER=${CPU_USER}%;70;90;0;100"
        exit $STATE_OK
fi

4.4. 4. 生产环境下运维开发类脚本

4.4.1. 4.1 系统初始化脚本

系统初始化脚本用于新装Linux的相关配置工作,

比如禁掉iptables和SELinux及IPv6、优化系统内核、停掉一些没必要启动的系统服务等。

我们将系统初始化脚本应用于公司内部的运维开发机器的批量部署(比如用Ansible来下发)上。事实上,复杂的系统业务初始化initial脚本由于涉及了多条产品线和多个业务平台,因此远比这里列出的开发环境下的初始化脚本复杂得多,而且其代码量也极大,基本上都是6000~7000行的Shell脚本,各功能模块以函数的形式进行封装。下面的脚本只是涉及一些基础部分,希望大家注意这点。脚本代码如下所示(此脚本已在CentOS 6.8 x86_x64下测试通过):

#!/bin/bash

#添加epel外部yum扩展源
cd /usr/local/src
wget http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
rpm -ivh epel-release-6-8.noarch.rpm

#安装gcc基础库文件以及sysstat工具
yum -y install gcc gcc-c++ vim-enhanced unzip unrar sysstat

#配置ntpdate自动对时
yum -y install ntp
echo "01 01 * * * /usr/sbin/ntpdate ntp.api.bz    >> /dev/null 2>&1" >> /etc/crontab
ntpdate ntp.api.bz
service crond restart

#配置文件的ulimit值
ulimit -SHn 65535
echo "ulimit -SHn 65535" >> /etc/rc.local
cat >> /etc/security/limits.conf << EOF
*                     soft     nofile             65535
*                     hard     nofile             65535
EOF

#基础系统内核优化
cat >> /etc/sysctl.conf << EOF
fs.file-max=419430
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_syn_retries = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 1
net.ipv4.tcp_keepalive_time = 1200
net.ipv4.ip_local_port_range = 1024 65535
net.ipv4.tcp_max_syn_backlog = 16384
net.ipv4.tcp_max_tw_buckets = 36000
net.ipv4.route.gc_timeout = 100
net.ipv4.tcp_syn_retries = 1
net.ipv4.tcp_synack_retries = 1
net.core.somaxconn = 16384
net.core.netdev_max_backlog = 16384
net.ipv4.tcp_max_orphans = 16384
EOF
/sbin/sysctl -p

#禁用control-alt-delete组合键以防止误操作
sed -i 's@ca::ctrlaltdel:/sbin/shutdown -t3 -r now@#ca::ctrlaltdel:/sbin/shutdown -t3 -r now@' /etc/inittab

#关闭SELinux
sed -i 's@SELINUX=enforcing@SELINUX=disabled@' /etc/selinux/config

#关闭iptables
service iptables stop
chkconfig iptables off

#ssh服务配置优化,请至少保持机器中至少有一个具有sudo权限的用户,下面的配置会禁止root远程登录
sed -i 's@#PermitRootLogin yes@PermitRootLogin no@' /etc/ssh/sshd_config #禁止root远程登录
sed -i 's@#PermitEmptyPasswords no@PermitEmptyPasswords no@' /etc/ssh/sshd_config #禁止空密码登录
sed -i 's@#UseDNS yes@UseDNS no@' /etc/ssh/sshd_config /etc/ssh/sshd_config
service sshd restart

#禁用IPv6地址
echo "alias net-pf-10 off" >> /etc/modprobe.d/dist.conf
echo "alias ipv6 off" >> /etc/modprobe.d/dist.conf
chkconfig ip6tables off

#vim基础语法优化
echo "syntax on" >> /root/.vimrc
echo "set nohlsearch" >> /root/.vimrc

#精简开机自启动服务,安装最小化服务的机器初始可以只保留crond,network,rsyslog,sshd这四个服务。
for i in `chkconfig --list|grep 3:on|awk '{print $1}'`;do chkconfig --level 3 $i off;done
for CURSRV  in crond rsyslog sshd network;do chkconfig --level 3 $CURSRV on;done

#重启服务器
reboot

4.4.2. 4.2 控制shell多进程数量的脚本

下面的run.py是爬虫程序,经测试,在机器上运行8个run.py进程是机器性能最好的时候,该进程数量既能充分发挥机器的性能又不会导致机器响度速度过慢。

而且有时为了避免并发进程数过多导致机器卡死,需要限制并发的数量。下面的脚本可以实现这个需求,其代码如下所示:

#!/usr/bin/env bash
#usage:xxx
#scripts_name:${NAME}.sh
# author:xiaojian

CE_HOME="/data/ContentEnginne"
LOG_PATH="/data/logs"

# 控制爬虫数量为8
MAX_SPIDER_COUNT=8

count=`ps -ef|grep -v grep|grep run.py|wc -l`
try_time=0

cd $CE_HOME

# 限制并发的数量
while [ $count -lt $MAX_SPIDER_COUNT -a $try_time -lt $MAX_SPIDER_COUNT ]; do
    let try_time +=1
    python run.py >> ${LOG_PATH}/spider.log 2>&1 &
    count=`ps -ef|grep -v grep|grep run.py|wc -l`
done

4.4.3. 4.3 调用Ansible来分发多条线路的配置

Ansible的hosts文件内容如下,举例IP,真实IP已被隐藏

[yd]
1.1.1.1
2.2.2.2

[wt]
3.3.3.3
4.4.4.4

[dx]
5.5.5.5
6.6.6.6

publishconf.sh部分内容如下

#!/bin/bash

#如果hosts文件不存在,就调用touch命令建立;另外,这里要增加一个逻辑判断,即如果已经有人在发布平台了,第二个运维人员发布的时候,一定要强制退出,等待前面的发布人员发布结束。
if [ ! -f "$hosts" ]
then
    touch "$hosts"
else
    echo "此平台已经有运维小伙伴在发布,请耐心等待!"
    exit
fi

#如果出现中止进程的情况,捕捉异常信号,清理临时文件。
trap "echo '程序被中止,开始清理临时文件';rm -rf $hosts;exit" 1 2 3
#进入public_conf目录,通过git pull获取gitlab上最新的相关文件配置

cd /data/conf /public_conf/
git pull origin master:master

#配置文件这里也是通过内部的GitLab管理,这里没简化操作,主要是防止执行git pull origin master或git pull的时候,此时可能会存在着多分支的情况会导致运行报错
if [ $? == 0 ];then
    echo "当前配置文件为最新版本,可以发布!"
else
    echo "当前配置文件不是最新的,请检查后再发布"
    exit
fi

#此为发布单平台多IP的逻辑,$#判断参数个数,这里的逻辑判断为参数大于或等于3时就是单平台多IP发布。
if [ $# >=3 ];then
  shift 1
  这里通过shift命令往左偏移一个位置参数,从而获取全部的IP。
  echo "此次需要更新的机器IP为:$@"
  for flat in $@
  do
  echo "此次需要更新的机器IP为:$flat"
  platform=`awk '/\[/{a=$0}/'"$flat"'/{print a}' $hosts | head -n1`
    #通过这段awk命令组和来获取当前的机器ip属于哪条线路,比如是移动还是网通或者电信,后续有相应的措施。


  if  [[ $platform =~ "yd" ]];then
    /usr/local/bin/ansible -i $hosts $flat -m shell -a "/home/fastcache_conf/publish_fastcache.sh ${public_conf}_yd"
    elif  [[ $platform =~ "wt" ]];then
    /usr/local/bin/ansible -i $hosts $flat -m shell -a "/home/fastcache_conf/publish_fastcache.sh ${public_conf}_wt"
    else
    /usr/local/bin/ansible -i $hosts $flat -m shell -a "/home/fastcache_conf/publish_fastcache.sh ${public_conf}_dx"
  fi
  done
fi

#程序正常运行后,也要清理此临时文件,方便下次任务发布
rm -rf $hosts
trap "rm -rf $hosts" exit

4.4.4. 4.4 手动建立软Raid级别需求

#!/bin/bash
function rg_mkfs_interac() {
    read -p "请输入您要做的RAID级别,可选择项为0|1|5|10:" raid
    read -p "请输入哪些磁盘需要并进RAID,磁盘之间请用空格格开,例如sdb sdc等" mydev
    echo $raid
    echo $mydev
    # create md0
        rg_info "Create RAID..."
        mdadm -Ss
        yes | mdadm -C /dev/md0 --level=$raid --auto=yes $mydev >/dev/null
        mdadm -D /dev/md0 >/dev/null || rg_info 58 "Create RAID /dev/md0 failed."
            # public
            partprobe /dev/$DISK_SYS 2>/dev/null
            sleep 3
            # mkfs
            for i in {${DISK_SYS}4,md0}; do
                echo -n "$MKFS /dev/$i... "
                if $MKFS /dev/$i &>/dev/null; then
                echo OK
                else
                echo failed && rg_info 55 "mkfs $i failed"
                fi
            done
            rg_info "Create cache direcotry..." && mkdir -p /cache/{cache,logs}
            echo -e "/dev/${DISK_SYS}4 \t\t/cache/logs \t\t$FS \tdefaults \t0 0" >>/etc/fstab
            echo -e "/dev/md0 \t\t/cache/cache \t\t$FS \t$MOUNT_OPTS \t0 0" >>/etc/fstab
        echo "--"
#save mdadm.conf
        if (mdadm -Ds 2>/dev/null |grep -q .); then
            [ -f /etc/mdadm.conf ] && rg_info "Backup old mdadm.conf..." && /bin/cp /etc/mdadm.conf /etc/mdadm.conf.bak
            rg_info "Save RAID configration (mdadm.conf)..."
                if [ "$VER6" == 'yes' ]; then
                    mdadm -Ds |sed 's!/dev/md[^ ]*:\([0-9]\)!/dev/md\1!; s!metadata[^ ]* !!; s/$/ auto=yes/' >/etc/mdadm.conf
                else
                    mdadm -Ds |sed 's/$/ auto=yes/' >/etc/mdadm.conf
                fi
        fi
#mount all
        fgrep -q /cache /etc/fstab || rg_info 48 "Internal error: f_mkfs has BUG!"
        rg_info "挂载所有分区..."
        if mount -a; then
            rg_info "创建mkpart锁..."
            echo "$VERSION" >$MKFS_LOCK 2>/dev/null && chattr +i $MKFS_LOCK
            ret=0
        else
            rg_info 49 "mount -a 出错"
        fi
        return $ret
}

4.4.5. 4.5 重载或更新机器路由配置

参考了Git的思想,配置文件分成3种:

分别对应Git的工作区、Git本地版本库和Git远程版本库。对应的动作和思路很明确:

reload和updata动作都会进行差异对比,然后根据需求获取真正有用的rules配置文件。

这里只列举了updata_rules()函数,reload_rules()函数的设计思路与此类似。 其内容如下所示:

#!/bin/bash
function update_rules() {
#使用是内部SVN服务器,所以这里帐号和密码明文,没有考虑太多安全带来的问题
svn co svn://192.168.10.68/route_auto /tmp/route_auto --username=testyum --password=oTIil31pw --force --no-auth-cache

if [ $? -eq 0 ]; then
    echo "[INFO]: 获取最新 rules 成功,检测下载的 rules 库文件是否为空..."
    if !(test -s $LOCAL_TMP_RULES); then
        echo "获取到的最新 rules 库文件为空,请检查远端 rules 库文件!!"
        exit 1
    else
    cp -rf $LOCAL_TMP_RULES $RULES_ENV_FILE
    cp -rf $LOCAL_TMP_RULES $TMPFILES
    echo "获取到的最新 rules 库文件非空,程序继续..."
    fi

    echo "[INFO]: 将最新 rules 库文件与本地 rules 库文件比对是否有差异..."
    if ! (diff $RULES_ENV_FILE $LOCAL_TMP_RULES &>/dev/null); then
        echo "有差异 rules,加载最新 rules 库配置..."
        . $LOCAL_TMP_RULES
        cp -rf $LOCAL_TMP_RULES $RULES_ENV_FILE
    else
        echo "无差异 rules,加载本地 rules 库配置..."
        . $RULES_ENV_FILE
    fi
fi
}