shell编程-循环
循环分类
# 当型循环
while 当什么情况发生的时候
当什么模式,后面[ 条件 ]
只要条件满足成立时我就循环
循环到这个条件不满足
# 直到型循环
do_until # 很少 压根不用
后面接条件表达式
这个条件只要不满足就一直循环
循环到满足为止
# 通用型循环
for #最常用的
基本while能做的for也能做
死循环:for (( ; ; ))
for循环应用场景
[root@web02 test]# cat 1.txt
www.yys.com xxx
blog.yys.com yyy
zh.yys.com zzz
[root@web02 test]# cat 1.sh
#!/bin/bash
for domain in `cat 1.txt`;do
echo "----------------"
echo $domain
done
[root@web02 test]# sh 1.sh
----------------
www.yys.com
----------------
xxx
----------------
blog.yys.com
----------------
yyy
----------------
zh.yys.com
----------------
zzz
#!/bin/bash
for n in `seq 10`;do
echo "----------------"
echo $n
done
while循环
# 第一种写法
while [ 条件表达式 ]; do
cmd1
cmd2
cmd3
...
done
# 第二种
while [ 条件表达式 ]
do
cmd1
cmd2
cmd3
...
done
## while死循环 while true使用场景多,多数使用
while true;do #条件为真
echo 'heihei'
sleep 1
done
#!/bin/bash
while [ 1 -eq 1 ];do #条件为真
echo 'hoho'
sleep 2
done
#!/bin/bash
while :;do #纯粹的死循环
echo 'haha'
sleep 2
done
while模拟for循环seq10
## while打出1-10
#!/bin/bash
i=1 ## 定义变量i=1
while [ $i -lt 11 ];do ## 变量i小于11时
echo $i ## 打印变量i
((i++)) ## i自增
done
使用while循环实现1加到100的值
#!/bin/bash
i=1
n=0
while [ $i -le 100 ];do
n=$((i + n))
((i++))
done
echo '1-100的总和为:'$n
#!/bin/bash
i=1
n=0
while [ $i -le 100 ];do
((n=i+n))
((i++))
done
echo '1-100的总和为:'$n
直到型循环(忘记他)
until 循环执行一系列命令直至条件为 true 时停止。
until 循环与 while 循环在处理方式上刚好相反。
一般 while 循环优于 until 循环,但在某些时候—也只是极少数情况下,until循环更加有用。
# 第一种写法
until [ 条件表达式 ]; do
cmd1
cmd2
cmd3
...
done
# 第二种
until [ 条件表达式 ]
do
cmd1
cmd2
cmd3
...
done
#!/bin/bash
n=0
until [ $n -gt 10 ];do
echo $n
((n++))
done
for循环语法
- 语法一:无法指定循环次数,表达式有多少内容就循环多少次
for var in 变量表达式;do
cmd1
cmd2
done
for var in 变量表达式
do
cmd1
cmd2
done
# 变量表达式:
1.可以是以空格为分隔符的字符串
2.可以是以空格为分隔符的数字
3.可以是数组
4.可以是命令结果 seq 10
5.可以是文件内容(但是要注意for并不是按行读取,如果每一行都没有空格还行,但是一旦遇到空格就...)
# 例:
## 循环以空格为分隔符的字符串
## 横向排列
#!/bin/bash
for name in "ljy yl hhh";do
echo $name
done
[root@web02 test]# sh 1.sh
ljy yl hhh
## 竖向排列
[root@web02 test]# cat 1.sh
#!/bin/bash
for name in "ljy" "yl" "hhh";do
echo $name
done
[root@web02 test]# sh 1.sh
ljy
yl
hhh
## 循环以空格为分隔符的数字
[root@web02 test]# cat 1.sh
#!/bin/bash
for num in 1 2 3 4 5
do
echo $num
done
[root@web02 test]# sh 1.sh
1
2
3
4
5
for num in {1..10};do
echo $num
done
[root@web02 test]# sh 1.sh
1
2
3
4
5
6
7
8
9
10
for zm in {a..c};do
echo $zm
done
[root@web02 test]# sh 1.sh
a
b
c
## 循环数组
name=("www" "ccc" "bbb" "ddd")
for str in ${name[*]};do
echo $str
done
## 循环命令结果
for file in `ls -1 /`;do
echo $file
done
[root@web02 test]# sh 1.sh
www
ccc
bbb
ddd
for text in `cat /etc/passwd`;do
echo $text
done
[root@web02 test]# sh 1.sh
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP
User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
systemd-network:x:192:192:systemd
Network
Management:/:/sbin/nologin
dbus:x:81:81:System
message
bus:/:/sbin/nologin
polkitd:x:999:998:User
for
polkitd:/:/sbin/nologin
sshd:x:74:74:Privilege-separated
SSH:/var/empty/sshd:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
nginx:x:998:996:Nginx
web
server:/var/lib/nginx:/sbin/nologin
apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin
mysql:x:27:27:MariaDB
Server:/var/lib/mysql:/sbin/nologin
rpc:x:32:32:Rpcbind
Daemon:/var/lib/rpcbind:/sbin/nologin
redis:x:997:995:Redis
Database
Server:/var/lib/redis:/sbin/nologin
tomcat:x:53:53:Apache
Tomcat:/usr/share/tomcat:/sbin/nologin
rpcuser:x:29:29:RPC
Service
User:/var/lib/nfs:/sbin/nologin
nfsnobody:x:65534:65534:Anonymous
NFS
User:/var/lib/nfs:/sbin/nologin
- 语法二:可指定循环次数格式
for((i=1;i<=10;i++));do
echo $i
done
for也可以死循环
for (( ; ; ));do
echo 123
sleep
done
循环控制语句
continue
break
break跳出循环
break命令允许跳出所有循环(终止执行后面的所有循环)。
下面的例子中,脚本进入死循环直至用户输入数字大于5。
要跳出这个循环,返回到shell提示符下,需要使用break命令。
[root@zabbix01 ~]# vim break.sh
#!/bin/bash
while true;do
read -p 'Please Input A Number: ' num
if [ $num -ne 5 ];then
echo "你输入的是 $num"
else
break
fi
done
[root@zabbix01 ~]# sh break.sh
Please Input A Number: 1
你输入的是 1
Please Input A Number: 2
你输入的是 2
Please Input A Number: 3
你输入的是 3
Please Input A Number: 4
你输入的是 4
Please Input A Number: 5
#!/bin/bash
n=0
while [ $n -lt 10 ];do
((n++))
if [ $n -eq 5 ];then
break
fi
echo $n
done
[root@web02 test]# sh break.sh
1
2
3
4
continue 跳出循环
continue命令与break命令类似,只有一点差别,它不会跳出所有循环,仅仅跳出当前循环
。
#!/bin/bash
while true;do
read -p 'Please Input A Number: ' num
if [ $num -ne 5 ];then
echo "你输入的是 $num"
else
continue
fi
done
[root@web02 test]# sh continue.sh
Please Input A Number: 1
你输入的是 1
Please Input A Number: 2
你输入的是 2
Please Input A Number: 3
你输入的是 3
Please Input A Number: 4
你输入的是 4
Please Input A Number: 5
Please Input A Number: 6
你输入的是 6
#!/bin/bash
n=0
while [ $n -lt 10 ];do
((n++))
if [ $n -eq 5 ];then
continue
fi
echo $n
done
[root@web02 test]# sh continue.sh
1
2
3
4
6
7
8
9
10
while读取文件
## 方法一:使用exec读取文件内容,然后进入while循环
#!/bin/bash
exec < 1.txt
while read line;do
echo '---------'
echo $line
done
## 方法二:使用管道符,将文件内容交给while循环
cat 1.txt|while read line_name;do
echo $line_name
echo "------"
done
## 方法三:使用标准输入,将文件内容交给while循环
#!/bin/bash
while read name;do
echo $name
echo "------"
done < 1.txt
while读文件练习
写一个脚本,读取下面文件内容,并算出所有人年龄总和
[root@zabbix01 ~]# cat student.txt
写一个脚本,读取下面文件内容,并算出所有人年龄总和
wyd 0
hhh 1
tls 18
zls 18
yl 2
lyf 0
hyb 8
#!/bin/bash
name_age=0
while read line;do
age=`echo "$line"|awk '{print $2}'`
((name_age+=age))
done < student.txt
echo "所有人年龄总和为:"$name_age
跳板机作业
/etc/passwd
1.传输功能 传输文件
2.登陆框
角色
- 运维 ops 能访问所有的机器
- 开发 dev web01 web02 web03
- 测试 test lb01 lb02
数据库 (user.txt)
用户名 密码 角色
ljy 123 ops
文件传输功能
- 请输入要传输的文件
检查是否有输入
- 要输入传输的目标服务器并支持多个服务器
显示主机清单
+---------+
| web01 |
+---------+
| web02 |
+---------+
| web03 |
+---------+
| lb01 |
+---------+
| lb02 |
+---------+
| db01 |
+---------+
| db02 |
+---------+
| db03 |
+---------+
检测服务器信息
- 内存
- 磁盘
- CPU
查看多台服务器的所有信息
3.远程连接 什么角色能连接什么机器
#!/bin/bash
# 用户数据库信息
user_file="user.txt"
# 登录验证
login() {
read -p "请输入用户名: " username
read -sp "请输入密码: " password
echo
# 从用户列表文件中查找对应的角色
role=$(grep -E "^$username " "$user_file" | awk '{print $3}')
if [[ -z "$role" ]]; then
echo "用户名或密码错误!"
exit 1
fi
echo "登录成功,欢迎您,$username!"
}
# 文件传输功能
file_transfer() {
read -p "请输入要传输的文件路径: " file_path
if [[ -z "$file_path" ]]; then
echo "未输入文件路径!"
return
fi
# 服务器清单
server_list=("web01" "web02" "web03" "lb01" "lb02" "db01" "db02" "db03")
cat >EOF
+---------+
| web01 |
+---------+
| web02 |
+---------+
| web03 |
+---------+
| lb01 |
+---------+
| lb02 |
+---------+
| db01 |
+---------+
| db02 |
+---------+
| db03 |
+---------+
EOF
echo "请选择目标服务器(支持多选,用空格分隔):"
for ((i=0; i<${#server_list[@]}; i++)); do
echo "$((i+1)). ${server_list[i]}"
done
read -p "输入服务器序号(多个序号以空格分隔): " selected_servers
if [[ -z "$selected_servers" ]]; then
echo "未选择目标服务器!"
return
fi
# 检查文件是否存在
if [[ ! -f "$file_path" ]]; then
echo "文件 $file_path 不存在!"
return
fi
IFS=" " read -ra selected_servers_arr <<< "$selected_servers"
for server_index in "${selected_servers_arr[@]}"; do
if [[ "$server_index" -gt 0 && "$server_index" -le ${#server_list[@]} ]]; then
server=${server_list[$((server_index-1))]}
echo "正在传输文件到服务器 $server ..."
# 执行文件传输操作,例如使用 scp 命令
# scp "$file_path" "$server"
echo "传输文件到服务器 $server 完成"
fi
done
}
# 检测服务器信息
check_server_info() {
# 服务器清单
server_list=("web01" "web02" "web03" "lb01" "lb02" "db01" "db02" "db03")
echo "请选择要检测信息的服务器(支持多选,用空格分隔):"
for ((i=0; i<${#server_list[@]}; i++)); do
echo "$((i+1)). ${server_list[i]}"
done
read -p "输入服务器序号(多个序号以空格分隔): " selected_servers
if [[ -z "$selected_servers" ]]; then
echo "未选择服务器!"
return
fi
IFS=" " read -ra selected_servers_arr <<< "$selected_servers"
for server_index in "${selected_servers_arr[@]}"; do
if [[ "$server_index" -gt 0 && "$server_index" -le ${#server_list[@]} ]]; then
server=${server_list[$((server_index-1))]}
echo "正在检测服务器 $server 的信息..."
# 执行服务器信息检测操作,例如使用 ssh 命令远程连接并执行相关命令
# ssh "$server" "free -m; df -h; top -n 1"
echo "服务器 $server 的信息检测完毕"
fi
done
}
# 主程序
login
case "$role" in
"ops")
echo "您是运维角色,可以访问所有的机器"
file_transfer
check_server_info
;;
"dev")
echo "您是开发角色,可以访问 web01、web02 和 web03 机器"
file_transfer
;;
"test")
echo "您是测试角色,可以访问 lb01 和 lb02 机器"
check_server_info
;;
*)
echo "未知角色!"
exit 1
;;
esac