Shell编程案例
在Windows下写shel脚本,windows的回车换行跟linux回车不一样,在 windows下编辑shell文件,默认输入的回车是"\r\n" ,导致在 linux下执行shell脚本时报这个 \r的错。使用sed -i 's/\r//' build.sh后再执行(就是将windows下的中文回车行换成英文回车行),即 sed -i 's/\r//' build.sh && bash build.sh
[root@docker01 ~]# sed -i.bak '1i\ews' ren.txt 将ren.txt备份后继续在ren.txt插入一行内容
1、菜单选择
输出下面菜单
1.install MySQL
2.install Tomcat
3.exit
当用户选择对应的数字就开始安装对应的服务(可echo输出替代),需要对用户输入的数字进行判断是否为整数(用条件测试表达式实现)。
a、if语句实现
#! /bin/bash cat <<EOF 1.install MySQL 2.install Tomcat 3.exit EOF read -t 15 -p "Please input an integer :" num #check weather integer or not expr 1 + $num &>/dev/null if [ $? -ne 0 ] then echo "Usage:$0 {1|2|3}" exit 1 fi if [ $num -eq 1 ] then echo "install MySQL ……" elif [ $num -eq 2 ] then echo "install Tomcat ……" elif [ $num -eq 3 ] then echo "bye." exit else echo "Usage:$0 {1|2|3}" exit 1 fi
b、case语句实现
[root@centos74-ren shell_test]# cat case_inter.sh #! /bin/bash cat <<EOF 1.install MySQL 2.install Tomcat 3.exit EOF read -t 15 -p "Please input an integer :" num #check weather integer or not expr 1 + $num &>/dev/null if [ $? -ne 0 ] then echo "Usage:$0 {1|2|3}" exit 1 fi case $num in 2) echo "install Tomcat ……" ;; 1) echo "install MySQL ……" ;; 3) echo "bye." exit ;; *) echo "Usage:$0 {1|2|3}" exit 1 ;; esac
2、使用read读入方式比较两个整数大小(用条件表达式实现)
先判断两个读入的数据是否是整数,通过expr判断,当两者都是整数时候,expr $a+$b +2 &>/dev/null;echo $?返回是0.说明是整数
[root@centos74-ren shell_test]# cat inter_c.sh #! /bin/bash read -t 15 -p "Please input two integer :" a b #check weather integer or not expr 1 + $a + $b &>/dev/null if [ $? -ne 0 ] then echo "Please input two integer :" exit 1 fi if [ $a -gt $b ] then echo "$a > $b" elif [ $a -eq $b ] then echo "$a = $b" else echo "$a < $b" fi
3、判断系统根分区剩余空间的大小,如果低于1000MB就提示不足,否则提示充足
#! /bin/bash m=`df -m / | awk 'NR==2{print $4 }'` if [ $m -lt 1000 ] then echo "the disk space is not enough!!!" else echo "the disk space is enough" fi
可以将条件修改$m -lt 40000,再看下效果
4、 使用变量定义、read读入及脚本传参方式实现比较2个整数的大小
定义变量:就是直接在脚本中写好变量,且赋值,直接比较
#! /bin/bash a=2 b=3 if [ $a -gt $b ] then echo "$a>$b" elif [ $a -lt $b ] then echo "$a<$b" else echo "$a=$b" fi
read读入,就是交互式,手动输入要比较的大小,输入的必须是整数
#! /bin/bash read -p "please input two integer: " a b if [ -z "$b" ] then echo "must two integer args:" exit 1 fi expr $a + $b + 10 &>/dev/null if [ $? -ne 0 ] then echo "please input two integer:" exit 2 fi if [ $a -gt $b ] then echo "$a>$b" elif [ $a -lt $b ] then echo "$a<$b" else echo "$a=$b" fi
脚本传参,就是在执行脚本的过程中,将要比较的值写进去
[root@centos74-ren shell_test]# cat 0720_02_03.sh #! /bin/bash #read -p "please input two integer: " a b a=$1 b=$2 if [ -z "$b" ] then echo "must two args:" exit 1 fi expr $a + $b +1 &>/dev/null if [ $? -ne 0 ] then echo "please input two integer:" exit 2 fi if [ $a -gt $b ] then echo "$a>$b" elif [ $a -lt $b ] then echo "$a<$b" else echo "$a=$b" fi
5、打印一个菜单如下,当用户选择对应的数字时,就执行对应项的应用,最好对用户的输入进行是否为整数判断
1.install lamp
2.install lnmp
3.exit
[root@centos74-ren shell_test]# cat inter.sh #! /bin/bash cat <<EOF 1.install lamp 2.install lnmp 3.exit EOF read -t 15 -p "Please input an integer :" num #check weather integer or not expr 1 + $num &>/dev/null if [ $? -ne 0 ] then echo "Usage:$0 {1|2|3}" exit 1 fi if [ $num -eq 1 ] then echo "install lamp ……" elif [ $num -eq 2 ] then echo "install lnmp ……" elif [ $num -eq 3 ] then echo "bye." exit else echo "Usage:$0 {1|2|3}" exit 1 fi
6、通过脚本传参的方式,检查Web网站URL是否正常
[root@centos74-ren shell_test]# cat check_web.sh #! /bin/bash Url_Check() { wget --spider -T 10 -q -o /dev/null $1 if [ $? -eq 0 ] then echo "$1 is ok !" return 0 else echo "$1 is not ok !!!" return 2 fi } Url_Check $1
7、利用case语句开发Rsync服务启动停止脚本,并能通过chkconfig实现开机自启动
[root@centos74-ren shell_test]# cat rsync.sh #! /bin/bash . /etc/init.d/functions start() { rsync --daemon retval=$? if [ $retval -eq 0 ] then action "rsync start is ok" /bin/true return $retval else action "rsync start is failed" /bin/false fi } stop() { pkill rsync retval=$? if [ $retval -eq 0 ] then echo "rsync stop is ok" return $retval else action "rsync stop is failed" /bin/false return $retval fi } case $1 in start) start retval=$? ;; stop) stop retval=$? ;; restart) stop sleep 3 start retval=$? ;; *) echo "Usage:$0 start|stop|restart" exit 1 ;; esac exit $retval
8、猜数字游戏。首先让系统随机生成一个数字,给这个数字定一个范围(1-60),让用户输入猜的数字,对输入进行判断,如果不符合要求,就给予高或低的提示,猜对后则给出猜对用的次数,请用while语句实现
[root@centos74-ren shell_test]# cat random.sh #! /bin/bash rand_num=$((RANDOM%60)) Search_count=0 while true do ((Search_count++)) read -p "pleae input an integer: " num if [ $num -gt $rand_num ] then echo "the numer is too high" elif [ $num -eq $rand_num ] then echo "CONTRADULATIONS !! is ok" echo "total search $Search_count" exit 1 else echo "the numer is too lower" fi done
9、分析nginx访问日志(自备),把日志中每行的访问字节数对应字段数字相加,计算出总的访问量。给出实现程序,请用while循环实现
读取每行的行数时,最好别用管道符,因为管道符相当于开了新的子shell,内外无法互相传参,通过done重定向读取
[root@centos74-ren shell_test]# cat nginx_colum.sh #! /bin/bash sum=0 while read line do num=`echo "$line" | awk '{print $3}'| grep -v "-" ` sum=$((sum+num)) done < ./nginx.log echo $sum
10、计算从1加到100之和(要求用for和while,至少给出两种方法)
[root@centos74-ren shell_test]# cat while_100.sh #! /bin/bash sum=0 i=1 while true do if [ $i -le 100 ] then sum=$((sum+i)) ((i++)) else break fi done echo $sum
11、利用bash for循环打印下面这句话中字母数不大于6的单词(某企业面试真题)。I am oldboy teacher welcome to oldboy training class
[root@centos74-ren shell_test]# cat char.sh #! /bin/bash a="I am oldboy teacher welcome to oldboy training class" for i in $a do chr=`echo ${#i}` if [ $chr -le 6 ];then echo $i fi done
[root@centos74-ren shell_test]# cat char2.sh #! /bin/bash a="I am oldboy teacher welcome to oldboy training class" b=`echo $a | tr "" "\n"` for i in $b do if (( `echo $i | wc -L` <= 6 ));then echo $i fi done
12、服务监测
#! /bin/bash . /etc/init.d/functions Service_Name=(crond sshd cloud-init cloud-config) for i in ${Service_Name[@]} do Service=`systemctl status $i | grep Active | awk '{print $3}' | cut -d "(" -f2 | cut -d ")" -f1 ` if [ "$Service" == "running" -o "$Service" == "exited" ];then action "$i is running" /bin/true else action "$i is failed" /bin/false systemctl start $i fi done
服务监测结果:
13、系统资源监控--内存、cpu、io、NIC
#! /bin/bash #####Memory Resource Monitor##### mem_rate=`free -m | awk 'NR==2{print ($3/$2)*100}'` if [ `echo "$mem_rate >= 10" | bc` -eq 1 ];then echo $mem_rate echo "The memory is not enough" else echo "The memory has enough space" fi ###CPU Resource Monitor#### cpu_user=`top -b -n 1 | grep Cpu | awk '{print $2 }'` cpu_system=`top -b -n 1 | grep Cpu | awk '{print $4 }'` cpu_idle=`top -b -n 1 | grep Cpu | awk '{print $8 }' | cut -f 1 -d "."` cpu_load_1min=`uptime | awk '{print $10 }' | cut -d , -f 1` cpu_load_5min=`uptime | awk '{print $11 }' | cut -d , -f 1` cpu_load_15min=`uptime | awk '{print $12 }' | cut -d , -f 1` if [ `echo "$cpu_idle <= 99.7" | bc` -eq 1 ];then echo "the CPU is not enoug,$cpu_idle" else echo "the CPU has enough space $cpu_idle" fi echo "CPU_user:$cpu_user" echo "CPU_sys:$cpu_system" echo "CPU_idle:$cpu_idle" echo "CPU_load: $cpu_load_1min,$cpu_load_5min,$cpu_load_15min" #####IO Monitor##### io_util=`iostat -kxd | awk 'NR==4{print $NF}'` io_KB_read=`iostat -kd | awk 'NR==4{print $3}'` io_KB_wrtn=`iostat -kd | awk 'NR==4{print $4}'` echo "io_util:$io_util" echo "io_KB_read:$io_KB_read" echo "io_KB_wrtn:$io_KB_wrtn"
执行结果:
date="`date '+%Y-%m-%d %H:%M:%S'`" ip="www.baidu.com" nic="eth0" lost_rate=`ping -c 8 -w 8 $ip | grep 'packet loss' |awk -F'packet loss' '{ print $1 }'| awk '{ print $NF }' | sed 's/%//g'` if [ $lost_rate -eq 0 ] then echo "network_ok $date $ip $nic" else echo "network_error $date $ip $nic" systemctl restart NetworkManager fi sleep 10 eth=eth0 #while [ "1" ] #do STATUS="fine" RXpre=$(cat /proc/net/dev | grep $eth | tr : " " | awk '{print $2}') TXpre=$(cat /proc/net/dev | grep $eth | tr : " " | awk '{print $10}') sleep 1 RXnext=$(cat /proc/net/dev | grep $eth | tr : " " | awk '{print $2}') TXnext=$(cat /proc/net/dev | grep $eth | tr : " " | awk '{print $10}') clear RX=$((${RXnext}-${RXpre})) TX=$((${TXnext}-${TXpre})) if [[ $RX -lt 1024 ]];then RX="${RX}B/s" elif [[ $RX -gt 1048576 ]];then RX=$(echo $RX | awk '{print $1/1048576 "MB/s"}') $STATUS="busy" else RX=$(echo $RX | awk '{print $1/1024 "KB/s"}') fi if [[ $TX -lt 1024 ]];then TX="${TX}B/s" elif [[ $TX -gt 1048576 ]];then TX=$(echo $TX | awk '{print $1/1048576 "MB/s"}') else TX=$(echo $TX | awk '{print $1/1024 "KB/s"}') fi echo -e "===================================" echo -e "Date: `date +%F`" echo -e "Time: `date +%k:%M:%S`" echo -e "Port: $1" echo -e "Status: $STATUS" echo -e " \t RX \tTX" echo "------------------------------" echo -e "$eth \t $RX $TX " echo "------------------------------" #done
网卡执行监控结果:
14、日志分析脚本
分析nginx访问日志(自备),把日志中每行的访问字节数对应字段数字相加,计算出总的访问量。我们取每行的第三个数据相加
#! /bin/bash sum=0 while read line do num=`echo "$line" | awk '{print $3}'| grep -v "-" ` sum=$((sum+num)) done < ./nginx.log echo $sum
[root@centos74-ren shell_test]# cat nginx.log 12 23 45 23 34 34 2w we 33 22 33 44 23 44 45 q w 33 3 2 - e 3 44 [root@centos74-ren shell_test]# [root@centos74-ren shell_test]# sh nginx_colum.sh 278 [root@centos74-ren shell_test]#
15、定时任务以及备份
#! /bin/bash [ -d /backup ] || mkdir -p /backup/ [ -d /service_backup ] || mkdir -p /service_backup/ Date=`date +%Y%m%d-%H%M-%w-%T` cd /service_backup/ tar -cvf ${Date}.tar.gz /root/*.sh --force-loca #Locale backup rsync -a /service_backup/*.tar.gz /backup/ md5sum /backup/${Date}.tar.gz >> /backup/${Date}.md5 #Remote backup rsync /backup/* rsync_backup@192.168.0.18::backup --password-file=/etc/rsync.passwd # For details see man 4 crontabs # Example of job definition: # .---------------- minute (0 - 59) # | .------------- hour (0 - 23) # | | .---------- day of month (1 - 31) # | | | .------- month (#1 - 12) OR jan,feb,mar,apr ... # | | | | .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat # | | | | | # * * * * * user-name command to be executed */5 * * * * root /bin/sh backup.sh
执行结果验证:
16、查询一个文件的字符串是不是在另一个文件中
要查var_result.txt中的字符串是不是在par.yml文件中,如果在的话就把该字符串写到var_check_result.txt
[root@k8s-master ~]# cat check_var.sh #! /bin/bash while read line do var=`echo "$line" ` files=`cat /root/par.yml |grep "$var" ` if [ $? -eq 0 ] then echo "$var" >> var_check_result.txt else echo "file is not exist" fi done < ./var_result.txt
var_result.txt中的每个字符串占一行
[root@csren ~]#while read line; do ssh -q `echo $line | awk '{print $1}'` hostname;done<csren1 ##while循环只能ssh连接一个server,去看主机名
shell中for循环的默认分隔符是:空格、tab、\n
需求是只以\n作为分隔符
shell for循环以\n作为分割符,
compute-1 eth4
compute-2 eth5
compute-3 eth11
compute-4 eth7
需要在本机去ping上面四台主机分别对应的网卡是不通
[root@csren ~]# cat csren.sh ##for可以实现遍历看网卡状态 #!/bin/bash IFS=$'\n\n' ##这样为了读取整行内容 for i in `cat csren1`; do echo $i ssh -q `echo $i | awk '{print $1}'` ifconfig `echo $i | awk '{print $2}'` | grep -i up done [root@csren ~]# cat csren.sh ##while循环只能ssh连接一个server,去看网卡状态 #!/bin/bash while read line; #读取整行内容 do ssh -q `echo $line | awk '{print $1}'` ifconfig `echo $line | awk '{print $2}'` | grep -i up done< csren1