在 bash while 循环中执行远程 ls 时出现问题

在 bash while 循环中执行远程 ls 时出现问题

我需要在单个 BASH 语句中执行以下操作。更喜欢的是,我有四个系统;我们称它们为 A、B、C 和 D。

系统 A 可以通过 SSH 连接到系统 B 和系统 C。

系统 B 可以通过 SSH 连接到系统 D。

从系统 A 运行以下命令:

ssh systemB "cd folder && (while true; do val1=\$(ssh systemD 'ls directory' | wc -l); val2=$(ssh systemC 'ls directory' | wc -l); echo "\$val1 \$val2"; if (( val1 == 0 && val2 == 0 )); then echo "Done"; break; fi; sleep 5; done;)"

循环第一次运行时似乎获得了正确的文件计数。当循环开始后两个目录中的文件计数发生变化时,val1和的值val2似乎保持不变。

答案1

如果systemB不能sshsystemC你就不能在那里有你的循环。它将必须从以下位置驱动systemA

until
  val1=$(ssh -J systemB systemD "ls -q directory | wc -l")
  val2=$(ssh systemC "ls -q directory | wc -l")
  echo "$val1  $val2"
  [ "$val1" -eq 0 ] && [ "$val2" -eq 0 ]
do
  sleep 5
done
echo Done

还:

  • 添加-qls没有它你也可以计算文件名中的换行符。只要它只是检查数字是否非零,这里并不是真正的问题。
  • 在远程进行计数 ( wc -l) 以避免传输整个文件列表。
  • 更清楚退出条件是什么。
  • 使用-J systemB用作systemB主持人。请注意,身份验证仍然使用凭据(ssh 代理或密钥)systemC完成。systemA要使用systemB's,请执行:ssh systemB 'ssh systemD "ls -q directory | wc -l"'

您可以使用 which 在第一个匹配处停止,而不是计算文件数,ls | grep -q '^'并且如果 systemD 上有文件,还可以避免 sshing 到 systemC:

while
  ssh -J systemB systemD "ls -U directory | grep -q \^" ||
    ssh systemC "ls -U directory | grep -q \^"
do
  sleep 5
done
echo Done

(假设 GNUls具有-U跳过排序的选项,这意味着ls可以在从目录读取文件名时开始输出文件名)

使用 ssh 控制套接字还可以避免在每次运行时进行昂贵的 ssh 连接和身份验证。

答案2

如果您编写像下面这样的代码,而不是一大堆单行代码,您会立即看到问题所在。

ssh systemB "cd folder &&
            (while true; do
                val1=\$(ssh systemD 'ls directory' | wc -l); 
                val2=$(ssh systemC 'ls directory' | wc -l); 
                echo "\$val1  \$val2"; 
                if (( val1 == 0 && val2 == 0 )); then 
                    echo "Done"; 
                    break; 
               fi; 
               sleep 5; 
            done;)"

您在 的行中\缺少了。因此,是在完成时创建的,而不是作为循环的一部分。$val2val2ssh systemB

因此,如果当您启动此命令时,$(ssh systemC 'ls directory' | wc -l)值为 10,则循环将为

ssh systemB "cd folder &&
            (while true; do
                val1=\$(ssh systemD 'ls directory' | wc -l); 
                val2=10; 
                echo "\$val1  \$val2"; 
                if (( val1 == 0 && val2 == 0 )); then 
                    echo "Done"; 
                    break; 
               fi; 
               sleep 5; 
            done;)"

相关内容