CentOS系统中BASH脚本While循环无法正常执行求助
问题原因
脚本循环仅执行一次就退出的核心原因是**ssh和scp命令会默认读取标准输入(stdin)**,而你的while read循环正从$clientlist读取stdin。当第一个客户端的远程命令执行时,这些命令会把$clientlist中剩余的客户端条目当作自己的输入消耗掉,导致read命令提前读到文件末尾,循环直接终止。
解决方案
有两种常用修复方式,任选其一即可:
方法1:禁止ssh/scp读取标准输入
给所有ssh和scp命令加上-n参数,该参数会将它们的stdin重定向到/dev/null,避免干扰循环的read操作。同时注意你脚本中mv命令的语法错误(原命令缺少目标参数):
while read client; do echo "Running configuration on $client" echo "-------------------------------------------------------------------" sshpass -p XXXXXXXXXXXXX ssh-copy-id -n root@$client ssh -n root@$client "mkdir /etc/yum.repos.d/repo-backup" ssh -n root@$client "mv /etc/yum.repos.d/* /etc/yum.repos.d/repo-backup/" scp -n local.repo root@$client:/etc/yum.repos.d/ # 修正mv命令:需要指定源和目标 ssh -n root@$client "mv /etc/yum/pluginconf.d/rhnplugin.conf /etc/yum/pluginconf.d/rhnplugin.bkp" scp -n rhnplugin.conf root@$client:/etc/yum/pluginconf.d/ ssh -n root@$client "yum clean all" ssh -n root@$client "rm -rf /var/cache/yum" ssh -n root@$client "yum repolist" done < $clientlist
方法2:使用独立文件描述符读取客户端列表
将while read的输入重定向到自定义文件描述符(比如3),让循环从该描述符读取内容,和ssh/scp的stdin彻底隔离:
# 使用文件描述符3读取客户端列表 while read -u 3 client; do echo "Running configuration on $client" echo "-------------------------------------------------------------------" sshpass -p XXXXXXXXXXXXX ssh-copy-id root@$client ssh root@$client "mkdir /etc/yum.repos.d/repo-backup" ssh root@$client "mv /etc/yum.repos.d/* /etc/yum.repos.d/repo-backup/" scp local.repo root@$client:/etc/yum.repos.d/ # 修正mv命令语法 ssh root@$client "mv /etc/yum/pluginconf.d/rhnplugin.conf /etc/yum/pluginconf.d/rhnplugin.bkp" scp rhnplugin.conf root@$client:/etc/yum/pluginconf.d/ ssh root@$client "yum clean all" ssh root@$client "rm -rf /var/cache/yum" ssh root@$client "yum repolist" done 3< $clientlist
补充说明
你的测试脚本仅包含echo命令,不会读取stdin,因此循环能正常遍历所有客户端。而实际脚本中的ssh/scp会抢占stdin,这就是两者行为差异的根本原因。
内容的提问来源于stack exchange,提问作者Kat Fitzgerald
相关产品推荐
相关产品推荐

