先声明一下,写的把磁盘测崩了,就是来回安装卸载测试脚本测崩的。。。
所以就到了主备的脱机备份还原的步骤,不过倒是省了安装dm的步骤,还是有好处的。
接下来看脚本内容。
电脑快炸了,暂时不演示了。安装数据库是没问题的,后续的自己想办法。
目录
/root/zhubei
/root/zhubei/anzhuangbao 压缩包目录
/root/zhubei/jichuanzhuang 放一些脚本的目录
/root/zhubei/wenjian 放置一些模板文件,如limit.conf、auto.xml、hosts等。
一、实现自动安装dm数据库
anzhuanghuanjin.sh
#!/bin/bash
. qingdan.sh #这个是变量文件,提供变量修改
echo "温馨提示,请为tmp目录准备好空间,没有请退出加空间"
sleep 3 #给留时间,发现不对,退出
systemctl stop firewalld.service
systemctl disable firewalld.service
#创建用户
groupadd dinstall -g 2001
useradd -G dinstall -m -d /home/$user1 -s /bin/bash $user1
echo "$passwd1" | passwd $user1 --stdin
cp -a /root/zhubei/wenjian/limits.conf /etc/security/limits.conf #将提前准备好的权限文件提前复制过去。
#创建目录
mkdir -p $data
mkdir -p $arch
mkdir -p $bak
#修改用户
chown -R dmdba:dinstall $data
chown -R dmdba:dinstall $arch
chown -R dmdba:dinstall $bak
#给权限
chmod -R 755 $data
chmod -R 755 $arch
chmod -R 755 $bak
创建安装目录
mkdir $path
chown dmdba:dinstall $path
#解压安装,在安装目录下放了一个包,可以替换。
cd /root/zhubei/anzhuangbao
ZIP=$(ls -l|grep "dm8"|awk '{ print $9}')
rm -rf jieya/*
unzip $ZIP -d jieya
cd jieya
IMAGE=$(ls -l|awk '{print $9}'| egrep "*.iso$")
mount -o loop $IMAGE /mnt/
# 通过一个xml文件安装。自动执行。
cd /mnt/
./DMInstall.bin -q /root/zhubei/wenjian/auto.xml
变量文件如下
qingdan.sh
#!/bin/bash
#用户和密码
user=root
passwd="526533526533Yy"
user1=dmdba
passwd1=Dameng123
#主机清单
HOSTS="192.168.2.160 192.168.2.161 192.168.2.162"
#安装路径
path=/home/$user1/dmdbms
#数据库实例目录
data=/dmdata/data/
#备份目录
bak=/dmdata/dmbak
#归档日志目录
arch=/dmdata/arch
#监视器主机
check="192.168.2.160"
#主库
zhu="192.168.2.161"
#备库
bei="192.168.2.162"
这样的话写一次就可以在各个文件中调用,改起来也方便
xml文件如下
<?xml version="1.0"?>
<DATABASE>
<!-- 安装语言 -->
<LANGUAGE>EN</LANGUAGE>
<!--安装程序的时区配置,缺省为+08:00,取值范围:-12:59 ~ +14:00 -->
<TIME_ZONE>+08:00</TIME_ZONE>
<!-- key文件,试用可不填-->
<KEY></KEY>
<!-- 安装程序组件类型,取值范围:0、1、2,0 表示安装全部,1 表示安装服务器,2 表示安装客户端。缺省为0。 -->
<INSTALL_TYPE>0</INSTALL_TYPE>
<!-- 安装目录 -->
<INSTALL_PATH>/home/dmdba/dmdbms</INSTALL_PATH>
<!-- 是否初始化库,取值范围:Y/N、y/n,不允许为空。 -->
<INIT_DB>n</INIT_DB>
<!--数据库实例参数 -->
<DB_PARAMS>
<!--初始数据库存放的路径,不允许为空 -->
<PATH>/dm8_1/data</PATH>
<!--初始化数据库名字,缺省为DAMENG,不超过128个字符 -->
<DB_NAME>DMOA</DB_NAME>
<!--初始化数据库实例名字,缺省为DMSERVER,不超过128个字符 -->
<INSTANCE_NAME>DMOA</INSTANCE_NAME>
<!--初始化时设置dm.ini中的PORT_NUM,缺省为5236,取值范围:1024~65534 -->
<PORT_NUM>5233</PORT_NUM>
<CTL_PATH></CTL_PATH>
<LOG_PATHS>
<LOG_PATH></LOG_PATH>
</LOG_PATHS>
<!--数据文件使用的簇大小,取值范围:16页、32页,缺省为16页 -->
<EXTENT_SIZE>16</EXTENT_SIZE>
<!--数据文件使用的页大小,取值范围:4K、8K、16K、32K,缺省为8K -->
<PAGE_SIZE>16</PAGE_SIZE>
<!--日志文件使用的簇大小,缺省为256,取值范围为64~2048之间的整数 -->
<LOG_SIZE>256</LOG_SIZE>
<!--标识符大小写敏感。取值范围:Y/N y/n 1/0,缺省为Y -->
<CASE_SENSITIVE>Y</CASE_SENSITIVE>
<!--字符集选项,缺省为0。0代表GB18030,1代表UTF-8,2代表韩文字符集EUC-KR -->
<CHARSET>0</CHARSET>
<!--规定VARCHAR对象长度的单位。取值范围:0,1。1:所有VARCHAR类型对象的长 度以字符为单位;0:有VARCHAR类型对象的长度以字节为单位。缺省为0。 -->
<LENGTH_IN_CHAR>0</LENGTH_IN_CHAR>
<USE_NEW_HASH>1</USE_NEW_HASH>
<!--初始化时设置SYSDBA的密码,缺省为SYSDBA,长度在9到48个字符之间 -->
<SYSDBA_PWD></SYSDBA_PWD>
<SYSAUDITOR_PWD></SYSAUDITOR_PWD>
<SYSSSO_PWD></SYSSSO_PWD>
<SYSDBO_PWD></SYSDBO_PWD>
<!--初始化时区,默认是东八区。格式为:正负号小时:分钟,取值范围:-12:59 ~ +14:00 -->
<TIME_ZONE>+08:00</TIME_ZONE>
<PAGE_CHECK>0</PAGE_CHECK>
<EXTERNAL_CIPHER_NAME></EXTERNAL_CIPHER_NAME>
<EXTERNAL_HASH_NAME></EXTERNAL_HASH_NAME>
<EXTERNAL_CRYPTO_NAME></EXTERNAL_CRYPTO_NAME>
<ENCRYPT_NAME></ENCRYPT_NAME>
<USBKEY_PIN></USBKEY_PIN>
<BLANK_PAD_MODE>0</BLANK_PAD_MODE>
<SYSTEM_MIRROR_PATH></SYSTEM_MIRROR_PATH>
<MAIN_MIRROR_PATH></MAIN_MIRROR_PATH>
<ROLL_MIRROR_PATH></ROLL_MIRROR_PATH>
<PRIV_FLAG>0</PRIV_FLAG>
<ELOG_PATH></ELOG_PATH>
</DB_PARAMS>
<!--是否创建数据库实例的服务,取值范围: Y/N y/n,不允许为空,不初始化数据库将忽略此节点。非root用户不能创建数据库服务。 -->
<CREATE_DB_SERVICE>n</CREATE_DB_SERVICE>
<!--是否启动数据库,取值范围: Y/N y/n,不允许为空,不创建数据库服务将忽略此节点。 -->
<STARTUP_DB_SERVICE>n</STARTUP_DB_SERVICE>
</DATABASE>
这个文件我没有用变量的方式调,而是直接修改的,如果觉得麻烦,也可以直接在脚本中调用变量用sed的方式修改这个文件。总之,最好能达到只需要修改一个文件的程度!
能安装完数据库就要考虑,是不是要免密?是不是要能在远程调用变量?安装过程中出现空间不够要不要检测,然后提前退出?
二、免密登陆
这个我从网上找了一个脚本,我也不想重复造轮子。
mianmi.sh
#!/bin/bash
. qingdan.sh
if [ "$#" -lt 2 ]; then
echo "Usage:./generate_ssh_key.sh [user] [password]"
exit 2
fi
user=$1
password=$2
#这里的HOSTS同样是变量文件中的一个调用的变量。
hosts="${HOSTS[@]}"
echo "================= 程序开始运行 ==================="
for host in ${hosts}
do
echo ================= $host ===================
expect -c "
set timeout 2;
spawn ssh ${user}@$host
expect {
*yes/no* { send \"yes\\n\"; exp_continue; }
*password* { send \"${password}\\n\" }
}
sleep 1
send \"ssh-keygen -t rsa\\n\"
expect {
*id_rsa* { send \"\\n\"; exp_continue; }
*y/n* {set timeout 5; send \"y\\n\"; exp_continue; }
*passphrase* {set timeout 5; send \"\\n\"; exp_continue; }
*again* {set timeout 5; send \"\\n\" }
}
sleep 1
foreach target {${hosts}} {
send \"ssh-copy-id \$target\\n\"
expect {
*connecting* {set timeout 5; send \"yes\\n\"; exp_continue;}
*password* {set timeout 5; send \"${password}\\n\";}
}
sleep 1
}
"
done
echo "================= 程序结束运行 ==================="
这个脚本其实用了expect这个这个工具,有兴趣的可以研究一下。
三、在远程调用变量文件
我的解决办法是直接拿ansible执行。
举个例子
假设我的安装路径是/home/dmdba/dmdbms/。这一段都是变量。
如果直接用ssh user@host "su - dmdba -c "$变量" ,很多时候就会出现莫名其妙的bug,因为你永远不知道你的下一句是在哪个环境里,这种情况下,不如直接配置个ansible。
当然,由于强迫症,我太像给三台机器都自动配置ansible了,因此在安装之前写了这些
qidong.sh
#!/bin/bash
#调用变量
. qingdan.sh
#配置免密的脚本,其实就是调用了一下免密登陆的脚本。然后输入了几个变量,没啥内容
./peizhimianmi.sh
#安装ansible
for host in $HOSTS
do
ssh root@$host "yum -y install ansible"
done
#生成一个要配置的主机清单文件,这个目录是我自己的脚本目录
cp -a /root/zhubei/wenjian/hosts /root/zhubei/wenjian/hosts1
#修改主机清单,这里写入的是all组
echo -e "[all]\n\
$check\n\
$zhu\n\
$bei" >> /root/zhubei/wenjian/hosts1
#写入check,监视器组
echo -e "[check]\n\
$check" >> /root/zhubei/wenjian/hosts1
#写入zhu,主组
echo -e "[zhu]\n\
$zhu" >> /root/zhubei/wenjian/hosts1
#写入bei,备组
echo -e "[bei]\n\
$bei" >> /root/zhubei/wenjian/hosts1
#将主机清单复制到各个主机
for host in $HOSTS
do
scp /root/zhubei/wenjian/hosts1 $user@$host:/etc/ansible/hosts
done
#删除临时创建的主机清单,保留原本的模板文件
rm -rf /root/zhubei/wenjian/hosts1
#将脚本复制到各个主机
for host in $HOSTS
do
scp -r /root/zhubei $user@$host:/root/
done
cd /root/zhubei/jichuanzhuang
#这里其实是为了在远程也能用本地变量,所以直接把相应的脚本文件加入到了复制产生的变量文件中。这样,在远程才能使用本地
cp -a qingdan.sh yuancheng.sh
#这里把一个没写shell类型的自动安装脚本追加到要远程使用的自动安装脚本中。
cat yuancheng-anzhuanghuanjin.sh >> yuancheng.sh
for host in $HOSTS
do
scp yuancheng.sh $user@$host:/root/zhubei/jichuanzhuang
done
#给远程脚本权限
ansible all -m shell -a 'chmod 777 /root/zhubei/jichuanzhuang/yuancheng.sh'
#检测tmp空间大小
cp -a qingdan.sh tmp2.sh
cat tmp.sh >> tmp2.sh
#执行远程脚本
for host in $HOSTS
do
ssh $user@$host < tmp2.sh
#这个文件是tmp2.sh脚本发送给主机的,只有tmp目录空间大于2G才会发送。当tmp空间足够。才会发送。
cat /root/zhengque
if [ $? -eq 0 ]
then
ssh $user@$host "rm -rf /tmp/*;/root/zhubei/jichuanzhuang/yuancheng.sh"
else
rm -rf /root/zhubei/jichuanzhuang/tmp2.sh
exit
fi
#这个是本次执行完一定要删除的,不然下次判断tmp空间大小就出错了
rm -rf /root/zhengque
done
#这里删除了临时创建的远程执行文件,下面ansible删除的也是同一个
rm -rf /root/zhubei/jichuanzhuang/tmp2.sh
ansible all -m shell -a 'rm -rf /root/zhubei/jichuanzhuang/yuancheng.sh'
#这里给dmdba用户配了一下免密,害怕报错,最后还是疯狂报错。。。。
./mianmi.sh $user1 $passwd1
#这里检测一下库有没有安装成功,这里其实写的不太完美,因为我不太确定本机能否接收远程的命令结果返回值。最好也和上面一样,改成用文件判断的方式
for host in $HOSTS
do
ssh $user@$host "cd $path/bin/"
if [ ! $? -eq 0 ]
then
echo "有的库没安装,是$host,退出了。"
exit
else
echo "$host:是正常的。"
fi
done
#创建实例
./shili.sh
#注册服务,这里使用了一个playbook注册服务。
ansible-playbook -t zhuce playbook.yaml
#这里检测空间大小用了和上面一样的方法。
cp -a qingdan.sh jiancekongjian2.sh
cat jiancekongjian.sh >>jiancekongjian2.sh
#检测空间大小
for host in $HOSTS
do
ssh $user@$host < jiancekongjian2.sh
cat /root/zhengque
if [ $? -eq 0 ]
then
echo "$host空间充足,可以备份还原"
else
echo "$host空间不足,不能备份还原"
rm -rf /root/zhubei/jichuanzhuang/jiancekongjian2.sh
exit
fi
rm -rf /root/zhengque
done
rm -rf /root/zhubei/jichuanzhuang/jiancekongjian2.sh
#执行备份还原,这里的-t就是指定的playbook中的tags。
ansible-playbook -t chushihua playbook.yaml
./bak.sh
./huanyuan.sh
检测tmp空间大小其实也用了另一个脚本
tmp.sh
#这里不写shell类型,不写变量文件调用,因为这个文件其实是要被调用追加到一个临时创建的文件中。
#这里提取了tmp的空间大小。
tmp=$(df -h /tmp/ | awk 'NR==2'| awk '{print $4}' | sed 's/G//')
#bc -l是处理浮点数的一个工具,echo "$tmp>2"|bc -l ,为真是1,为假是0.有兴趣的自己去试一试。
if [ ! $(echo "$tmp>2"|bc -l) -eq 0 ]
then
echo "tmp空间充足"
#这里创建的文件
touch zhengque
#发送给主节点,主节点判断空间是否充足,如果不够,停止安装。
scp zhengque $user@$check:/root/
else
#这个是凑数的,我刚知道return的值不能从子脚本返回主脚本。没法写。
echo "tmp空间不足,返回1"
fi
shili.sh
#!/bin/bash
. qingdan.sh
#这里其实也能使用ansible创建实例,但是ansible比较消耗资源,直接用ansible容易卡死。absible只适合执行一些资源消耗不大的命令。
for host in $HOSTS
do
#这里不直接登陆dmdba的一个原因是,免密配置会很繁琐。那个免密脚本做不到。我没时间研究免密的脚本。谁有空可以研究一下。
ssh $user@$host "su - dmdba -c \"cd $path/bin && \
./dminit path=/dmdata/data/ PAGE_SIZE=32 EXTENT_SIZE=64 CASE_SENSITIVE=y DB_NAME=zhubei INSTANCE_NAME=DBSERVER PORT_NUM=5236\""
done
playbook.yaml
---
- hosts: all
remote_user: root
#这个是为了减轻资源消耗,聊胜于无吧。。。
gather_facts: no
#这里调用了一个变量文件。其实里面和qingdan.sh是一样的内容,不过是yaml格式的。
vars_files:
- vars.yaml
#这个tasks任务负责注册服务,tags是为了执行playbook时,只执行有对应tags的tasks任务。
tasks:
- name: "注册服务"
shell: |
{{ path }}/script/root/dm_service_installer.sh -t dmserver -dm_ini /dmdata/data/zhubei/dm.ini -p zhubei
tags: zhuce
- hosts: all
remote_user: root
gather_facts: no
vars_files:
- vars.yaml
#因为备份数据库的时候要先初始化,所以要启动,停止一次。
tasks:
- name: "初始化实例"
shell: |
su - {{ user1 }} -c "{{ path }}/bin/DmServicezhubei start"
tags: chushihua
- name: "停止实例"
shell: |
su - {{ user1 }} -c "{{ path }}/bin/DmServicezhubei stop"
tags: chushihua
vars.yaml
- user: root
- passwd: 526533526533Yy
- user1: dmdba
- passwd1: Dameng123
- HOSTS: 192.168.2.160 192.168.2.161 192.168.2.162"
- path: /home/{{user1}}/dmdbms
#这个path最后不要加斜杠!
- data: /dmdata/data/
- bak: /dmdata/dmbak
- arch: /dmdata/arch
- check: 192.168.2.160
- zhu: 192.168.2.161
- bei: 192.168.2.162
jiancekongjian.sh
shiyongkongjian=$(df -h | grep "/$"|awk '{print $5}' | sed 's/%//')
if [ ! $shiyongkongjian -gt 80 ]
then
touch zhengque
scp zhengque $user@$check:/root/
else
echo "空间不足"
fi
~
bak.sh
#!/bin/bash
. qingdan.sh
#这个文件其实只干了一件事,就是把bak文件追加到qingdan.sh中,有了变量,然后在远程执行。
cp -a qingdan.sh qingdan2.sh
cat bak >> qingdan2.sh
ssh $user@$zhu < qingdan2.sh
rm -rf /root/zhubei/jichuanzhuang/qingdan2.sh
bak
su - $user1 -c "$path/bin/dmrman CTLSTMT=\"BACKUP DATABASE '/dmdata/data/zhubei/dm.ini' FULL TO BACKUP_FILE1 BACKUPSET 'BACKUP'\""
bak文件中只有这一句。
huanyuan.sh
#!/bin/bash
. qingdan.sh
cp -a qingdan.sh qingdan2.sh
cat huanyuan >> qingdan2.sh
#这里向各个节点传输备份文件
for host in $HOSTS
do
scp $user@$zhu:/dmdata/data/zhubei/bak/BACKUP/ $user@$host:/dmdata/data/zhubei/bak/
done
#进行还原
ssh $user@$check<qingdan2.sh
ssh $user@$bei<qingdan2.sh
huanyuan
su - $user1 -c "$path/bin/dmrman CTLSTMT=\"RESTORE DATABASE '/dmdata/data/zhubei/dm.ini' FROM BACKUPSET 'BACKUP'\""
su - $user1 -c "$path/bin/dmrman CTLSTMT=\"RECOVER DATABASE '/dmdata/data/zhubei/dm.ini' UPDATE DB_MAGIC\" "
这里的文件格式可能有点小问题。
至此,后面的内容无法实现了。因为再测脚本电脑就炸了,频繁的卸载安装对电脑伤害很大。。。。。
最后,有一个删除的脚本。用来测试用
#!/bin/bash
cd /home/dmdba/dmdbms/script/root/
./dm_service_uninstaller.sh -nDmServicezhubei
PID=$(ps aux | grep dmdba | grep -v grep| awk '{print $2}')
kill -9 $PID
userdel -r dmdba
groupdel dinstall
rm -rf /dmdata
umount /mnt
rm -rf /tmp/*