第六天

一、while

1、范例1:每隔2秒记录一次系统负载情况

1.1 方法一:屏幕输出
[root@node4 day6]# cat while01.sh 
#!/bin/bash

while true
    do
    uptime
    sleep 2
done
1.2 追加到log里,使用微秒单位
[root@node4 day6]# cat while02.sh 
#!/bin/bash

while [ 1 ]
do
    uptime >> ./uptime.log
    usleep 1000000
done

[root@node4 day6]# sh while02.sh &

跟踪文件更新和尾部变化:
[root@node4 day6]# tail -f uptime.log 
1.3 查看后台执行的任务
[root@node4 day6]# sh while02.sh &
[1] 5355
[root@node4 day6]# jobs
[1]+  Running                 sh while02.sh &
[root@node4 day6]#


拿到前台:
[root@node4 day6]# fg 1
sh while02.sh

(1)
暂停任务:
Ctrl+z
[1]+  Stopped                 sh while02.sh

(2)
放到后台执行:
[root@node4 day6]# bg
[1]+ sh while02.sh &
[root@node4 day6]# jobs
[1]+  Running                 sh while02.sh &
1.4 nohup

2、范例二

2.1 求1到100的和
[root@node4 day6]# cat while03.sh 
#!/bin/bash
# xsz
# qq:666
# functions:while-3 example
# version:1.1

i=1
sum=0
while((i<=100))
do
    ((sum=sum+i))
    ((i++))
done
[ "$sum" -ne 0 ] && printf "totalsum is:$sum\n"
[root@node4 day6]# sh while03.sh 
totalsum is:5050
[root@node4 day6]# 
2.2 通过算法实现
[root@node4 day6]# cat sum.sh 
#!/bin/sh

i=100
((sum=i*(i+1)/2))
echo $sum
[root@node4 day6]# sh sum.sh 
5050


[root@node4 day6]# cat sum2.sh 
#!/bin/sh

i=10000000
((sum=i*(1+10000000)/2))
echo $sum
[root@node4 day6]# sh sum2.sh 
50000005000000
[root@node4 day6]# 

提示:上述公式中an表示等差数列的第N项。
求和公式
Sn=(a1+an)n/2
Sn=a1n+n(n-1)d/2 d=公差

3、范例3:使用while循环竖向打印10,9,8……1

3.1 方法1
[root@node4 day6]# cat while04.sh 
#!/bin/sh

i=10
while ((i>0))
do
    echo $i
    ((i--))
done
[root@node4 day6]# sh while04.sh 
10
9
8
7
6
5
4
3
2
1
[root@node4 day6]# 
3.2 方法二
两个中括号需要用$调用i
[root@node4 day6]# cat while05.sh 
#!/bin/sh

i=10
while [[ $i > 0 ]]
do
    echo $i
    ((i--))
done
[root@node4 day6]# sh while05.sh 
10
9
8
7
6
5
4
3
2
1
[root@node4 day6]# 
3.3 正着打
[root@node4 day6]# cat while06.sh 
#!/bin/sh
i=1
while [[ i -lt 11 ]]
do
    echo $i
    ((i++))
done
[root@node4 day6]# sh while06.sh 
1
2
3
4
5
6
7
8
9
10
[root@node4 day6]# 
3.4 其他
[root@node4 day6]# cat while07.sh 
#!/bin/sh
read -t 20 -p "please input ht enumber:" i
while ((i--))
do
    echo $i
done
[root@node4 day6]# sh while07.sh 
please input ht enumber:11
10
9
8
7
6
5
4
3
2
1
0
[root@node4 day6]# 

传参:
[root@node4 day6]# cat while08.sh 
#!/bin/sh
i="$1"
while [ $i -gt 0 ]
do
    echo $i
    ((i--))
done
[root@node4 day6]# 
[root@node4 day6]# sh while08.sh 5
5
4
3
2
1
[root@node4 day6]# 
3.5 until
until先执行循环再判断
[root@node4 day6]# cat until01.sh 
#!/bin/sh

i=1
until ((i>100))
do
    ((sum=sum+i))
    ((i++))
done
[ -n "$sum" ] && echo $sum
[root@node4 day6]# sh until01.sh 
5050

[root@node4 day6]# cat until02.sh 
#!/bin/sh

i=10
until [[ $i < 1 ]]
do
    echo $i
    ((i--))
done
[root@node4 day6]# sh until02.sh 
10
9
8
7
6
5
4
3
2
1
[root@node4 day6]# 
3.6 定时访问网站地址
[root@node4 day6]# cat while09.sh 
#!/bin/bash

while true
do
    curl -I -s http://www.niaoyun.com | head -1
    sleep 10
done
[root@node4 day6]# sh while09.sh 
HTTP/1.1 301 Moved Permanently


修改:
[root@node4 day6]# cat while09.sh 
#!/bin/bash

while true
do
     if [ `curl -o /dev/null -s -w "%{http_code}" http://10.201.106.134` -ne 200 ];then
	echo "10.201.106.134 error"
	#echo "niaoyun.com is error" | mail -s "18-status" root@localhost
     else
	echo "10.201.106.34 ok"
     fi
    sleep 2
done

[root@node4 day6]# sh while09.sh 
10.201.106.34 ok
10.201.106.34 ok
10.201.106.34 ok
10.201.106.34 ok
10.201.106.134 error
10.201.106.134 error
10.201.106.134 error

二、高级例子

1、判断URL是否正常的脚本

1.1 方法1 根据http code status判断
[root@node4 day6]# cat while-2-1.sh 
#!/bin/sh
while true
do
    status=`curl -o /dev/null -s -w "%{http_code}" $1`
    if [ "$status" = "200" ];then
	echo "this url is good"
    else
	echo "this url is bad"
    fi
    sleep 2
done
[root@node4 day6]# sh while-2-1.sh www.baidu.com
this url is good
this url is good
this url is good


函数化:
[root@node4 day6]# cat while-2-1-2.sh 
#!/bin/sh

. /etc/init.d/functions
while true
do
    status=`curl -o /dev/null -s -w "%{http_code}" $1`
    if [ "$status" = "200" ];then
	action "this url is good" /bin/true
    else
	action "this url is bad" /bin/false
    fi
    sleep 1
done

[root@node4 day6]# sh while-2-1-2.sh www.baidu.com
this url is bad                                            [FAILED]
this url is good                                           [  OK  ]
this url is good                                           [  OK  ]
this url is good                                           [  OK  ]
this url is good                                           [  OK  ]
1.2 数组方法检查

失败: [root@node4 day6]# cat while-2-2.sh #!/bin/sh . /etc/init.d/functions

url_list=(
http://www.baidu.com
http://www.qq.com
http://www.niaoyun.com
)

function wait()
{
    echo -n "3秒后,执行该操作."
    for ((i=0;i<3;i++))
    do
	echo -n ".";sleep 1
    done
}

function check_url()
{
    wait
    echo 'check url...'
    for((i=0;i<`echo ${#url_list[*]}`;i++))
    do
    #HTTP/1.1 200 OK
    #judge=($(curl -I -s ${url_list[$i]} | head -1 | tr "\r" "\n"))
    judge=($(curl -o /dev/null -s -w "%{http_code}" "${url_list[$i]}"))
    if [[ "${judge[1]}" == '200' || "${judge[2]}" == 'OK' ]];then
	action "${url_list[$i]}" /bin/true
    else
	action "${url_list[$i]}" /bin/false
    fi
    done
}
check_url

2、apache日志分析

2.1 问题1、计算apache一天的日志access_2010-12-8.log中所有行的日志各元素的访问字节数的总和
取出字节数:
[root@node4 day6]# awk '{print $10}' access_2010-12-8.log  | grep -v "-"
44286
10850
11809
255

计算:
[root@node4 day6]# awk '{print $10}' access_2010-12-8.log | grep -v "-" | tr "\n" "+" | sed 's#+$#\n#g' | bc
226905
[root@node4 day6]# 


脚本:
[root@node4 gaoji]# cat while05.sh 
exec <access_2010-12-8.log
sum=0
while read line
do
    [ -z "`echo $line | awk '{print $10}' | sed 's#[0-9]##g'`" ] || continue
    ((sum=sum+`echo $line | awk '{print $10}'`))
done
echo $sum
[root@node4 gaoji]# sh while05.sh 
226905

修改,增加变量:
[root@node4 gaoji]# cat while05.sh 
exec <access_2010-12-8.log
sum=0
while read line
do
bytes=`echo $line | awk '{print $10}'`
    [ -z "`echo $bytes | sed 's#[0-9]##g'`" ] || continue
    ((sum=sum+$bytes))
done
echo $sum

for循环:

[root@node4 gaoji]# cat for-6.sh 
#!/bin/bash
size=`awk '{print $10}' $1`
sum=0
for num in $size
do
    [ -n "$num" -a "$num" = "${num//[^0-9]/}" ] || continue
	((sum=$num+sum))
done

echo "Log.size:$sum bytes`echo $(($sum/1024))`KB"

[root@node4 gaoji]# sh for-6.sh access_2010-12-8.log 
Log.size:226905 bytes221KB
2.2 抓阄脚本
1)执行脚本后,想去的同学输入英文名全拼,产生随机数01-99之间的数字,数字越大就去参加项目实践,前面已经抓到的数字,下次不能再出现相同数字。
2)第一个输入名字后,屏幕输出信息,并将名字和数字记录到文件里,程序不能退出继续等待别的学生输入。

低配版:输入名字打印名字和一个随机数,然后继续等待输入。

[root@node4 gaoji]# cat while06.sh 
#!/bin/sh

while read -p "please input you name: " name
do
    if [ -n "$name" ]; then
	echo -e "$name\t$RANDOM"
    fi
done
[root@node4 gaoji]# sh while06.sh 
please input you name: xs
xs	6982
please input you name: xsz
xsz	10364

三、for循环

1、for简单例子

1.1 列出数字

[root@node4 for]# cat for01.sh 
#!/bin/sh

for num in 5 4 3 2 1
do
    echo $num
done

[root@node4 for]# cat for01.sh 
#!/bin/sh

for ip in 10.201.106.1 10.201.106.2
do
    ping -c 1 $ip
done


法2:
[root@node4 for]# cat for01.sh 
#!/bin/sh

for num in {5..1}
do
    echo $num
done
[root@node4 for]# sh for01.sh 
5
4
3
2
1

[root@node4 for]# cat for01.sh 
#!/bin/sh

for num in `seq 5 -1 1`
do
    echo $num
done

打单数:
[root@node4 for]# cat for01.sh 
#!/bin/sh

for num in `seq 9 -2 1`
do
    echo $num
done

1.2 打印当前目录内容

[root@node4 for]# cat for02.sh 
#!/bin/sh

for filename in `ls .`
do
    echo $filename
done

1.3 清理开机自启动的服务

[root@node4 for]# cat for03.sh 
#!/bin/sh

LANG=en
for oldboy in `chkconfig --list | grep 3:on | awk '{print $1}'`
do
    chkconfig --level 3 $oldboy off
done


把需要的服务开启:
[root@node4 for]# cat for03.sh 
#!/bin/sh 

LANG=en
for oldboy in crond network syslog sshd
do
    chkconfig --level 3 $oldboy on
done

1.4 seq

[root@node4 for]# seq 6
1
2
3
4
5
6
[root@node4 for]# seq 3 6
3
4
5
6
[root@node4 for]# seq 1 2 10
1
3
5
7
9

[root@node4 for]# seq -s , 1 10
1,2,3,4,5,6,7,8,9,10

计算
[root@node4 for]# seq -s "+" 5 | bc 
15

2、企业面试题

2.1 使用for循环在/oldboy目录下创建10个文件,名称依次为oldboy-1 oldboy-2

[root@node4 for]# cat a1.sh 
#!/bin/bash

for file in `seq 10`
do
    [ ! -d "$dir" ] && mkdir -p /oldboy
    touch /oldboy/oldboy-$file
done


[root@node4 for]# cat a1-2.sh 
#!/bin/sh

DIR=/oldboy
mkdir $DIR -p
[ ! -d $dir ] && exit
for num in `seq 10`
do
    cd $DIR && touch oldboy-$num
done

2.2 将以上文件中的oldboy全部改成linux

[root@node4 for]# cat a2.sh 
for f in `ls /oldboy/*`
do
    mv $f `echo $f | sed 's#oldboy-#linux-#g'`
done


[root@node4 for]# cat a2-1.sh 
for f in `seq 10`
do
    cd /oldboy
    mv oldboy-$f linux-$f
done


[root@node4 for]# cat a2-2.sh 
#!/bin/bash
DIR=/oldboy
[ ! -d $DIR ] && exit 1
cd $DIR
for f in `ls /oldboy/`
do
 mv $f linux-`echo $f | cut -d "-" -f2`
done

2.3 批量创建10个系统账号oldboy01-oldboy10并设置密码(密码不能相同)

[root@node4 for]# cat a3.sh 
for n in `seq -w 10`
do
    useradd oldboy-$n && echo "oldboy-$n" | passwd --stdin oldboy-$n
done

2.4 批量创建10个系统账号oldboy01-oldboy10并设置密码(密码为随机8位数)

[root@node4 for]# cat a4.sh 
for n in `seq -w 11 15`
do
    useradd oldboy-$n 
    pass=`echo $RANDOM | md5sum | cut -c 11-18`
    echo -e "user:oldboy-$n pass:$pass" >> /tmp/user.log
    echo "$pass" | passwd --stdin oldboy-$n
done


[root@node4 for]# cat /tmp/user.log 
user:oldboy-11 pass:8705147a
user:oldboy-12 pass:f6816151
user:oldboy-13 pass:561cf29e
user:oldboy-14 pass:d38ad8a6
user:oldboy-15 pass:5c60ead2

3、MySQL分表分库备份

3.1 分库备份

[root@node4 for]# cat mysql_bak.sh 
#!/bin/bash

myuser="root"
mypass="oldboy123"
mycmd="mysql -u$myuser -p$mypass"
mydump="mysqldump -u$myuser -p$mypass"

for database in oldboy hellodb zabbix
do
    $mydump $database | gzip > /backup/${database}_$(date +%F).sql.gz
done

[root@node4 backup]# ls
hellodb_2018-03-05.sql.gz  oldboy_2018-03-05.sql.gz  zabbix_2018-03-05.sql.gz


备份所有数据库,单库备份:
[root@node4 for]# cat mysql_bak01.sh
#!/bin/bash

myuser="root"
mypass="oldboy123"
mycmd="mysql -u$myuser -p$mypass"
mydump="mysqldump -u$myuser -p$mypass"


for database in `$mycmd -e "SHOW DATABASES;" | sed '1d'`
do
    $mydump $database | gzip > /backup/${database}_$(date +%F).sql.gz
done


不备份系统库:
for database in `$mycmd -e "SHOW DATABASES;" | sed '1d' | grep -Ev "mysql|information_schema"`

3.2 分表

[root@node4 for]# cat mysql_bak02.sh 
#!/bin/bash

myuser="root"
mypass="oldboy123"
mycmd="mysql -u$myuser -p$mypass"
mydump="mysqldump -u$myuser -p$mypass"


for database in `$mycmd -e "SHOW DATABASES;" | sed '1d' | grep -Ev "mysql|information_schema"`
do
    [ ! -d "/backup/${database}" ] && mkdir -p /backup/${database}
    for table in `$mycmd -e "SHOW TABLES from $database;" | sed '1d'`
    do
	$mydump $database $table | gzip > /backup/${database}/${database}_${table}_$(date +%F).sql.gz
    done
done

[root@node4 backup]# tree /backup/
/backup/
├── hellodb
│   ├── hellodb_classes_2018-03-05.sql.gz
│   ├── hellodb_coc_2018-03-05.sql.gz
│   ├── hellodb_courses_2018-03-05.sql.gz
│   ├── hellodb_scores_2018-03-05.sql.gz
│   ├── hellodb_students_2018-03-05.sql.gz
│   ├── hellodb_teachers_2018-03-05.sql.gz
│   └── hellodb_toc_2018-03-05.sql.gz
├── oldboy
│   ├── oldboy_kecheng_2018-03-05.sql.gz
│   └── oldboy_student_2018-03-05.sql.gz
├── test
└── zabbix
    ├── zabbix_agent_2018-03-05.sql.gz
    └── zabbix_server_2018-03-05.sql.gz