如何编写Bash脚本循环读取命令文件并在终端逐行执行?
解决方案
一、纯Bash无法实现你的需求
纯Bash脚本运行时会创建子Shell,它无法直接向当前活跃的父终端窗口输入内容并模拟回车操作。特别是涉及多层SSH登录的场景,直接在Bash脚本里执行ssh命令会让脚本阻塞,直到你手动退出远程连接,后续命令才会继续执行,完全不符合你的要求。
二、可行的实现方案
1. 使用expect工具(推荐,适合交互式命令场景)
expect是专门处理交互式命令行的工具,能模拟用户输入、等待预期输出,完美适配多层SSH登录的场景。
示例脚本
假设你的命令文件是commands.txt,每行一条命令,比如:
ssh user@machine1_ip logout ssh user@machine2_ip sudo su - echo "hello from machine2" logout
编写auto_run.exp脚本:
#!/usr/bin/expect # 打开命令文件 set cmd_file [open "commands.txt" r] set commands [split [read $cmd_file] "\n"] close $cmd_file # 循环执行每条命令 foreach cmd $commands { if {$cmd eq ""} { continue } # 跳过空行 send "$cmd\r" # 发送命令+回车 # 等待命令执行后的提示符(根据你的终端提示符调整,比如"$ "或"# ") expect -re {\$ |# } } interact # 最后让用户接管终端
使用步骤:
- 安装expect:
sudo apt install expect(Debian/Ubuntu)或sudo yum install expect(CentOS/RHEL) - 给脚本加执行权限:
chmod +x auto_run.exp - 在终端中运行:
./auto_run.exp
2. 使用xdotool工具(模拟键盘输入,适合向当前活跃终端输入)
xdotool可以模拟键盘和鼠标操作,直接向当前聚焦的终端窗口输入命令并回车。
示例Bash脚本
#!/bin/bash CMD_FILE="commands.txt" while IFS= read -r cmd; do if [[ -z "$cmd" ]]; then continue; fi # 模拟输入命令,delay控制输入速度,避免终端跟不上 xdotool type --delay 100 "$cmd" # 模拟按下回车 xdotool key Return # 等待命令执行完成(根据实际命令耗时调整sleep时长) sleep 2 done < "$CMD_FILE"
使用步骤:
- 安装xdotool:
sudo apt install xdotool(Debian/Ubuntu)或sudo yum install xdotool(CentOS/RHEL) - 给脚本加执行权限:
chmod +x auto_run.sh - 先点击激活要输入的终端窗口,再运行脚本:
./auto_run.sh
三、关于多层SSH的额外建议
如果不想用嵌套SSH命令,还可以通过配置~/.ssh/config简化多层登录,比如:
Host machineC User user_O HostName remote_machine_C_ip ProxyJump user_O@remote_machine_P_ip,user_B@remote_machine_B_ip
之后直接执行ssh machineC就能自动完成多层跳转,命令文件里只需要写ssh machineC和后续操作即可,大幅降低复杂度。
内容的提问来源于stack exchange,提问作者Tms91
相关产品推荐
相关产品推荐

