目录
示例2:打印出下面语句中字符数不大于6的单词 rabbit is favorite to eat cabbage
实验3:使用for实现批量主机root密码的修改,成功或失败都必须记录
1.步进循环语句for
for
循环是最简单,也是最常用的循环语句。与其他的程序设计语言一样,
for
循环都是初学者在学
习循 环结构时的入门课程。for
循环通常用于遍历整个对象或者数字列表。按照循环条件的不同,
for
循环语 句可以分为带列表的for
循环、不带列表的
for
循环以及类
C
风格的
for
循环。
1.1带列表的for循环语句
带列表的
for
循环通常用于将一组语句执行已知的次数,其基本语法如下:
for variable in listdostatement1statement2...done
在上面的语法中,
variable
称为循环变量,
list
是一个列表,可以是一系列的数字或者字符串,元素
之间使用空格隔开。do
和
done
之间的所有的语句称为循环体,即循环结构中重复执行的语句。
for
循环体的 执行次数与list
中元素的个数有关。在带列表的
for
语句执行时,
Shell
会将
in
关键字后面的
list
列表的第
1个元素的值赋给变量variable
,然后执行循环体;当循环体中的语句执行完毕之后,
Shell
会将列表中的第2
个元素的值赋给变量
variable
,然后再次执行循环体。当
list
列表中的所有的
元素都被访问后,
for
循环结构终止,程序将继续执行done
语句后面的其他的语句。
示例1:直接列出变量列表所有元素
方法1:直接列出元素方法
[root@localhost test5]# vim list.sh
#!/bin/bash
for IP in 192.168.1.101 192.168.1.102
do
echo $IP
done
[root@localhost test5]# chmod +rx list.sh
[root@localhost test5]# ./list.sh
192.168.1.101
192.168.1.102
方法2:使用大括号
[root@localhost test5]# vim list2.sh
#!/bin/sh
for IP in 192.168.1.10{1..5}
do
echo $IP
done
[root@localhost test5]# chmod +x list2.sh
[root@localhost test5]# ./list2.sh
192.168.1.101
192.168.1.102
192.168.1.103
192.168.1.104
192.168.1.105
方法3:使用seq
[root@localhost test5]# vim list3.sh
for IP in $(seq -f "192.168.1.10%1g" 1 5)
do
echo $IP
done
[root@localhost test5]# chmod +x list3.sh
[root@localhost test5]# ./list3.sh
192.168.1.101
192.168.1.102
192.168.1.103
192.168.1.104
192.168.1.105
说明:seq的用法如下
[root@localhost test5]# seq -f 'hello%03g' 1 2
hello001
hello002
示例2:打印出下面语句中字符数不大于6的单词 rabbit is favorite to eat cabbage
[root@localhost test5]# cat 3.sh
for n in rabbit is favorite to eat cabbage
do
if [ `expr length $n` -le 6 ]
then
echo $n
fi
done
[root@localhost test4]# ./3.sh
rabbit
is
to
eat
Shell
允许用户指定
for
语句的步长。当用户需要另外指定步长时,其基本语法如下:
for varibale in {start..end..step}dostatement1statement2...done
示例3:通过for循环,计算100以内奇数的和
[root@localhost test5]# cat 3.sh
#!/bin/bash
sum=0;
for i in {1..100..2}
do
let "sum+=i"
done
echo "the sum is $sum"
[root@localhost test5]# ./3.sh
the sum is 2500
1.2 不带列表的for循环语句
在某些特殊情况下,
for
循环的条件列表可以完全省略,称为不带列表的
for
循环语句。如果没有为
for
循环提供条件列表,Shell
将从命令行获取条件列表。不带列表的
for
循环语句的一般语法如下:
for variabledostatement1statement2...done
由于系统变量$@同样可以获取所有的参数,所以以上的语法等价于以下语法:
for variable in $@ 或 $*dostatement1statement2...done
示例4:
[root@localhost test5]# vim 1.sh
#!/bin/bash
for arg
do
echo $arg
done
[root@localhost test5]# bash 1.sh {1..6}
1
2
3
4
5
6
1.3 类C风格的for循环语句
for ((expression1;expression2;expression3))dostatement1;statement2;...done
在上面的语法中,
for
循环语句的执行条件被
2
个圆括号包括起来。执行条件分为
3
个部分,由
2
个分
号隔开,第1
部分
expression1
通常是条件变量初始化的语句;第
2
部分
expression2
是决定是否执行
for
循环的条件。当expression2
的值为
0
时,执行整个循环体;当
expression2
的值为非
0
时,退出
for
循环体。第3
部分,即表达式
expression3
通常用来改变条件变量的值,例如递增或者递减等。
示例5:批量创建用户
用户名以
test
开头,按数字序号变化;
一共添加
30
个账号,即
test01
,
tes02...,test30
用户初始密码为
123456
[root@localhost test5]# vim add_user.sh
#!/bin/bash
for ((i=1;i<=30;i++))
do
if [ $i -lt 10 ]
then
user=test0$i
else
user=test$i
fi
if ! id -u $user &> /dev/null
then
useradd $user
echo "123456" | passwd --stdin $user &> /dev/null
else
echo "$user is exists..."
fi
done
注意:可以简化写法,直接用for带列表的循环,这样就不用for里面嵌套if判断
比如for i in {01..30}
实验1: for创建20用户
用户前缀由用户输入
用户初始密码由用户输入
例如:test01,test10
[root@manager ~]# vim test291.sh
#!/bin/bash
#
#********************************************************************
#Author: Shi
#Date: 2022-12-29
#FileName: test291.sh
#********************************************************************
read -p "请输入用户的前缀:" prefix
read -p "请输入用户的密码:" passwd
for ((i=1;i<=20;i++))
do
user=$prefix$i
if id $user &>/dev/null
then
echo $user 已存在
else
useradd $user
if [ $? -eq 0 ];then
echo "用户创建成功,准备输入密码"
else
echo "用户创建失败"
exit
fi
echo ${passwd} |passwd $user --stdin &>/dev/null
if [ $? -eq 0 ];then
echo "密码输入成功"
else
echo "密码输入失败"
fi
done
运行验证脚本
[root@manager ~]# bash test291.sh
请输入用户的前缀:prefix
请输入用户的密码:passwd
用户创建成功,准备输入密码
密码输入成功
用户创建成功,准备输入密码
密码输入成功
用户创建成功,准备输入密码
密码输入毽爸瓣 挨功
用户创建成功,准备输入密码
密码输入成功
用户创建成功,准备输入密码
密码输入成功
用户创建成功,准备输入密码
密码输入成功
用户创建成功,准备输入密码
密码输入成功
用户创建成功,准备输入密码
密码输入成功
用户创建成功,准备输入密码
密码输入成功
用户创建成功,准备输入密码
密码输入成功
用户创建成功,准备输入密码
密码输入成功
用户创建成功,准备输入密码
密码输入成功
用户创建成功,准备输入密码
密码输入成功
用户创建成功,准备输入密码
密码输入成功
实验2:for ping测试指网段的主机
网段由用户输入,例如用户输入192.168.2 ,则ping 192.168.2.10 --- 192.168.2.20
UP: /tmp/host_up.txt
Down: /tmp/host_down.txt
[root@manager ~]# vim test292.sh
#!/bin/bash
#
#********************************************************************
#Author: Shi
#Date: 2022-12-29
#FileName: test292.sh
#********************************************************************
read -p "请输入网段: " ip
for ((i=120;i<=130;i++))
do
IP="$ip"."$i"
echo $IP
if ping -c 2 -w 0.3 192.168.139.$IP &> /dev/null
then
echo "192.168.139.$IP is up" >>/tmp/host_up.txt
else
echo "192.168.139.$IP is down" >>/tmp/host_down.txt
fi
done
运行验证脚本
[root@manager tmp]# bash test292.sh
请输入网段: 192.168.139
192.168.139.120
192.168.139.121
192.168.139.122
192.168.139.123
192.168.139.124
192.168.139.125
192.168.139.126
192.168.139.127
192.168.139.128
192.168.139.129
192.168.139.130
[root@manager tmp]# cat host_up.txt
192.168.139.128 is up
[root@manager tmp]# cat host_done.txt
192.168.139.120 is down
192.168.139.121 is down
192.168.139.122 is down
192.168.139.123 is down
192.168.139.125 is down
192.168.139.126 is down
192.168.139.127 is down
192.168.139.129 is down
192.168.139.130 is down
实验3:使用for实现批量主机root密码的修改,成功或失败都必须记录
提示:主机IP存放在一个文件中
SSH:实现公钥认证,执行远程中主机命令
实现公钥认证
# ssh-keygen 在用于管理的主上生成密钥对
# ssh-copy-id -i 192.168.2.3
[root@manager ~]# vim test293.sh
#!/bin/bash
#
#********************************************************************
#Author: Shi
#Date: 2022-12-29
#FileName: test293.sh
#********************************************************************
read -p "please input your passwd:" passwd
for i in `cat password.txt`
do
ssh $i "echo "$passwd" | passwd --stdin root"
运行脚本验证
[root@manage 20221229]# bash test293.sh 运行脚本文件
please input your passwd:rookey
ssh: connect to host 192.168.139.131 port 22: No route to host
ssh: connect to host 192.168.139.132 port 22: No route to host
Changing password for user root.
passwd: all authentication tokens updated successfully.
ssh: connect to host 192.168.139.128 port 22: No route to host