脚本的批量处理
一、部署脚本参考示范
1、安装脚本
个别项目比如X7项目sp补丁的安装、中标普华软件的安装等都需要对好多机器进行安装操作
结合之前部署的经验,现觉得需要总结一下,方便之后有类似项目的类似批量场景时,大家可以借鉴或者改进
过去X7项目安装sp补丁的时候,对于Shell不是十分熟悉,仅是写了sp的安装脚本,然后ssh到每台机器上用./test.sh来安装,不过也算是节省了一部分手敲安装指令的时间,下面是当时脚本的部分内容:
#!/bin/bash
#给系统升级SP1补丁
function sp1()
{
read -p"是否要升级SP1补丁,回复yes或者no:" g
if [ $g = yes ] || [ $g = y ]
then
cd 1207-X7-SP1
chmod +x NeoKylin-Server-5.0_U3-loongson-Release-Build14-X7-SP1-20200810.run
./NeoKylin-Server-5.0_U3-loongson-Release-Build14-X7-SP1-20200810.run
for i in {1..10}
do
echo "你已经成功的升级了SP1补丁" # 输出10次,更醒目些
done
cd ..
else
echo "你跳过了安装SP1补丁的操作!!!"
fi
}
#将有关lightdm-gtk的两个包降级
function lightdm()
{
read -p"是否确定要降级lightdm,回复yes或者no:" h
if [ $h = yes ] || [ $h = y ]
then
cd lightdm-gtk
rpm -Uvh lightdm-gtk-* --oldpackage
rpm -qa | grep lightdm-gtk
cd ..
else
rpm -qa | grep lightdm-gtk
fi
}
sp1
lightdm
上面脚本算是很基础的安装脚本了,可以把每个要执行的操作写函数里,后面调用函数,不同情况的安装都在函数里修改。其中需要注意的地方就是,对于脚本书写,尽量使用相对路径,这样脚本随着补丁包一起移动会比较方便
2、配置脚本
下面是天云项目安全加固配置脚本的部分内容,更详细的内容请参考知识库里我的这篇文章:“安全加固脚本+修改root密码->出现root始终无法登录问题”
#!/bin/bash
# 定义一个函数判断文本是否已经在文件中存在
function is_in_file(){
# 接收第一个参数“内容”,接收第二个参数“文件路径”
num=`cat $2 | grep "$1" | wc -l`
if [ $num == 1 ]
then
return 0
else
return 1
fi
}
is_in_file "pam_cracklib.so minlen=8 minclass=3" /etc/pam.d/common-password
if [ $? == 1 ]
then
# 设置密码复杂度含有"大写字母、小写字母、数字、特殊字符"其中的三种
sed -i "s/pam_cracklib.so/pam_cracklib.so minlen=8 minclass=3/g" /etc/pam.d/common-password
fi
# 设置密码使用期限不超过15天
sed -i "1,/99999/{s/99999/15/}" /etc/login.defs
is_in_file 'auth required pam_tally2.so deny=5 unlock_time=1800 even_deny_root root_unlock_time=1800' /etc/pam.d/common-auth
if [ $? == 1 ]
then
# 设置无效次数过多锁定、锁定时间30分
sed -i '15i auth required pam_tally2.so deny=5 unlock_time=1800 even_deny_root root_unlock_time=1800' /etc/pam.d/common-auth
fi
配置脚本,最需要注意的地方就是对某些配置的修改是否会因多次运行出现重复配置。为此定义了一个函数,接收两个参数,来判断要添加的配置是否已经在文件中存在,这样可以保证脚本幂等性,多次运行也不会有隐存bug。其他配置脚本,参考这个书写就行,或者自己有其他更好的写法自己写也行,但核心就是要考虑重复运行的情况
二、账户名以及密码统一的环境
1、使用Shell
我记得X7项目一批车是100多台机器,也就是100多套系统,一个个手动scp传进去其实也可以,就是有点机械,都传入一遍,大约花费两个小时,这是很不方便的,如果网络通的情况下,可以问客户要所有机器规划的ip地址列表,这样就能批量分发了,可以用下面的脚本
#!/bin/bash
# 该脚本依据expect来实现自动交互输入密码,所以需要给控制主机装一个expect软件包
user="kylin" # 请修改远程主机用户名
password="123123" # 请修改远程主机密码
files='/home/kylin/test.sh' # 请修改本地脚本文件所在位置,注意写绝对路径
dir='~/' # 请修改目标路径
for i in `cat ./ip_list.txt` # 由于是读取脚本同级目录下的ip_list.txt文件,所以先创建好这个文件,把ip添加进去
do
expect << EOF
set timeout 120
spawn scp -r $files $user@$i:$dir
expect {
"yes/no" {send "yes\n"; exp_continue}
"password" {send "$password\n"; exp_continue}
}
expect eof
EOF
done
中间没有传成功的,是可以看出来的,到时候单独处理一下。所以很重要的前提是:批量执行操作前,请一定要催客户把所有机器网络环境准备好,把ip调通!!!
有了这个分发脚本,只要网络环境ok,之前手动ssh操作100台机器的时间,可以从两个小时缩短到十几分钟。最关键的是,这次升级完补丁,没准项目适配一周后,新的补丁又出来了,到时候稍微改一下脚本就行
分发完剩下的就是跑脚本了,跑脚本的话,可以修改一下分发脚本,用下面这个
#!/bin/bash
user="kylin" # 请修改远程主机用户名
password="123123" # 请修改远程主机密码
files='/home/kylin/test.sh' # 请修改要执行的脚本路径,注意写绝对路径
for i in `cat ./ip_list.txt` # 由于是读取脚本同级目录下的ip_list.txt文件,所以先创建好这个文件,把ip添加进去
do
expect << EOF
set timeout 120
spawn ssh $user@$i $files # 改用ssh,后面跟上命令
expect {
"yes/no" {send "yes\n"; exp_continue}
"password" {send "$password\n"; exp_continue}
}
expect eof
EOF
done
2、使用Ansible
对于已经掌握Ansible的人会很友好,因为Ansible与生俱来的幂等性使得管理受控主机很方便且相对专业。不过不熟悉也没关系,按照下面方式设置,是可以正常使用的,涉及到Ansible的更高级操作,自行查阅相关资料
(1)环境准备
安装ansible软件包
(2)ansible基础配置
需要有一个主机清单hosts文件和ansible.cfg通用配置
[kylin@localhost ~]# cd test
[kylin@localhost test/]# cat hosts # 这个hosts文件自己创建,里面写上受控主机的ip
192.168.10.11
192.168.10.12
192.168.10.13
[kylin@localhost test/]# cat ansible.cfg # 这个文件也是自己创建的,里面写上ansible的通用(全局)配置
[defaults]
inventory = /home/kylin/test/hosts # hosts文件所在位置
remote_user = kylin
remote_port = 22
host_key_checking = False
[kylin@localhost test/] ls # 编辑好之后的项目目录结构大概是这样的
ansible.cfg copy.yml hosts # copy.yml是后边要写的playbook剧本
(3)写一个基础的playbook
---
- hosts: all
become: True
tasks:
- name: copy scripts to the controlled host
copy:
src: /home/kylin/test/install.sh # 要传入受控主机上的脚本路径
dest: /home/kylin/ # 这里末尾最好加上斜杠
mode: 0777
- name: run the script
command: /bin/bash /home/kylin/test/install.sh
register: result # 或取脚本运行后的结果存入result变量
- name: get the results after running the script
debug:
var: result.stdout_lines # 输出result变量里的stdout结果,也就是脚本运行后的结果
(4)执行playbook
ansible-playbook copy.yml -k
回车后输入密码,就可以把脚本传入所有受控主机然后运行并获取运行后的结果了
ansible的好处也很明显,除了幂等性之外,另一方面,如果熟悉了常用模块的使用,之后修改playbook执行批量任务的时候,会比脚本方便的多,它就是专为批量且多次运行而生的,尤其体现在麒麟云的部署上,那种环境下一定是用playbook去部署环境的而不是shell
三、账户名以及密码不统一的环境
1、使用Shell
账户名和密码不统一的话,需要先提前给所有机器做好免密,免密做好之后对所有主机的操作就方便的多了,控制主机与受控终端的免密做法如下:
本机执行ssh-keygen
,然后一路回车,最后再用ssh-copy-id命令(ssh-copy-id kylin@192.168.10.11
)这样的方式做免密,期间需要输入密码。做好免密之后,分发脚本书写就更简单了
#!/bin/bash
user="kylin" # 请修改远程主机用户名
files='/home/kylin/test.sh' # 请修改本地脚本文件所在位置,注意写绝对路径
dir='~/' # 请修改目标路径
for i in `cat ./ip_list.txt` # 由于是读取脚本同级目录下的ip_list.txt文件,所以先创建好这个文件,把ip添加进去
do
scp -r $files $user@$i:$dir
done
分发完之后用还用相同的改法可以执行脚本
#!/bin/bash
user="kylin" # 请修改远程主机用户名
files='/home/kylin/test.sh' # 请修改要执行的脚本路径,注意写绝对路径
for i in `cat ./ip_list.txt` # 由于是读取脚本同级目录下的ip_list.txt文件,所以先创建好这个文件,把ip添加进去
do
ssh $user@$i $files # 改用ssh,后面跟上命令
done
2、使用Ansible
使用Ansible处理账户名和密码不统一的环境,也是需要做一下免密,做法和上面说的方法一样,环境准备、ansible基础配置以及playbook还按照之前介绍的方法做相同配置即可,稍微方便了一点的是,在最后运行playbook的时候,可以不用加-k,即:
ansible-playbook copy.yml
直接运行剧本即可