SSH for 循环:传递给变量中捕获的函数的参数未扩展

SSH for 循环:传递给变量中捕获的函数的参数未扩展

我有几台服务器,其中有几个文件,其中包含我需要解析的部署日期信息,并获取 2 个月或更早的文件的本地副本。

#!/bin/bash

# split on new line not space
# don't want to quote everything
# globbing desired
IFS=$'\n'

servers=(
  blue
  red
)

parseDate() {
    grep 'deploy_date:' $file | \
    sed  ...                  | \
    # much more in here...
}

getOldFiles() {
    local #all vars
    currentDateInSecs=$(date +%s)
    twoMonthsInSecs=526000
    for server in ${servers[@]}; do
        oldfile=$(
          ssh $server "
            $(declare -f parseDate)
            for file in /dir/$server/file*; do
                dateInSecs=$(date -jf '%b/%e/%Y' $(parseDate) +%s)
                timeDiff=$((\$currentDateInSecs - \$dateInSecs))
                ((\$timeDiff >= \$twoMonthsInSecs)) &&
                    cat \$file
            done
          "
        )
        [ -n $oldFile ] &&
            cat $oldFile ~/oldFiles/${server}-${file}.txt
    done

问题:

当前的问题是dateInSecs=$(date -jf '%b/%e/%Y' $(parseDate \$file) +%s).

当 变量parseDate \$file中的 is未扩展时,无需命令替换即可正常工作,但我需要它。$()$file

我该如何解决?

信息:

这不是脚本,它们在我的 ~/.bash_profile 中

这是 git 存储库中的一个脚本(以及其他脚本),它源自~/bash_profile(我有一个使用设置源的安装脚本$PWD),因此人们可以直接使用这些命令,而不是 cd'ing 到 git 存储库(其中还有许多其他内容)不适用于他们)。

从 Macos 到 CentOS 服务器运行。

答案1

所有可以在oldfile=$(...)命令替换中扩展的内容都将被扩展你ssh。$()如果您希望它们在远程而不是本地运行,则需要转义各种内部。您想要在远程评估的任何内容都需要转义。尝试:

oldfile=$(
          ssh $server "
            $(declare -f parseDate)
            for file in /dir/$server/file*; do
                dateInSecs=\$(date -jf '%b/%e/%Y' \$(parseDate \$file) +%s)
                timeDiff=\$(($currentDateInSecs - \$dateInSecs))
                ((\$timeDiff >= \$twoMonthsInSecs)) &&
                    cat \$file
            done
          "
        )

另外,虽然 BSDdate有此-j选项,但 GNUdate没有。由于您正在连接到 CentOS 计算机,因此您可能想要更改

dateInSecs=\$(date -jf '%b/%e/%Y' \$(parseDate \$file) +%s)

dateInSecs=\$(date \$(parseDate \$file) +%s)

但我们需要查看您获得的确切格式才能parseDate确定。

答案2

请小心使用双引号和单引号。如果使用双引号,则在执行命令之前将计算所有$variables和表达式。$( … )例如:

ssh $server "
    $(declare -f parseDate)
    for file in /dir/$server/file*; do
        dateInSecs=$(date -jf '%b/%e/%Y' $(parseDate \$file) +%s)
        timeDiff=$((\$currentDateInSecs - \$dateInSecs))
        ((\$timeDiff >= \$twoMonthsInSecs)) && cat \$file
    done
"

在这里,如果$serverremoteHost,这将被准备成这样被传递ssh到远程$server

ssh remoteHost "
    parseDate() { … }
    for file in /dir/remoteHost/file*; do
        dateInSecs=
        timeDiff=
        ((\$timeDiff >= \$twoMonthsInSecs)) && cat \$file
    done
"

在 RemoteHost 本身上,您将尝试执行如下操作:

    parseDate() { … }
    for file in /dir/remoteHost/file*; do
        dateInSecs=
        timeDiff=
        (( >= )) && cat $file
    done

如果您可以修改您的问题以包括对您想要实现的目标的解释以及示例输入和输出,那么这里的某人可能会建议如何重写您的代码以满足要求。

相关内容