shell之循环
1、for循环
语法结构如下:
1
2
3
4
5shell风格
for 变量名 [ in 取值列表 ]
do
循环体
done1
2
3
4
5C语言风格
for ((初值;条件;步长))
do
循环体
doneeg1:for实现批量主机ping探测。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26[root@centos7 shell]# cat pingtest.sh
!/usr/bin/bash
ip.txt
i=2,3,.....
for i in {2..254}
do
{
ip=192.168.122.$i
# -W1表示1秒超时,-C1表示ping 1次
ping -c1 -W1 $ip &>/dev/null
if [ $? -eq 0 ];then
# tee既显示在屏幕上,又写到文件里面去
echo "$ip" |tee -a ip.txt
fi
}& # 如果这里不加&,那么该执行脚本的进程会被阻塞在这里,ctrl C都没用
done
等待之前所有的后台进程执行结束
wait
echo "finish"
[root@centos7 shell]# time sh pingtest.sh # 执行脚本后,可以查看脚本的运行时间
finish
real 0m1.905s
user 0m0.018s
sys 0m0.974seg2:ping一个文件中的所有主机。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20[root@centos7 shell]# cat ip.txt
10.45.1.10
10.22.11.1
[root@centos7 shell]# cat pingtest2.sh
!/usr/bin/bash
for ip in `cat ip.txt`
do
ping -c1 -W1 $ip &>/dev/null
if [ $? -eq 0 ];then
echo "$ip is up"
else
echo "$ip is down"
fi
done
wait
echo "finish"
[root@centos7 shell]# bash pingtest2.sh
10.45.1.10 is down
10.22.11.1 is down
finisheg3:批量创建账号。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35!/usr/bin/bash
while :
do
read -p "Please enter prefix & password & num[zhu 123456 5]" prefix pass num
echo "user information:
===========
user prefix:$prefix
user pass:$pass
user num:$num
===========
"
read -p "Are you sure?[y/n]" action
if [ "$action" = "y" ];then
break
fi
done
echo "creat user"
seq -w 10等位补齐,01,02......。
for i in {1..$num}是错误的
for i in `seq -w $num`
do
user=$prefix$i
id $user &>/dev/null
if [ $? -eq 0 ];then
echo "$user exists"
else
useradd $user
echo "$pass" |passwd --stdin $user &>/dev/null
if [ $? -eq 0 ];then
echo "$user is created"
fi
fi
doneeg4:从文件中读取账号密码创建账号。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44[root@centos7 shell]# cat user.txt
zhu 123
zhu2 456
[root@centos7 shell]# cat createuser.sh
!/usr/bin/bash
if [ $# -eq 0 ];then
echo "usage: `basename $0` file"
exit 1
fi
if [ ! -f $1 ];then
echo "error file"
exit 2
fi
希望for循环处理文件按回车分割而不是空格或tab
如果不重新定义分隔符为换行符,那么相当于for line in zhu 123 zhu2 456,即循环4次
如果重新定义了分隔符为换行符,那么相当于for line in "zhu 123" "zhu2 456",即循环2次
IFS是for循环内部字段分隔符
IFS=$'\n'
IFS='
'
for line in `cat $1`
do
if [ ${#line} -eq 0 ];then
echo "nothing to do"
continue
fi
user=`echo "$line" |awk '{print $1}'`
pass=`echo "$line" |awk '{print $2}'`
id $user &>/dev/null
if [ $? -eq 0 ];then
echo "user $user already exists"
else
useradd $user
echo "$pass" |passwd --stdin $user &>/dev/null
if [ $? -eq 0 ];then
echo "$user is created"
fi
fi
done
[root@centos7 shell]# bash createuser.sh user.txt
user zhu already exists
user zhu2 already existseg5:for实现批量远程主机ssh配置。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22!/usr/bin/bash
ip.txt内容如下:
10.10.10.10
10.10.10.11
for i in `cat ip.txt`
do
{
ping -c1 -W1 $ip &>/dev/null
if [ $? -eq 0 ];then
搜索以#UserDNS开头的行,换成UserDNS no,或者写成sed -ri '/^#UserDNS/c\UserDNS no'
ssh $ip "sed -ri '/^#UserDNS/cUserDNS no' /etc/ssh/sshd_config"
ssh $ip "sed -ri '/^#GSSAPIAutentication/cGSSAPIAutentication no' /etc/ssh/sshd_config"
ssh $ip "systemctl stop firewalld;systemctl disable firewalld"
ssh $ip "sed -ri '/^SELINUX/cSELINUX=disable' /etc/selinux/config"
ssh $ip "setenforce 0"
fi
}&
done
wait
echo "finish"eg6:计算1+2+……100。
1
2
3
4
5
6!/usr/bin/bash
for i in {1..100}
do
let sum=$sum+$i
done
echo "sum:$sum"
2、while和until循环
while循环语法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21当条件测试成立(条件测试为真,就是返回值为0),执行循环体
while 条件测试
do
循环体
done
死循环
while true
do
循环体
done
while :
do
循环体
done
while [ 1 = 1 ]
do
循环体
doneuntil循环语法:
1
2
3
4
5当条件测试成立(条件测试为假),执行循环体
until 条件测试
do
循环体
doneeg1:while实现批量用户创建。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18!/usr/bin/bash
user.txt的内容如下
zhu
zhu2
zhu3
输入重定向
while read user
do
id $user &>/dev/null
if [ $? -eq 0 ];then
echo "user $user already exits"
else
useradd $user
if [ $? -eq 0 ];then
echo "$user is created."
fi
fi
done < user.txteg2:while实现批量用户创建,指定账号密码。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27!/usr/bin/bash
逐行处理文件的内容,最好优先考虑while,把一行看成变量值,所以要判断空行
user.txt的内容如下
zhu 123
zhu2 456
输入重定向
while read line
do
判断是否为空行
if [ ${#line} -eq 0 ];then
echo "这是空行!!!"
continue
fi
user=`echo $line |awk '{print $1}'`
pass=`echo $line |awk '{print $2}'`
id $user &>/dev/null
if [ $? -eq 0 ];then
echo "user $user already exits"
else
useradd $user
echo "$pass"|passwd --stdin $user &>/dev/null
if [ $? -eq 0 ];then
echo "$user is created."
fi
fi
done < user.txt
echo "all ok"eg3:while实现ping主机探测。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18!/usr/bin/bash
i=2
while [ $i -le 254 ]
do
{
ip=192.168.122.$i
ping -c1 -W1 $ip &>/dev/null # -W1表示1秒超时
if [ $? -eq 0 ];then
echo "$ip is up"
else
echo "$ip is down"
fi
}&
let i++
done
wait # 等待所有的后台进程执行结束,如果不加这里,有些ping执行不成功,就会执行echo "finish"
echo "finish"eg4:while测试远程主机连接。
1
2
3
4
5
6
7!/usr/bin/bash
ip=10.10.10.10
while ping -c1 -W1 $ip &>/dev/null
do
sleep 1
done
echo "$ip is down"eg5:while计算1+2+……100。
1
2
3
4
5
6
7
8!/usr/bin/bash
i=1
while [ $i -le 100 ]
do
let sum=$sum+$i
let i++
done
echo "sum:$sum"eg6:until测试远程主机连接。
1
2
3
4
5
6
7!/usr/bin/bash
ip=10.10.10.10
until ping -c1 -W1 $ip &>/dev/null
do
sleep 1
done
echo "$ip is up"eg7:until实现ping主机探测。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18!/usr/bin/bash
i=2
until [ $i -gt 254 ]
do
{
ip=192.168.122.$i
ping -c1 -W1 $ip &>/dev/null # -W1表示1秒超时
if [ $? -eq 0 ];then
echo "$ip is up"
else
echo "$ip is down"
fi
}&
let i++
done
wait # 等待所有的后台进程执行结束,如果不加这里,有些ping执行不成功,就会执行echo "finish"
echo "finish"eg8:until计算1+2+……100。
1
2
3
4
5
6
7
8!/usr/bin/bash
i=1
until [ $i -gt 100 ]
do
let sum=$sum+$i
let i++
done
echo "sum:$sum"