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
          "
        )

또한 BSD date에는 이 -j옵션이 있지만 GNU date에는 없습니다. 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

달성하려는 목표에 대한 설명과 입력 및 출력 예시를 포함하도록 질문을 수정할 수 있다면 여기 있는 누군가가 요구 사항을 충족하도록 코드를 다시 작성하는 방법을 제안할 수 있습니다.

관련 정보