如何解决Shell 脚本可以逐行读取文件,但不能对每一行执行操作
我正在尝试在多台机器上运行此命令
sshpass -p 'nico' ssh -o 'StrictHostKeyChecking=no' nico@x.x.x.x "mkdir test"
IP 存储在以下 .txt 文件中
$ cat ips.txt
10.0.2.15
10.0.2.5
我创建了一个 bash 脚本来逐行读取这个文件。如果我使用 echo
运行它:
#!/bin/bash
input="ips.txt"
while IFS= read -r line
do
echo "$line"
#sshpass -p 'nico' ssh -o 'StrictHostKeyChecking=no' nico@$line "mkdir test"
done < "$input"
它打印每一行:
$ ./variables.sh
10.0.2.15
10.0.2.5
这让我明白脚本正在按预期工作。但是,当我用我想为每一行运行的命令替换 echo
行时:
#!/bin/bash
input="ips.txt"
while IFS= read -r line
do
#echo "$line"
sshpass -p 'nico' ssh -o 'StrictHostKeyChecking=no' nico@$line "mkdir test"
done < "$input"
解决方法
通过使用 for
而不是 while
设法解决了这个问题。脚本最终看起来像这样:
for file in $(cat ips.txt)
do
sshpass -p 'nico' ssh -o 'StrictHostKeyChecking=no' nico@$file "mkdir test"
done
,
虽然你的例子是一个有效的解决方案,但它不是解释。
你可以在这里找到解释:ssh breaks out of while-loop in bash
两个字:
- "while" 循环继续从循环标头中定义的相同文件描述符(在您的情况下为 $input )中读取
- ssh(或 sshpass)从标准输入读取数据(但在你的情况下是从文件描述符 $input)。这是隐藏内容的关键,因为我们没有执行“ssh”来读取数据。
只是为了理解这个问题,您可能会遇到同样奇怪的经历,例如在 while 循环中使用“ffmpeg”或“mplayer”等命令。 Mplayer 和 ffmpeg 在运行时使用键盘,因此它们将消耗所有文件描述符。
另一个有趣而有趣的例子:
#!/bin/bash
{
echo first
for ((i=0; i < 16384; i++)); do echo "testing"; done
echo "second"
} > test_file
while IFS= read -r line
do
echo "Read $line"
cat | uptime > /dev/null
done < test_file
在第一部分我们写第一行:第一 16384 行:测试 然后最后一行:第二个
16384 行“测试”等于 128Kb 缓冲区
在第二部分,命令“cat | uptime”将消耗恰好 128Kb 的缓冲区,因此我们的脚本将给出
Read first
Read second
作为解决方案,正如您所做的那样,我们可以使用“for”循环。 或者使用“ssh -n” 或者使用一些文件描述符 - 您可以在我提供的链接中找到示例。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。