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が拡張されていない場合は、コマンドを置き換えなくてもうまく機能しますが、必要です。$()$file

どうすれば解決できますか?

情報:

これはスクリプトではなく、私の~/.bash_profileにあります。

これは(他のスクリプトのうち)gitリポジトリにあるスクリプトです~/bash_profile(私は設定ソースを使用するインストールスクリプトを持っています$PWD)。したがって、人々はgitリポジトリにCDを送るのではなく、このコマンドを直接使うことができます。他の多くのもの)彼らには適用されません)。

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
"

さて、それなら$serverこのremoteHostように準備します。今後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

達成しようとしている目標の説明と、入力と出力の例を含めるように質問を変更できる場合は、ここにいる誰かが要件を満たすようにコードを書き換える方法を提案できます。

関連情報