9一、题目要求 : 部署MySQL主从mysql
用shell脚本实现,部署mysql主从,假设两台机器上已经安装了mysql,而且目前无新库。
linux
【核心要点】git
步骤 : 一、主上改配置文件,打开bin-log,设定server_id ,设定ignore_db ,重启,受权用户,锁表,show master staus .github
二、从上改配置文件,设定server_id,重启,stop slave ,chang master ,start slave。sql
在主上写一个脚本,全部操做在此脚本完成,包括写expect脚本和执行expect脚本。docker
#!/bin/bash #这个脚本用来配置MySQL主从同步 #做者:猿课-阿铭 www.apelearn.com #日期:2018-12-17 #!/bin/bash master_ip=192.168.100.12 slave_ip=192.168.100.13 mysqlc="mysql -uroot -paminglinux" check_ok() { if [ $? -ne 0 ] then echo "$1 出错了。" exit 1 fi } f_exist() { d=`date +%F%T` if [ -f $1 ] then mv $1 $1_$d fi } ## 设置主mysql配置 if ! grep '^server-id' /etc/my.cnf then sed -i '/^\[mysqld\]$/a\server-id = 1001' /etc/my.cnf fi if ! grep '^log-bin.*=.*' /etc/my.cnf then sed -i '/^\[mysqld\]$/a\log-bin = aminglinux' /etc/my.cnf fi sed -i '/^log-bin.*/a\binlog-ignore-db = mysql ' /etc/my.cnf /etc/init.d/mysqld restart check_ok "主上重启mysql" ## 登陆mysql,受权用户、锁表以及show master status。 $mysqlc <<EOF grant replication slave on *.* to 'repl'@$slave_ip identified by 'yourpassword'; flush tables with read lock; EOF $mysqlc -e "show master status" > /tmp/master.log file=`tail -1 /tmp/master.log|awk '{print $1}'` pos=`tail -1 /tmp/master.log|awk '{print $2}'` ## 建立在从上配置和操做的脚本 f_exist /tmp/slave.sh cat > /tmp/slave.sh << EOF #!/bin/bash if ! grep '^server-id' /etc/my.cnf then sed -i '/^\[mysqld\]$/a\server-id = 1002' /etc/my.cnf fi /etc/init.d/mysqld restart check_ok "从上重启mysql" $mysqlc <<EOF stop slave; change master to master_host="$master_ip", master_user="repl", master_password="yourpassword", master_log_file="$file", master_log_pos=$pos; start slave; EOF EOF ## 建立传输slave.sh的expect脚本 f_exist /tmp/rs_slave.expect cat > /tmp/rs_slave.expect <<EOF #!/usr/bin/expect set passwd "aminglinux" spawn rsync -a /tmp/slave.sh root@$slave_ip:/tmp/slave.sh expect { "yes/no" { send "yes\r"} "password:" { send "\$passwd\r" } } expect eof EOF ## 执行expect脚本 chmod +x /tmp/rs_slave.expect /tmp/rs_slave.expect check_ok "传输slave.sh" ## 建立远程执行命令的expect脚本 f_exist /tmp/exe.expect cat > /tmp/exe.expect <<EOF #!/usr/bin/expect set passwd "aminglinux" spawn ssh root@$slave_ip expect { "yes/no" { send "yes\r"} "password:" { send "\$passwd\r" } } expect "]*" send "/bin/bash /tmp/slave.sh\r" expect "]*" send "exit\r" EOF ## 执行expect脚本 chmod +x /tmp/exe.expect /tmp/exe.expect check_ok "远程执行slave.sh" ## 主上解锁表 $mysqlc -e "unlock tables"
实例 :shell
在/etc/my.cnf文件中,添加server-id数据库
执行脚本,查看结果bash
注意 : 服务器
if [ $? -ne 0 ] #$?等于0
if ! grep '^server-id' /etc/my.cnf #在/etc/my.cnf文件中查看有没有server-id,若是没有,执行下一步。
sed -i '/^\[mysqld\]$/a\server-id = 1001' /etc/my.cnf #/etc/my.cnf文件中查看没有server-id,就在/etc/my.cnf 中添加。
sed -i '/^\[mysqld\]$/a\log-bin = aminglinux' /etc/my.cnf #
sed -i '/^log-bin.*/a\binlog-ignore-db = mysql ' /etc/my.cnf #添加一个忽略的数据库叫MySQL,不作同步。
sed -i '/^\[mysqld\]$/a\server-id = 1002' /etc/my.cnf #将server-id = 1002,输入到/etc/my.cnf 。
$mysqlc -e "show master status" > /tmp/master.log #show master statu的结果,输出到 /tmp/master.log 。
EOF #是用在mysqlc
EOF #是用在cat > /tmp/slave.sh << EOF
spawn rsync -a /tmp/slave.sh root@$slave_ip:/tmp/slave.sh #将/tmp/slave.sh传输到root@$slave_ip:/tmp/slave.sh
若是系统是CentOS 7,并且使用的yum安装的MySQL,重启命令可能要使用 : systemctl restart mysqld
9二、题目要求 : 管理docker
写一个脚本,实现一键管理docker容器,好比启动、关闭、删除容器等操做。 要求:
【核心要点】
一、要关闭或启动容器,首先要知道容器的id,使用命令docker ps -a 查看,第一列就是容器id。
二、须要以交互的方式让用户输入关闭、启动或者删除的命令,若是用户输入的命令不对须要给出提示。
三、能够把容器的id先存入到一个临时文件里,方便后续遍历。
#!/bin/bash #这个脚本用来管理docker容器 #做者:猿课-阿铭 www.apelearn.com #日期:2018-12-17 while true do read -p "请输入你要执行的操做:(stop/start/rm) " opt if [ -z "$opt" ] then echo "请输入要执行的操做。" continue else break fi done docker ps -a |awk '{print $1}' > /tmp/id.txt case $opt in stop) for id in `cat /tmp/id.txt` do docker stop $id done ;; start) for id in `cat /tmp/id.txt` do docker start $id done rm) for id in `cat /tmp/id.txt` do read -p "将要删除容器$id,是否继续?(y|n)" c case $c in y|Y) docker rm -f $id ;; n|N) echo "容器$id不会被删除。" ;; *) echo "你只能输入'y'或者'n'。" ;; esac done *) echo "你只能输入start/stop/rm。" ;; esac
注意 :
docker ps -a |awk '{print $1}' > /tmp/id.txt # 把全部的容器的id,写入到/tmp/id.txt
for id in `cat /tmp/id.txt` # 在 /tmp/id.txt,查看容器的ID。
9三、题目要求 : 安装配置samba
写个shell脚本,可以实现一键安装并配置samba服务,执行该脚本时须要带一个参数,为共享的目录,目录若不存在,需自动建立。
要求,任何人均可以访问,且不用密码,而且目录是只读的。
【核心要点】
一、须要判断用户给出的目录是否是绝对路径,即是不是'/'开头
二、脚本要判断samba服务是否已经安装,若已经安装了就不须要执行yum install samba了
#!/bin/bash #这个脚本用来一键安装并配置samba #做者:猿课-阿铭 www.apelearn.com #日期:2018-12-17 if [ "$#" -ne 1 ] then echo "运行脚本的格式为:$0 /dir/" exit 1 else if ! echo $1 |grep -q '^/.*' then echo "请提供一个绝对路径。" exit 1 fi fi if ! rpm -q samba >/dev/null then echo "将要安装samba" sleep 1 yum install -y samba if [ $? -ne 0 ] then echo "samba安装失败" exit 1 fi fi cnfdir="/etc/samba/smb.conf" cat >> $cnfdir <<EOF [share] comment = share all path = $1 browseable = yes public = yes writable = no EOF if [ ! -d $1 ] then mkdir -p $1 fi chmod 777 $1 echo "test" > $1/test.txt #假设系统为CentOS7 systemctl start smb if [ $? -ne 0 ] then echo "samba服务启动失败,请检查配置文件是否正确。" else echo "samba配置完毕,请验证。" fi
实例 :
执行脚本,查看结果
注意 :
if ! echo $1 |grep -q '^/.*' #若是不是/开头,就提示用户提供一个绝对路径。
if [ $? -ne 0 ] # 当$?不等于0,提示安装失败了。
cat >> $cnfdir <<EOF #追加几行下面的内容
[share] #模块的名字 [share]
comment = share all #comment(描述)
path = $1 # 共享的目录路径
browseable = yes #是否是可见的
public = yes #是否是公开的,意思是不须要密码认证。
writable = no #是否是可写的
if [ ! -d $1 ] #判断目录是否存在。
echo "test" > $1/test.txt #在$1下,建立一个文件test.txt
9四、题目要求 : 批量查看堕胎机器负载
假如公司的一个业务,域名为www.aminglinux.com,如今有5台机器在跑。为了快速查看这5台机器的负载,须要你写一个Shell脚本,运行脚本后,就能一会儿把5台机器的负载所有打印出来。
【核心要点】
expect脚本或者配置密钥认证
ssh-keygen -f /root/.ssh/newkey #把公钥拷贝到,对方的文件的目录下 ;-f指定目录的名字
ssh -i /root/.ssh/newkey ip #指定私钥的位置。
ssh-agent #把私钥搞到内存里面
ssh-add /root/.ssh/newkey #把密钥添加到内存中。
eval ‘ssh-agent’ #
#!/bin/bash #这个脚本用来批量查机器负载 #做者:猿课-阿铭 www.apelearn.com #日期:2018-12-17 for ip in `cat /tmp/ip.list` do echo $ip ssh $ip "uptime" done
实例 :
把密钥写到/tmp/aaa文件中
ls /tmp/查看生成的密钥,aaa是私钥,aaa.pub是公钥
测试,查看拷贝的密钥,第一次登陆127.0.0.1,有没有生效。
若是出现下面的提示,说明没有添加成功,密钥生效,就把cat /tmp/aaa.pub中的公密钥写入到vi /root/.ssh/authorized_keys。再次执行ssh -i /tmp/aaa root@127.0.0.1
第二次登陆127.0.0.1的效果。
ssh-agent把私钥搞到内存里面
再次执行发现就不用,密码登陆了。
执行脚本,查看结果
注意 :
9五、题目要求 : 自动挂云盘
咱们使用的云主机,购买一块云盘后,默认并非挂载状态的,用shell写一个脚本,只要把盘符和挂载点以参数的形式提供给脚本,该脚本就能够自动格式化、挂载。
要求:
【核心要点】
一、参数要有两个,第一个是设备名,第二个是挂载点,须要判断给出的参数个数以及是否可用
二、格式化磁盘的命令为mkfs.ext4磁盘设备名。
三、mount命令挂载,挂载完后还须要编辑/etc/fstab配置文件
#!/bin/bash #这个脚本用来自动挂载磁盘 #做者:猿课-阿铭 www.apelearn.com #日期:2018-12-17 if [ $# -ne 2 ] then echo "Useage $0 盘符 挂载点, 如: $0 /dev/xvdb /data" exit 1 fi if [ ! -b $1 ] then echo "你提供的盘符不正确,请检查后再操做" exit 1 fi echo "格式化$1" mkfs -t ext4 $1 if [ ! -d $2 ] ;then mkdir -p $2 fi n=`awk '$NF == "$2"' /etc/fstab|wc -l` if [ $n -eq 0 ] then echo "$1 $2 ext4 defaults 0 0" >> /etc/fstab mount -a else echo "配置文件/etc/fstab中已经存在挂载点$2,请检查一下." exit 1 fi
实例 :
执行脚本,查看结果
注意 :
9六、题目要求 : 并发备份数据库
需求背景:
领导要求小明备份数据库服务器里面的100个库(数据量在几十到几百G),须要以最快的时间完成(5小时内),而且不能影响服务器性能。
【核心要点】
#!/bin/bash #这个脚本用来并发备份数据库 #做者:猿课-阿铭 www.apelearn.com #日期:2018-12-19 ##假设100个库的库名、host、port以及配置文件路径存到了一个文件里,文件名字为/tmp/databases.list ##格式:db1 10.10.10.2 3308 /data/mysql/db1/my.cnf ##备份数据库使用xtrabackup(因为涉及到myisam,命令为inoobackupex) exec &> /tmp/mysql_bak.log if ! which innobackupex &>/dev/nll then echo "安装xtrabackup工具" rpm -ivh http://www.percona.com/downloads/percona-release/redhat/0.1-3/percona-release-0.1-3.noarch.rpm && \ yum install -y percona-xtrabackup-24 if [ $? -ne 0 ] then echo "安装xtrabackup工具出错,请检查。" exit 1 fi fi bakdir=/data/backup/mysql bakuser=vyNctM bakpass=99omeaBHh function bak_data { db_name=$1 db_host=$2 db_port=$3 cnf=$4 [ -d $bakdir/$db_name ] || mkdir -p $bakdir/$db_name innobackupex --defaults-file=$4 --host=$2 --port=$3 --user=$bakuser --password=$bakpass $bakdir/$1 if [ $? -ne 0 ] then echo "备份数据库$1出现问题。" fi } fifofile=/tmp/$$ mkfifo $fifofile exec 1000<>$fifofile thread=10 for ((i=0;i<$thread;i++)) do echo >&1000 done cat /tmp/databases.list | while read line do #每循环一次,读一次fd100中的内容,即空行,只有读到空行了才会执行{}内的指令 #每次循环都须要打印当前的时间,休眠1秒,而后再次向fd100中写入空行,这样后续的read就有内容了 # read -u1000 { bak_data `echo $line` echo >&1000 } & //丢到后台去,这样10次很快就循环完,只不过这些任务是在后台跑着,因为咱们一开始就向fd1000里写入了两个空行,因此read会一次性读到两行。 done #等待全部后台任务执行完成 wait #删除fd1000 exec 1000>&- #删除命名管道 rm -f $fifofile
实例 :
安装一个窗口screen , 直接输入”screen“命令就进入了另外一个窗口
使用mkfifo命令,建立一个管道文件1.fifo。
往管道里面写入东西,出现卡顿现象,缘由:只写入东西,没有进程读它。先使用"cat 1.fifo"读取新建的管道文件,而后再写入东西。(ctrl +a 退出screen窗口)
把100个文件流绑定再一块儿,并查看结果,生成的结果是一个软连接。
读100个用户,并赋值给a。
注意 :
exec &> /tmp/mysql_bak.log #定义一个/tmp/mysql_bak.log ,全部的命令、结果写入到这个日志里面
if ! which innobackupex &>/dev/nll # 检测innobackupex命令是否存在
function bak_data { #定义备份数据库的函数,用于备份数据库
innobackupex --defaults-file=$4 --host=$2 --port=$3 --user=$bakuser --password=$bakpass $bakdir/$1 #备份数据库,$4指定配置文件的路径等等,而后放到 $bakdir/$1
if [ $? -ne 0 ] #返回值不等于0,就提示用户。
fifofile=/tmp/$$ #fifo文件的定义
mkfifo $fifofile #建立匿名管道文件
exec 1000<>$fifofile #把100个文件流绑定再一块儿。
thread=10 #定义并发量为10
echo >&1000 #写入10次
cat /tmp/databases.list | while read line #有几个数据库的列表,就循环几回。
9七、题目要求 : 打印三角形
以前我们打印过正方形,也打印过乘法口诀,那今天来打印一个三角形(正三角形,元素用*表示)。
【核心要点】
正三角形的元素排列,若是边长为5个* ,在shell终端显示该正三角形的话,须要有5行,第一行应该先打印4个空格,而后再打印'*',第二行先打印3个空格,而后打印‘*’ ,一直到第5行打印0个空格。
#!/bin/bash #这个脚本用来打印三角形 #做者:猿课-阿铭 www.apelearn.com #日期:2018-12-19 while true do read -p "please input the lenth: " n if [ -z $n ] then echo "要输入一个数字。" continue else n1=`echo $n|sed 's/[0-9]//g'` if [ -n "$n1" ] then echo "你输入的不是纯数字,从新输入。" continue else break fi fi done for i in `seq 1 $n` do j=$[$n-$i] for m in `seq $j` do echo -n " " done for p in `seq 1 $i` do echo -n "* " done echo done
实例 :
执行脚本,输入执行三角形的边长为几,查看结果。
注意 :
if [ -z $n ] #$n为空,提示用户。
n1=`echo $n|sed 's/[0-9]//g'` #判断用户输入的,是否是数字。
if [ -n "$n1" ] #若是不是数字。就提示用户。是数字就退出。
for i in `seq 1 $n` #循环次数是1到$n.
j=$[$n-$i] #第一次打印的空格次数吗,j是要打印空格的次数。
9八、题目要求 : 截取字符串
利用你学过的知识点,想办法根据要求。
字符串var=http://www.aaa.com/root/123.htm
1.取出www.aaa.com/root/123.htm
2.取出123.htm
4.取出http:
5.取出http://
6.取出root/123.htm
7.取出123
【核心要点】
grep/sed/awk
#!/bin/bash #这个脚本用来截取字符串 #做者:猿课-阿铭 www.apelearn.com #日期:2018-12-19 var=http://www.aaa.com/root/123.htm echo "1.取出www.aaa.com/root/123.htm" echo $var |awk -F '//' '{print $2}' echo "2.取出123.htm" echo $var |awk -F '/' '{print $5}' echo "3.取出http://www.aaa.com/root" echo $var |sed 's#/123.htm##' echo "4.取出http:" echo $var |awk -F '//' '{print $1}' echo "5.取出http://" echo $var |awk -F 'www' '{print $1}' echo "6.取出root/123.htm" echo $var |awk -F 'com/' '{print $2}' echo $var |awk -F '/' '{print $4"/"$5}' echo "7.取出123" echo $var |sed 's/[^0-9]//g'
实例 :
使用awk命令截取出www.aaa.com/root/123.htm
使用sed命令截取出第二段字符
使用awk命令截取出取出123.htm、取出http://www.aaa.com/root、取出http:、取出http://、取出root/123.htm、取出123。-F表示以什么作空格、间隔符,
执行脚本,查看结果
9九、题目要求 : 修改文本格式
请把下面的字符串写入到test3.txt文档中:
zhangsan y97JbzPru lisi 5JhvCls6q xiaowang Nnr8qt2Ma laoma iqMtvC02y zhaosi 9fxrb4sJD
改成以下:
zhangsan:y97JbzPru lisi:5JhvCls6q xiaowang:Nnr8qt2Ma laoma:iqMtvC02y zhaosi:9fxrb4sJD
【核心要点】
奇数、偶数行
#!/bin/bash #这个脚本用来格式化文本 #做者:猿课-阿铭 www.apelearn.com #日期:2018-12-19 n=`wc -l test3.txt|awk '{print $1}'` n2=$[$n/2] for i in `seq 1 $n2` do i2=$[$i*2] j=$[$i2-1] l1=`sed -n "$i2"p test3.txt` l2=`sed -n "$j"p test3.txt` echo $l2:$l1 done
实例 :
把第一行的第二行的换行符换成冒号。;s表示替换,N表示 把第一二变成一行; \n表示 表示替换; :/ :把换行符换成冒号。
执行脚本,查看结果
注意 :
n=`wc -l test3.txt|awk '{print $1}'` #统计文档中的行数。并打印出一行
n2=$[$n/2] #把第二行,合并成一行
for i in `seq 1 $n2` #执行的行数是1到$n2
i2=$[$i*2] #i2表示 ,须要要换行的次数
j=$[$i2-1] #j表示 ,循环的次数
l1=`sed -n "$i2"p test3.txt` #l1表示奇数行的内容,
l2=`sed -n "$j"p test3.txt` #l2表示偶数行的内容,
echo $l2:$l1 #$l2:$l1 表示偶数行、奇数行合并的行数
100、题目要求 : 自定义rm
inux系统的rm命令太危险,一不当心就会删除掉系统文件。 写一个shell脚原本奇数行的,要求当删除一个文件或者目录时,都要作一个备份,而后再删除。下面分两种状况,作练习:
假设有一个大的分区/data/,每次删除文件或者目录以前,都要先在/data/下面建立一个隐藏目录,以日期/时间命名,好比/data/.201703271012/,而后把全部删除的文件同步到该目录下面,可使用rsync -R 把文件路径一块儿同步
不知道哪一个分区有剩余空间,在删除以前先计算要删除的文件或者目录大小,而后对比系统的磁盘空间,若是够则按照上面的规则建立隐藏目录,并备份,若是没有足够空间,要提醒用户没有足够 的空间备份并提示是否放弃备份,若是用户选择y,则直接删除文件或者目录,若是选择n,则提示未删除,而后退出脚本。
【核心要点】
1. 简单 #!/bin/bash #这个脚本用来自定义rm #做者:猿课-阿铭 www.apelearn.com #日期:2018-12-19 filename=$1 big_filesystem=/data/ if [ ! -e $1 ] then echo "$1 不存在,请使用绝对路径" exit fi d=`date +%Y%m%d%H%M` read -p "Are U sure delete the file or directory $1? y|n: " c case $c in y|Y) mkdir -p $big_filesystem/.$d && rsync -aR $1 $big_filesystem/.$d/$1 && /bin/rm -rf $1 ;; n|N) exit 0 ;; *) echo "Please input 'y' or 'n'." ;; esac 2.复杂 #!/bin/bash #这个脚本用来自定义rm #做者:猿课-阿铭 www.apelearn.com #日期:2018-12-19 #!/bin/bash filename=$1 if [ ! -e $1 ] then echo "$1 不存在,请使用绝对路径" exit fi d=`date +%Y%m%d%H%M` f_size=`du -sk $1|awk '{print $1}'` disk_size=`LANG=en; df -k |grep -vi filesystem|awk '{print $4}' |sort -n |tail -n1` big_filesystem=`LANG=en; df -k |grep -vi filesystem |sort -n -k4 |tail -n1 |awk '{print $NF}'` if [ $f_size -lt $disk_size ] then read -p "Are U sure delete the file or directory: $1? y|n: " c case $c in y|Y) mkdir -p $big_filesystem/.$d && rsync -aR $1 $big_filesystem/.$d/$1 && /bin/rm -rf $1 ;; n|N) exit 0 ;; *) echo "Please input 'y' or 'n'." ;; esac else echo "The disk size is not enough to backup the files $1." read -p "Do you want to delete $1? y|n: " c case $c in y|Y) echo "It will delete $1 after 5 seconds whitout backup." for i in `seq 1 5`; do echo -ne ". "; sleep 1;done echo /bin/rm -rf $1 ;; n|N) echo "It will not delete $1." exit 0 ;; *) echo "Please input 'y' or 'n'." ;; esac fi
实例 :
查看磁盘的使用率
执行脚本,查看结果
注意 :
if [ ! -e $1 #若是提供的路径不存在,就提示用户。
mkdir -p $big_filesystem/.$d && rsync -aR $1 $big_filesystem/.$d/$1 && /bin/rm -rf $1 #建立隐藏的目录,并备份隐藏的目录,同步完了,再删除 。-R:把目录的结果一块儿同步过去。
f_size=`du -sk $1|awk '{print $1}'` #判断要删除的文件的大小
disk_size=`LANG=en; df -k |grep -vi filesystem|awk '{print $4}' |sort -n |tail -n1` #
big_filesystem=`LANG=en; df -k |grep -vi filesystem |sort -n -k4 |tail -n1 |awk '{print $NF}'` #查看最大的分区答空间大小,并显示出来。
if [ $f_size -lt $disk_size ] #要删除的文件的大小小于磁盘空间,就能够删除了。
$big_filesystem/.$d && rsync -aR $1 $big_filesystem/.$d/$1 && /bin/rm -rf $1 #备份删除的文件的,而后删除。
for i in `seq 1 5`; do echo -ne ". "; sleep 1;done #停顿5秒,每停顿那一秒,就打印一个点。
若是发生误删的操做,立刻中止全部的写的操做,那么找回来的机会比较答。
来源 : https://github.com/aminglinux/shell100/blob/master/61.md