You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何while循环执行ssh仅返回第一个VM的uname -a结果?

为什么while循环结合SSH只能获取第一台主机的结果?

我需要在多台VM上执行uname -a命令,单独执行SSH时一切正常:

$ ssh srv-13 uname -a
Linux srv-13 4.19.0-6-amd64 #1 SMP Debian 4.19.67-2 (2019-08-28) x86_64 GNU/Linux
$

$ ssh akd4 uname -a
Linux akd4 4.19.0-22-amd64 #1 SMP Debian 4.19.260-1 (2022-09-29) x86_64 GNU/Linux
$ 

尝试用while循环遍历主机列表时,只执行echo命令是正常的:

$ echo 'akd4 srv-13'| tr ' ' '\n'
akd4
srv-13
$

$ echo 'akd4 srv-13'| tr ' ' '\n' |while read i;do echo "==>$i";done
==>akd4
==>srv-13
$

但在循环里加入SSH执行uname -a后,只能得到第一台主机的结果:

$ echo 'akd4 srv-13'| tr ' ' '\n' |while read i;do echo "==>$i"; ssh $i uname -a;done
==>akd4
Linux akd4 4.19.0-22-amd64 #1 SMP Debian 4.19.260-1 (2022-09-29) x86_64 GNU/Linux
$ 

换成for循环就能得到预期的所有主机结果:

$ for i in akd4 srv-13;do ssh $i uname -a  ;done
Linux akd4 4.19.0-22-amd64 #1 SMP Debian 4.19.260-1 (2022-09-29) x86_64 GNU/Linux
Linux srv-13 4.19.0-6-amd64 #1 SMP Debian 4.19.67-2 (2019-08-28) x86_64 GNU/Linux
$ 

问题原因

核心原因是SSH默认会占用标准输入(stdin)。while循环里的read命令是从stdin读取主机列表的每一行,当执行第一个ssh时,ssh会把stdin中剩余的内容(也就是srv-13那一行)当作自己的输入消耗掉,导致后续的read命令再也读不到下一行,循环直接终止。

解决办法

有几种方式可以修复这个问题:

  1. 给SSH加-n参数:这个参数会让SSH不读取stdin,这样read就能正常获取下一行主机名:
echo 'akd4 srv-13'| tr ' ' '\n' |while read i;do echo "==>$i"; ssh -n $i uname -a;done
  1. 重定向SSH的输入到/dev/null:效果和-n参数一致,切断SSH对stdin的占用:
echo 'akd4 srv-13'| tr ' ' '\n' |while read i;do echo "==>$i"; ssh $i uname -a < /dev/null;done
  1. 使用for循环替代:for循环是从命令行参数中读取主机列表,不依赖stdin,因此不会受SSH的影响(就是你已经测试过的有效方法)。

内容的提问来源于stack exchange,提问作者user3313834

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 10:05:29