在具有 eval 和进程替换的函数之后循环停止

loop stops after a function with an eval and process substitution

上下文

我有一个遍历列表的脚本。在每次迭代中,预计会调用一个构造 'diff' 命令的函数,用于通过 'eval' 比较两个远程文件。

'diff' 命令通过两个进程替换获取其输入,其中每个进程替换通过 'ssh' 执行无密码身份验证(通过 public/private 密钥)获取远程文件。

'diff' 和 'ssh' 执行已经在脚本之外进行了测试,它们工作正常。

代码

这里我 post 我的脚本的一个非常短的版本但是产生了同样的问题:

#!/bin/bash
func(){
   NUM=
   echo "func $NUM"
   COMMAND="diff <(ssh user1@server1 'cat file1' ) <(ssh user2@server2 'cat file2' )"
   eval "${COMMAND}"  1>/dev/null
   RESULT=$?
}

LIST="1
2
3
4
5"

echo "$LIST" | while read NUM ; do
   echo "main $NUM"
   func $NUM
done

预期结果

main 1
func 1
main 2
func 2
main 3
func 3
main 4
func 4
main 5
func 5

问题

脚本在第一次迭代后停止:

main 1
func 1

问题

你知道循环停止的原因吗?以及如何解决?

这不是评估也不是进程替换。这是 ssh.

ssh 默认情况下将 stdin 传递给它在远程服务器上运行的命令(并从远程命令返回 stdout)。这使得在管道中使用成为可能。但是,在这种情况下,您不希望 ssh 触及 stdin,因为您自己在循环中使用它。

您可以轻松地让 ssh 不使用 stdin,方法是使用 -n 命令行选项,或者将 stdin 重定向到 /dev/null :

ssh -n user1@server1 'cat file1'
ssh user1@server1 'cat file1' < /dev/null

后者也适用于调用函数:

echo "$LIST" | while read NUM ; do
   echo "main $NUM"
   func $NUM < /dev/null
done

我想您不想听取关于 eval 的弊端的讲座,但我觉得有必要提及以这种方式使用 eval 可能是不必要的。我假设您这样做是为了构建一个使用进程替换的命令。相反,您可以使用 exec 构建具有进程替换的环境,例如:

exec 10< <(ssh -n user1@server1 'cat file1')