Shell 编程(实战篇)

一、shell实现100台服务器的公钥的批量分发;LLD规划:100台服务器ip为:192.168.42.101-201,root密码:123456

考虑因素:
1.如何创建秘钥
2.检查与服务器之间的通讯
3.分发秘钥

[root@backup ~]# cat keypir.sh 
#!/bin/bash
password=123456

#创建秘钥对---(ssh-keygen),写入指定文件
CreateKeyPair(){                         
ssh-keygen -f /root/.ssh/id_rsa -P ""    #-P:创建的秘钥是否设置密码,此处不设置密码。
}

#检查100台服务器网络是否畅通
CHECK(){                                 
ping -c 1 192.168.42.$i &>/dev/null
if [ $? -eq 0 ]                          #$? 返回为0时,说明网络畅通
then
return 1
else
return 0
fi
}

#分发秘钥
TRACE(){
which sshpass &>/dev/null     #确定sshpass是否安装,对方服务器可能没有安装
if [ $? -ne 0 ]               #通过which命令判断sshpass是否安装,安装了echo $?则返回0
then                          #$?不为0时,则说明没有安装
yum install sshpass -y
#sshpass -p $password ssh-copy-id -o StrictKeyHostChecking  192.168.42.$i
sshpass -p $password scp -p -o StrictHostKeyChecking=no /root/.ssh/id_rsa.pub 192.168.42.$i:/tmp/               
 #使用sshpass工具和-o参数实现避免交互输入yes和密码
 #将本地/root/.ssh/id_rsa.pub(生成的秘钥文件),传输到对应服务器上/tmp/目录下,此时不能直接传到/root/.ssh目录下,避免其他机器同样操作覆盖文件。
sshpass -p $password ssh -o StrictHostKeyChecking=no 192.168.42.$i "cat /tmp/id_rsa.pub >> /root/.ssh/authorized_keys"           
#ssh连接服务器,将/tmp/下密码文件写如入/root/.ssh/authorized_keys
sshpass -p $password ssh -o StrictHostKeyChecking=no 192.168.42.$i "chmod 600 /root/.ssh/authorized_keys"           #修改文件权限
sshpass -p $password ssh -o StrictHostKeyChecking=no 192.168.42.$i "rm -rf /tmp/id_rsa.pub"                      #由于是秘钥文件,为了安全起见,用完删除

else                                  #如果sshpass工具安装,则直接执行。
#sshpass -p $password ssh-copy-id 192.168.42.$i
sshpass -p $password scp -p -o StrictHostKeyChecking=no /root/.ssh/id_rsa.pub 192.168.42.$i:/tmp/
sshpass -p $password ssh -o StrictHostKeyChecking=no 192.168.42.$i "cat /tmp/id_rsa.pub >> /root/.ssh/authorized_keys" 
sshpass -p $password ssh -o StrictHostKeyChecking=no 192.168.42.$i "chmod 600 /root/.ssh/authorized_keys"
sshpass -p $password ssh -o StrictHostKeyChecking=no 192.168.42.$i "rm -rf /tmp/id_rsa.pub"
fi
}

#主函数,调用上方定义的函数,实现功能
MAIN(){                
for i in {101..201}
do
CHECK
if [ $? -eq 1 ]                     #调用CHECK检查网络是否畅通,return=1时(畅通)
then
    if [ -f /root/.ssh/id_rsa.pub ]  #畅通的话,检查秘钥文件是否存在
    then
       TRACE                         #执行TRACE函数,分发秘钥
    else
       CreateKeyPair                  #创建秘钥
       TRACE                          #分发秘钥
    fi
else                  #不通时
echo " 192.168.42.$i is unreachable..."

fi
done 
}

MAIN

二、设计一个shell 程序,在每天凌晨压缩打包/etc 目录下的所有内容,存放在/root/bak 目录里,且文件名为如下形式yymmdd_etc.tar.gz(yy为年,mm为月,dd为日),该目录保存7天内容;每天凌晨3点增量同步到备份服务器/backup目录下,每周六凌晨3点全量同步到备份服务的/backup目录下;备份服务器/backup下保留一个月的备份文件。

考虑因素:
(1)打包/etc目录,并存放在/root/bak目录里,按要求命名。
(2) /root/backup中只保存7天内容。
(3)增量备份,全量备份。
(4)备份服务器保存一个月文件。

#!/bin/bash
#定义变量
back_file_name=`date +%Y%m%d`.tar.gz     //文件名
back_file_dir=/root/bak                  //压缩打包路径
backup_server_user=rsync_backup			 //备份服务器用户
backup_server_pass=123456				 //备份服务器密码
root_pass=123456						 //备份主机root密码
backup_server_IP=192.168.42.159			 //备份服务器IP
mail_owner=ljwenjie66@163.com			 //邮箱地址
mail_topic="web data backup"			// 

data_tar(){                                           #定义用于压缩函数
    [ -d $back_file_dir ] || mkdir -p $back_file_dir  #判断/root/bak备份的目录是否存在,不存在就创建。
    tar -czf $back_file_dir/$back_file_name /etc/*    #/etc下所有内容进行打包/root/bak/下以时间命名。
}

data_trace(){                                         #进行增量备份
rsync -avz $back_file_dir $backup_server_user@$backup_server_IP::backup --password-file=/etc/rsync.password
}       #rsync将本地/root/bak新增的文件备份到备份主机上
        #--password-file中存储了rsync的密码,避免了交互输入密码

data_trace_all(){    #实现全量备份
    sshpass -p $root_pass scp -o StrictHostKeyChecking=no -rp $back_file_dir/* root@192.168.42.159:/backup
#sshappss -p 123456 scp -rp $back_file_dir root@192.168.42.138:/backup/
}        #sshpass工具实现了自动输入密码
         #-o StrictHostKeyChecking参数实现了自动输入yes or no,避免了人机交互
         #利用scp将/root/bak下所有内容进行备份,以root身份备份到对应主机的/backup目录下

clean_over_localdata(){   #清除本地7天前的的所有文件
    find $back_file_dir -mtime +7 -exec rm {} -rf \;
}

clean_over_remodata(){ #利用ssh连接备份服务器,将服务器中一个月之前的文件删除
    sshpass -p $backup_server_pass ssh -o StrictHostKeyChecking=no $backup_server_IP "find /backup/ -mtime +30 -exec rm {} -rf \;"
}

case $1 in
    data_tar)
        data_tar
        ;;
    trace_all)
        data_trace_all
        ;;
    data_trace)
        data_trace
        ;;
    clean_over_localdata)
        clean_over_lcoaldata
        ;;
    clean_remodata)
        clean_over_remodata
        ;;
    *)
        echo "please input true paramater..."   #如果输入的不是有效参数,则输出*

esac

三、shell开发运维管理工具。

要求:用户交互,当用户输入菜单号时,打印相关内容。
菜单

  1. 磁盘分区
  2. CPU负载
  3. 剩余内存
  4. 退出
    输入:1
    输出:(主机名,系统版本,分区情况)
    hostname:
    system:系统版本
    ---------分区一-----------(分区变量输出)
    path:分区一
    size:大小
    file_os:分区文件系统类型
    mount_on:分区挂载点
    ----------分区二----------
    path:分区二
    size:大小
    file_os:分区文件系统类型
    mount_on:分区挂载点
    输入:2
    输出:
    1分钟平均负载:
    5分钟平均负载:
    15分钟平均负载:
    输入:3
    输出:
    目前可用内存:
    可用Swap分区:
    输入:4
    输出:
    Bey…
#!/bin/bash
while true
do
#格式化输出以下菜单
cat <<EOF        
              -------------------菜单---------------------
              -              1.查看磁盘分区              -
              -              2.CPU负载                   -
              -              3.剩余内存                  -
              -              4.退出                      -  
              --------------------------------------------
EOF
#接受用户输入的一个值
read -p "请输入你要执行的操作:>>>" num
#实现第一个功能:查看磁盘分区
PART(){               
  echo "hostname:$HOSTNAME"                            #获取主机名
  echo "system: `cat /etc/redhat-release`"             #获取系统内核版本
  #定义数组,获取磁盘分区放入其中。
  array1=(`lsblk -l |awk '/sd[a-z][0-9]/{print $1}'`)  #磁盘名
  array2=(`lsblk -l |awk '/sd[a-z][0-9]/{print $4}'`)  #大小
  array3=(`lsblk -l |awk '/sd[a-z][0-9]/{print $6}'`)  #类型
  array4=(`lsblk -l |awk '/sd[a-z][0-9]/{print $7}'`)  #挂载点
  #遍历数组
  num=`echo $((${#array1[@]}-1))`  #获取数组长度-1的值,给num(这里是3
  for i in `seq 0 $num`            #i:0-3
  do
 #循环输出数组103位置值
cat <<EOF
                                   ---------${array1[$i]}-----------
                                        path: ${array1[$i]}
                                        size: ${array2[$i]}
                                        file_os: ${array3[$i]}
                                        mount_on:${array4[$i]}
EOF
done
}
#实现第二个功能:查看cpu负载
LOADING(){                          #通过uptime命令,和awk,获取平均负载。
uptime |awk -F [:,] '{print "一分钟平均负载:",$(NF-2)"\n""五分钟平均分在:",$(NF-1)"\n""十五分钟平均负载:",$NF}'
}                                  #$NF:从最后一列开始取。
#实现第三个功能:查看内存和swap
MEM(){
var=("目前可用内存:" "可用swap分区:")
n=0
for i in `free -h |awk '/^[^[:space:]]/ {print $4}'`    #取出内存和swap,进行遍历
do
echo ${var[$n]} $i            #为满足题目要求,(说明+内容),将说明放入数组依次输出+内容
let n++                       #n从0开始自加,实现数组依次输出。
done
}
#利用case语句捕获用户键入的值。
#模式匹配成功,则执行相应函数。
case $num in
   1)        
   PART
   ;;
   2)
   LOADING
   ;;
   3)
   MEM
   ;;
   4)
   exit 0
   ;;
   *)
   echo "please input true list..."
esac

done

优秀内容推荐:

(1)LVS-NAT的配置及运用
(2)LVS-DR的配置及运用
(3)Redis集群搭建
(4)LNMP架构介绍及部署实践
(5)Linux系统上安装MySQL数据库接描述

猜你喜欢

转载自blog.csdn.net/weixin_45961525/article/details/107875867