精读笔记 · 第27章 Shell 循环与 expect 交互
大约 4 分钟
精读笔记 · 第27章 Shell 循环与 expect 交互
精读整理自 RHCE9 随堂讲义(原文字版 12 页)|同名视频约 7 节(第02套) 关联知识文件:
分章笔记/01-Linux/02-07-Shell编程、02-05-服务管理与安全
一、for 循环(次数固定/列表遍历)
- 语法:
for 变量 [in 取值列表]; do 循环体; done。 - 取值列表三种:
{1..10}、$(seq 1 10)、seq 10;也可for user in \cat user.txt\ 遍历文件内容。 - 例:批量建 10 个用户
for i in {1..10}; do useradd "user$i"; done。
二、for 实战案例
- 探测全网在线主机:
for i in {2..254}; do ip=192.168.100.$i; ping -c1 -W1 $ip &>/dev/null; if [ $? -eq 0 ]; then echo "$ip" | tee -a ip.txt; fi; done
- 优化:脚本开头
>ip.txt清空;循环体包{ ... } &后台并发 +wait等待全部结束再提示 finish(大幅提速)。
- 按用户列表文件建用户:
for user in \cat $1\;健壮版本:先if [ $# -eq 0 ]提示用法并exit 1,再[ ! -f $1 ]报错exit 2,循环内用id $user判断已存在与否,echo "$pass" | passwd --stdin $user设密码并记录成功/存在。 - 批量改 root 密码(前提:已配好 ssh 密钥免密 + IP 列表文件):循环内先 ping 在线 →
ssh $i "echo $password | passwd --stdin root"→ 按结果写 ok.txt/fail.txt/meigai.txt;同样加{ } &+ wait 并发。
三、while / until(次数不固定)
- while:条件为真时执行:
while 条件; do ...; done;死循环用while :(配 let 自增 + sleep)。 - until:条件为假时执行(直到条件为真停止):
until [[ $i -eq 14 ]]; do let i++; sleep 1; echo $i; done。 - 总结:固定次数/列表用 for;按条件/不定次数用 while/until。
四、expect 自动交互(免人工干预)
- 背景:ssh 首次连接有 yes/no、输密码等交互,人工介入无法自动化 → Expect 按程序提示模拟 stdin。
- 安装:
yum install -y expect tcl tcl-devel。 - 核心命令:
spawn启动程序;expect { "内容" { send "应答\r"; exp_continue } ... }期望并应答(exp_continue继续匹配下一条);interact交还终端给用户;脚本首行#!/usr/bin/expect;set timeout 10设超时。 - 例:自动 ssh 登录:
#!/usr/bin/expect spawn ssh root@192.168.0.111 expect { "yes/no" { send "yes\r"; exp_continue } "password:" { send "666666\r" } } interact - 实战:批量推送公钥——先 ping 扫在线主机 → 循环内
spawn ssh-copy-id $ip+ expect 应答 yes/no 与 password;脚本前置:rpm -q expect未装则装;[ ! -f ~/.ssh/id_rsa ]则ssh-keygen -P "" -f ~/.ssh/id_rsa免交互生成。
五、课后作业参考答案要点(自测用)
- case 判断成绩:
[0-9]/[1-5][0-9]不及格、[6-7][0-9]及格、[8-9][0-9]/100优秀、*越界提示(用通配模式区间)。 - for 建 20 用户(前缀/密码由 read 输入);for 按输入网段 ping(在线→/tmp/host_up.txt,离线→host_down.txt);for+expect 批量改密码并记录成败。
六、命令速查表
| 场景 | 写法 |
|---|---|
| for 列表循环 | for i in {1..10}; do ...; done |
| 遍历文件 | for u in \cat 文件`; do ...; done` |
| while 循环 | while 条件; do ...; done;while : 死循环 |
| until 循环 | until 条件; do ...; done(假时执行) |
| 并发提速 | { 命令 } & + 循环后 wait |
| 判断退出码 | $? -eq 0 |
| 免交互生成密钥 | ssh-keygen -P "" -f ~/.ssh/id_rsa |
| expect 登录 | spawn/expect/send/exp_continue/interact |
七、易错点
for i in {1..10}花括号展开不支持变量:{1..$n}无效,要用seq。- ping 探测务必
-c1 -W1(只发 1 包、超时 1 秒),否则全网扫描极慢。 - 循环里跑网络命令记得
{ } &+wait,否则 253 台串行要等几分钟。 - passwd 设密码要
echo 密码 | passwd --stdin 用户(或 chpasswd);忘接 stdin 会卡交互。 - while 条件为真执行、until 条件为假执行,别记反。
- expect 脚本首行
#!/usr/bin/expect且要send "xxx\r"(回车符 \r);交互匹配不到会超时卡死,可加set timeout。
八、实操清单
for 批量建 10 用户 → 扫网段在线主机(串行版→并发版对比耗时)→ 按文件建用户(参数校验+存在判断)→ while/until 计时器 → expect 自动 ssh 登录 → expect 批量推送公钥脚本(含前置安装与密钥生成)。
九、本章自测
- for 三种取值列表写法?2. while 与 until 执行条件区别?3. 如何给循环加并发并等待?4. expect 五个关键字(spawn/expect/send/exp_continue/interact)各自作用?5. ssh-keygen 免交互生成密钥参数?6. 批量改密脚本如何记录成功/失败主机?
