shell—for循环
文章目录
- shell—for循环
- 1.for循环基本概述
- 1.1 什么是循环
- 1.2 什么是for循环
- 2.for循环基础语法
- 3.for循环练习题
1.for循环基本概述
1.1 什么是循环
脚本在执行任务的时候,总会遇到需要循环执行的时候,比如说我们需要脚本每隔五分钟执行一次ping操作,除了计划任务,我们还可以使用循环语句
1.2 什么是for循环
很多人把for循环叫做条件循环,因为for循环的次数和给予的条件是成正比的,也就是给你几个条件,就会循环几次
2.for循环基础语法
1.for循环基础语法示例
#for循环语法 for循环示例(默认以空格做分隔)
for 变量名 in [ 取值列表 ] for var in file1 file2 file3
do do循环体 echo the text is $var
done done
2.for循环基本使用示例,列表中的复杂值,可以使用引号或转义字符"/"来加以约束
[root@manage for]# cat for02.sh
#!/bin/bash
for var in file1 "file2 file3" file4 "hello world"
doecho the text is $var
done[root@manage for]# sh for02.sh
the text is file1
the text is file2 file3
the text is file4
the text is hello world[root@manage for]# cat for03.sh
#!/bin/bash#下面两种写法意思相同
#for var in {1..5}
for var in $(seq 5)
doecho $var
done[root@manage for]# sh for03.sh
1
2
3
4
5[root@manage for]# cat for04.sh
#!/bin/bash
for var in file1 file\'2 I\'s
doecho $var
done[root@manage for]# sh for04.sh
file1
file'2
I's
3.for循环,从变量中取值
[root@manage for]# cat for05.sh
#!/bin/bash
list="file1 file2 file3"
for i in $list
doecho "$i"
done
4.for循环,从文件中取值
[root@manage for]# cat /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6#如果是行文件,会直接以空格为分隔符,按列打印出来
[root@manage for]# cat for06.sh
for i in $(cat /etc/hosts)
doecho $i
done[root@manage for]# sh for06.sh
127.0.0.1
localhost
localhost.localdomain
localhost4
localhost4.localdomain4
::1
localhost
localhost.localdomain
localhost6
localhost6.localdomain6
5.for循环基本使用示例,自定义shell分隔符,默认情况以空格作为分隔符,通过IFS来自定义为分隔符
#以冒号做分隔符 IFS=:
#以冒号、分号和双引号作为字段分隔符 IFS=:;"
#以换行符作为字段分隔符 IFS=$'\n'[root@manage for]# cat for06.sh
#!/bin/bash
IFS=$'\n'
for i in $(cat /etc/hosts)
doecho $isleep 1
done[root@manage for]# sh for06.sh
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6#读取文件中信息,并且以冒号为分隔符
[root@manage for]# cat for07.sh
#!/bin/bash
IFS=: #以冒号做为分隔符
list=`head -1 /etc/passwd`
for i in $list
doecho $i
done[root@manage for]# sh for07.sh
root
x
0
0
root
/root
/bin/bash
6.for循环基本使用示例,C语言风格的for
#语法格式
for (( i=0;i<10;i++))
docommands
done[root@manage for]# cat for08.sh
#!/bin/bash
for (( i=0;i<10;i++))
doecho num is $i
done[root@manage for]# sh for08.sh
num is 0
num is 1
num is 2
num is 3
num is 4
num is 5
num is 6
num is 7
num is 8
num is 9#常规写法
[root@manage for]# cat for09.sh
#!/bin/bash
a=1
b=9
for i in $(seq 9)
doecho num is $a $blet a++let b--
done[root@manage for]# sh for09.sh
num is 1 9
num is 2 8
num is 3 7
num is 4 6
num is 5 5
num is 6 4
num is 7 3
num is 8 2
num is 9 1#c语言的写法
[root@manage for]# cat for10.sh
#!/bin/bash
for (( a=1,b=9;a<10;a++,b-- ))
doecho num is $a $b
done[root@manage for]# sh for10.sh
num is 1 9
num is 2 8
num is 3 7
num is 4 6
num is 5 5
num is 6 4
num is 7 3
num is 8 2
num is 9 1
3.for循环练习题
需求1:用for循环探测某个网段主机存活状态,将存活的主机存入ok.txt
[root@manage for]# cat for11.sh
#!/bin/bashfor i in {1..254}
do#加{}&并行处理{ip=10.0.0.$iping 10.0.0.$i -W1 -c1 &>/dev/nullif [ $? -eq 0 ];thenecho "$ip 存活"fi}&
donewait #上面循环执行完后在退出
需求2:判断主机存活状态,判断三次,如果三次都失败,则退出,将结果输出到文件中
[root@manage for]# cat for12.sh
#!/bin/bash
for i in {1..254}
do{ip=10.0.0.$iping 10.0.0.$i -W1 -c1 &>/dev/nullif [ $? -eq 0 ];thenecho "$ip 存活" >> ok.txtelsefor j in {1..3}doping 10.0.0.$i -W1 -c1 &>/dev/nullif [ $? -eq 0 ];thenecho "$ip 存活" >> ok.txtelse echo "$ip 不存活" >> err.txtfidonefi}&
donewait #上面循环执行完后在退出
需求3:有2个文件,一个ip文件,一个端口文件,探测ip的那个端口通
现在有一个ip.txt的文件,里面有很多IP地址。还有一个port.txt的文件,里面有很多端口号。现在希望对ip.txt的每个IP地址进行端口的探测,探测的端口号来源于port.txt文件中最后将开放的端口和IP保存到一个ok.txt文件。#需要安装nc命令:yum install nc -y
#用nc探测,结果输出echo $?=0,则端口为通,如果不为0则为不通
nc -z -w 1 10.0.0.201 22
[root@manage for]# cat ip.txt
10.0.0.1
10.0.0.2
10.0.0.3
10.0.0.4
10.0.0.5
10.0.0.6
10.0.0.7
10.0.0.8
10.0.0.201
172.16.1.5
192.168.10.1
192.168.10.99[root@manage for]# cat port.txt
80
22
8080
9000
3306
23
443
6379
10050
10051
10052[root@manage for]# cat for13.sh
#!/bin/bash
#遍历文件中的ip地址
for ip in $(cat ip.txt)
do{#第二次循环,遍历文件中的端口for port in $(cat port.txt)do#探测ip与端口的存活状态nc -z -w 1 $ip $port &>/dev/nullif [ $? -eq 0 ];thenecho "$ip 的 $port端口存活"fidone}&
donewait[root@manage for]# sh for13.sh
10.0.0.201 的 80端口存活
10.0.0.201 的 22端口存活
10.0.0.201 的 3306端口存活
10.0.0.201 的 10050端口存活
10.0.0.201 的 10051端口存活
10.0.0.201 的 10052端口存活
10.0.0.1 的 443端口存活
10.0.0.1 的 10050端口存活
需求4:获取系统的所有用户并输出
效果如下:
This is 1 user: root
This is 2 user: bin
This is 3 user: daemon
This is 4 user: adm
...............1.怎么获取所有的用户 awk -F ":" '{print $1}'2.遍历/etc/passwd 这个文件3.如何让数字的编号进行自增[root@manage for]# cat for14.sh
#!/bin/bash
i=1
for user in $(awk -F ':' '{print $1}' /etc/passwd)
doecho This is $i $user#下面两种自增用法,熟悉那种用那种#let i++i=$[ $i + 1 ]
done[root@manage for]# sh for14.sh
This is 1 root
This is 2 bin
This is 3 daemon
This is 4 adm
This is 5 lp
This is 6 sync
This is 7 shutdown
This is 8 halt
.......
需求5:批量创建100个用户,比如输入test则会创建test001-100
#怎么输出001-100 seq -w 1 100[root@manage for]# cat for15.sh
#!/bin/bash
for user in $(seq -w 1 100)
douseradd $1$user &>/dev/null echo $1$user 创建成功
done[root@manage for]# sh for15.sh test
test001 创建成功
test002 创建成功
test003 创建成功
test004 创建成功
test005 创建成功
.......#如果用户创建,则跳过,加判断
[root@manage for]# cat for16.sh
#!/bin/bashfor user in $(seq -w 1 100)
do#判断用户已存在,则输出用户存在,如果不存在,则创建id $1$user &>/dev/nullif [ $? -eq 0 ];thenecho $1$user用户已经存在elseuseradd $1$user &>/dev/null echo $1$user 创建成功fi
done[root@manage for]# useradd aaa5
[root@manage for]# sh for16.sh aaa
aaa1 创建成功
aaa2 创建成功
aaa3 创建成功
aaa4 创建成功
aaa5用户已经存在#另一种写法
[root@manage for]# cat for17.sh
#!/bin/bash
for user in $(seq -w 1 10)
doid $1$user &>/dev/nullif [ $? -ne 0 ];thenuseradd $1$userecho "$1$user is ok"else#表示结束当前本次的循环,直接开始下一次循环continuefi
done
需求6:
批量创建用户脚本,需要用户输入创建的用户数量,以及需要用户输入创建的前缀。例如:前缀qq,个数10,代表创建qq1~qq10,总共10个用户。[root@manage for]# cat for18.sh
#!/bin/bash
read -p "请输入你要创建的用户名:" qz
read -p "请输入你要创建的用户数量:" hz
read -p "你要创建的用户前缀是$qz,后缀是$hz,你确定要创建吗 [ y | n ] " Actioncase $Action iny|Yes|Y)for num in $(seq 1 $hz)dousername=$qz$numid $username &>/dev/nullif [ $? -ne 0 ];thenuseradd $usernameecho "$username用户创建成功"else#表示结束当前本次的循环,直接开始下一次循环continuefidone;;n)echo "不创建用户"exit 1;;*)echo "请按照提示输入"exit
esac[root@manage for]# sh for18.sh
请输入你要创建的用户名:qq
请输入你要创建的用户数量:10
你要创建的用户前缀是qq,后缀是10,你确定要创建吗 [ y | n ] y
qq1用户创建成功
qq2用户创建成功
......
需求7:批量创建用户脚本,需要用户输入创建的用户数量(必须是整数),同时还需要用户输入前缀(前缀不能为空)。
[root@manage for]# cat for19.sh
#!/bin/bash
read -p "请输入你要创建的用户名:" qz
if [ -z $qz ];thenecho "请不要输入空值...."exit
firead -p "请输入你要创建的用户数量:" hz
if [[ ! $hz =~ ^[0-9]+$ ]];thenecho "请输入数字....."exit
fi
read -p "你要创建的用户前缀是$qz,后缀是$hz,你确定要创建吗 [ y | n ] " Actioncase $Action iny|Yes|Y)for num in $(seq 1 $hz)dousername=$qz$numid $username &>/dev/nullif [ $? -ne 0 ];thenuseradd $usernameecho "$username用户创建成功"else#表示结束当前本次的循环,直接开始下一次循环continuefidone;;n)echo "不创建用户"exit 1;;*)echo "请按照提示输入"exit
esac[root@manage for]# sh for19.sh
请输入你要创建的用户名:
请不要输入空值....
[root@manage for]# sh for19.sh
请输入你要创建的用户名:aaaa
请输入你要创建的用户数量:
请输入数字.....
需求8:循环批量创建用户,需要填入用户的数量、用户的前缀、用户的统一密码(使用read、case、for语句)
[root@manage for]# cat for20.sh
#!/bin/bashread -p "请输入你要创建的用户名:" qz
if [ -z $qz ];thenecho "请不要输入空值...."exit
firead -p "请输入你要创建的用户数量:" hz
if [[ ! $hz =~ ^[0-9]+$ ]];thenecho "请输入数字....."exit
fi
read -p "你要创建的用户前缀是$qz,后缀是$hz,你确定要创建吗 [ y | n ] " Action#输入设置的密码
read -p "给用户设置密码:" pw
case $Action iny|Yes|Y)for num in $(seq 1 $hz)dousername=$qz$numid $username &>/dev/nullif [ $? -ne 0 ];thenuseradd $username#直接给创建的用户输入统一密码echo "$pw" | passwd --stdin $usernameecho "$username用户创建成功,密码是$pw"else#表示结束当前本次的循环,直接开始下一次循环continuefidone;;n)echo "不创建用户"exit 1;;*)echo "请按照提示输入"exit
esac[root@manage for]# sh for20.sh
请输入你要创建的用户名:ww
请输入你要创建的用户数量:2
你要创建的用户前缀是ww,后缀是2,你确定要创建吗 [ y | n ] y
给用户设置密码:123456
Changing password for user ww1.
passwd: all authentication tokens updated successfully.
ww1用户创建成功,密码是123456
Changing password for user ww2.
passwd: all authentication tokens updated successfully.
ww2用户创建成功,密码是123456
[root@manage for]# su - ww1
[ww1@manage ~]$ su - ww2
Password:
[ww2@manage ~]$ su - root
Password:
Last login: Thu Apr 21 08:07:16 CST 2022 from 10.0.0.1 on pts/1
需求9:通过读入文件中的用户,进行批量添加用户
[root@manage for]# cat user.txt
aaaa
bbbb
cccc[root@manage for]# cat for21.sh
#!/bin/bash
for user in $(cat user.txt)
douseradd $user
done[root@manage for]# sh for21.sh
[root@manage for]# id aaaa
uid=1319(aaaa) gid=1319(aaaa) groups=1319(aaaa)
[root@manage for]# id bbbb
uid=1320(bbbb) gid=1320(bbbb) groups=1320(bbbb)
[root@manage for]# id cccc
uid=1321(cccc) gid=1321(cccc) groups=1321(cccc)
10.通过读入文件中的用户与密码文件,进行批量添加用户。文件中的格式: user:passwd
[root@manage for]# cat user.txt
ddaaaa:11111
ddbbbb:111111
ddcccc:22222[root@manage for]# cat for22.sh
#!/bin/bash
for user in $(cat user.txt)
dous=$(echo $user | awk -F ":" '{print $1}')pw=$(echo $user | awk -F ":" '{print $2}')id $us &>/dev/nullif [ $? -eq 0 ];thenecho "$us 已经存在...."continueelseuseradd $us &>/dev/nullecho "$pw" | passwd --stdin $usfi
done[root@manage for]# sh for22.sh
Changing password for user ddaaaa.
passwd: all authentication tokens updated successfully.
Changing password for user ddbbbb.
passwd: all authentication tokens updated successfully.
Changing password for user ddcccc.
passwd: all authentication tokens updated successfully.
需求11:批量创建用户,用户名oldxu01-100 密码随机(8~12), 然后将创建成功的用户名及密码写入到一个文件中.
#创建随机密码:mkpasswd -l 8 (后面数字是几,就创建几位随机密码)dev:dasd1#!@#!@dsa
dev:dascxasdas1!@#[root@manage for]# cat for23.sh
#!/bin/bash
#1.创建10个用户
for user in dev{1..10}
do#2.设定随机密码(for循环一次,就生成一次)pass=$(mkpasswd -l 8)#3.创建用户useradd $userecho "$pass" | passwd --stdin $user &>/dev/null#4.保存每次的用户名和密码#echo "$user:$pass" >> user_pass.txt#这两条命令都可以,只不过tee -a既可以输出到屏幕,也可以输出到文件echo "$user:$pass" | tee -a user_pass.txt
done
需求12:写一个倒计时脚本,从10计数到0
[root@manage for]# cat for25.sh
#!/bin/bash
for i in {10..1}
doecho -n -e "最后倒计时:$i \r"sleep 1
done
需求13:写一个随机点名脚本
[root@manage for]# cat name.txt
何玲
欧文
欧文
徐冬冬
小强
小鹏
小鹏
扎西德勒
冯绍峰
小明
马蓉
张杰
小红
科比
杨幂
王宝强[root@manage for]# cat for26.sh
#!/bin/bashif [ -s name.txt ];then
#不为空,走这里User=$( sort --random-sort name.txt | awk 'NR==1')echo $Usergrep $User name.txt >>name1.txtsed -i '/'$User'/d' name.txt
#如果为空,走下面
elsecat name1.txt >name.txtrm -f name1.txtecho "没有名单" fi
需求14:下载https://mirrors.aliyun.com/zabbix/zabbix/4.0/rhel/7/x86_64/页面中的所有rpm包至本地
[root@manage for]# cat for27.sh
#!/bin/bashcurl https://mirrors.aliyun.com/zabbix/zabbix/4.0/rhel/7/x86_64/ &>url.txtUrl_file=url.txt
Pkg_name=$(grep '<a href=' $Url_file |awk -F '"' '{print $4}' | egrep -v 'channel-title|repodata|debuginfo|\.\./|dropmenu-button am-icon-more')
Get_url=https://mirrors.aliyun.com/zabbix/zabbix/4.0/rhel/7/x86_64/for package in $Pkg_name
do#完整的url地址url_package=$Get_url$package#指定下载到某个目录[ -d /mnt/rpm ] || mkdir /mnt/rpmwget -O /mnt/rpm/$package $url_package &>/dev/nullif [ $? -eq 0 ];thenecho "软件包:$pkg is ok...."elseecho "err......."fi
done
需求15:使用for循环备份mysql库,每个库对应一个sql文件,需要排除没用的
#1.拿到需要的库名称:mysql -uroot -pzabbix -e "show databases" | sed 1d |egrep -v '*_schema|mysql|test'#2.循环拼接备份命令 mysqldump -uroot -pzabbix -B zabbix >/mysql/data/zabbix.sql[root@manage for]# cat for-mysql.sh
#!/bin/bash
db_name=$(mysql -uroot -pzabbix -e "show databases" | sed 1d | egrep -v '*_schema|mysql|test')
Path=/mysql/backup/
Date=$(date +%F)[ -d $Path ] || mkdir -p $Path
for i in $db_name
domysqldump -uroot -pzabbix -B ${i} >$Path/${i}_$Date.sql#if [ $? -eq 0 ];thenif [ -f $Path/${i}_$Date.sql ];thenecho "$db_name库备份ok......"elseecho "$db_name库备份err....."fi
done#保留最近15天的备份数据find $Path -type d -mtime +15 |xargs rm -f
需求16:使用for循环进行分库分表备份
#分库: 值得是多个库分开备份.#分表: 一个库中有多个表,将多个分开备份#备份表mysqldump -u<username> -p<password> dbname tablename1 tablename2... > /path/to/***.sqlmysqldump -uroot -pzabbix zabbix users >/mysql/data/zabbix/2022-04-22/users.sql1.取出所有的库名称2.取出库对应的所有表3.将命令拼接在一起完成备份[root@manage for]# cat for-mysql-tables.sh
#!/bin/bash
db_name=$(mysql -uroot -pzabbix -e "show databases" | sed 1d | egrep -v '*_schema|mysql|test')
Path=/mysql/backup/
Date=$(date +%F)#1.判断备份存放目录是否存在,不存在则创建[ -d $Path ] || mkdir -p $Path
for i in $db_name
do#2.取出对应库的所有表名tables=$(mysql -uroot -pzabbix -e "use $i; show tables;" |sed 1d)for j in $tablesdo#判断对应目录是否存在[ -d $Path/$i/$Date/ ] || mkdir -p $Path/$i/$Date/#执行备份命令mysqldump -uroot -pzabbix $i $j >$Path/$i/$Date/${j}.sqldonedone#保留最近15天的备份数据find $Path/$i/ -type d -mtime +15 | xargs rm -rf
需求17:实现主从同步探测脚本
#配置邮箱
yum install mailx -y
vim /etc/mail.rc
set from=Tareya@163.com
set smtp=smtp.163.com
set smtp-auth-user=Tareya@163.com#
set smtp-auth-password=Tareya4454
set smtp-auth=login
set ssl-verify=ignore
set nss-config-dir=/etc/pki/nssdb/#1.判断IO线程和sql线程是否都为YES,如果是则成功
#2.如果IO线程失败,则直接邮件通知,如果sql线程失败,则检查是什么错误状态码,根据状态码修复
#3.无法修复,或任何错误代码太复杂建议,直接发邮件通知管理员[root@manage for]# cat mysql_slave.sh
#!/bin/bash
IO_Status=$(mysql -uroot -pzabbix -e "show slave status\G"| awk '/Slave_IO_Running/ {print $2}')
SQL_Status=$(mysql -uroot -pzabbix -e "show slave status\G"| awk '/Slave_SQL_Running/ {print $2}')#将结果定义为函数,case中调用函数即可
slave_sql_err_message(){mysql -uroot -pzabbix -e "show slave status\G"|grep "Last_SQL" >/tmp/sql_err.log#发送邮件mail -s "Mysql Master Slave SQL ERROR $(date +%F)" 111222222号@qq.com < /tmp/sql_err.logecho "邮件通知成功"
}slave_io_err_message(){mysql -uroot -pzabbix -e "show slave status\G"|grep "Last_IO" >/tmp/io_err.log#发送邮件mail -s "Mysql Master Slave IO ERROR $(date +%F)" 111222222号@qq.com < /tmp/io_err.logecho "邮件通知成功"
}if [ "$IO_Status" == "YES" ] && [ "$SQL_Status" == "YES" ];thenecho "Mysql 主从正常....."
elseif [ ! $IO_Status == "YES" ];thenslave_io_err_messagefi#2.判断sql异常if [ ! $SQL_Status == "YES" ];thenSQL_ERR=$(mysql -uroot -pzabbix -e "show slave status\G"|awk '/Last_SQL_Erron/ {print $2}')#3.精细化判断主从不同步的问题case $SQL_ERR in1007)echo "主从的SQL线程出现问题,尝试使用set global sql_slave_skip_counter=1跳过错误"sleep 2mysql -uroot -pzabbix -e "stop slave;set global sql_slave_skip_counter=1;start slave;"SQL_ERR1=$(mysql -uroot -pzabbix -e "show slave status\G"|awk '/Last_SQL_Erron/ {print $2}')if [ $SQL_ERR1 -eq 0 ];thenecho "尝试跳过了一次,恢复Mysql数据库成功"elseslave_sql_err_messagefi;;1008)slave_sql_err_message;;1032)slave_sql_err_message;; *)slave_sql_err_messageesacfifi