bash - 如何使用 sshpass 和单个 ssh 登录正确地迭代列表

标签 bash sshpass

情况:我们将文件名列表提供给 sshpass,它会正确地迭代远程文件夹以检查给定名称的文件是否实际存在,然后构建一个仅包含确实存在的文件的更新列表,即稍后在 bash 脚本中重用。

问题:该列表有时包含数以万计的文件,这意味着数以万计的 ssh 登录,这会损害性能,有时还会导致我们被自己的安全策略阻止。

预期的解决方案:不要每次都启动 for 循环并调用 sshpass,而是以其他方式执行并将循环传递给唯一的 sshpass 调用。

我必须将列表传递给下面示例测试中的 sshpass 指令:

#!/bin/bash

all_paths=(`/bin/cat /home/user/filenames_to_be_tested.list`)
existing_paths=()

sshpass -p PASSWORD ssh -n USER@HOST bash  -c "'
for (( i=0; i<${#all_paths[@]}; i++ ))
do
  echo ${all_paths[i]}
  echo \"-->\"$i
  if [[ -f ${all_paths[i]} ]]
  then
    echo ${all_paths[i]}
    existing_paths=(${all_paths[i]})
  fi
done
'

printf '%s\n' "${existing_paths[@]}"

这里的问题是它似乎循环(您看到一系列回显的行),但最终它并没有真正迭代 i 并且始终检查/打印同一行。

有人可以帮忙发现这个错误吗?谢谢!

最佳答案

问题在于 bash 首先解析字符串并替换变量。这是在发送到服务器之前发生的。如果你想阻止 bash 这样做,你应该转义每个应该在服务器上执行的变量。

#! /bin/bash

all_paths=(rootfs.tar derp a)

read -sp "pass? " PASS
echo

sshpass -p $PASS ssh -n $USER@$SERVER  "
files=(${all_paths[@]})
existing_paths=()
for ((i=0; i<\${#files[@]}; i++)); do
        echo -n \"\${files[@]} --> \$i\"
        if [[ -f \${files[\$i]} ]]; then
                echo \${files[\$i]}
                existing_paths+=(\${files[\$i]})
        else
                echo 'Not found'
        fi

done
printf '%s\n' \"\${existing_paths[@]}\"

这变得很难快速阅读。然而,有一个我个人喜欢使用的选项。创建函数并将它们导出到服务器以在服务器上执行,从而省略转义大量内容。

#! /bin/bash

all_paths=(rootfs.tar derp a)

function files_exist {
        local files=($@)
        local found=()
        for file in ${files[@]}; do
                echo -n "$file --> "
                if [[ -f $file ]]; then
                        echo "exist"
                        found+=("$file")
                else
                        echo "missing"
                fi
        done
        printf '%s\n' "${found[@]}"
}

read -sp "pass? " PASS
echo

sshpass -p $PASS ssh -n $USER@$SERVER  "
$(typeset -f files_exist)
files_exist ${all_paths[@]}
"

关于bash - 如何使用 sshpass 和单个 ssh 登录正确地迭代列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59387553/

相关文章:

linux - rlwrap 在后台运行时挂起作业

python - 试图让 Anaconda3 在 Mac 上运行

linux - Docker 环境变量未正确传递

bash - 如何保存ssh登录欢迎横幅并断开连接

ssh - GitLab CI : SSH fail, 无法验证私钥

bash -/bin/sh : No such file or directory when setting a docker-compose entrypoint

bash - 如何使 bash 扩展变量中的通配符?

linux - sshpass 不适用于 crontab

java - 使用 sshpass ssh 到远程主机并使用 java 获取结果