bash 스크립트 함수 내에서 ssh로 스크립트 문자열 전달 - 변수 평가 문제

bash 스크립트 함수 내에서 ssh로 스크립트 문자열 전달 - 변수 평가 문제

다음과 같이 SSH를 통해 원격 스크립트를 실행하는 bash 스크립트를 작성하려고 합니다.

#!/bin/bash
logfilepattern="*drupal*.gz php*.gz error*.gz"
function getlogcounts {
    echo "in getlogcounts"
    echo  $1
    echo  $2

    ssh $1 bash -c '  \  #script string starts here
    cd $2
    for file in `ls $logfilepattern`
    do
     ls -l $file
    done
'
}

getlogcounts [email protected] "/var/log/mylogs"

$1그리고 $2함수 내에서는 ok가 발견되는 것 같지만 스크립트 문자열 내에서는 값이 없는 것 같습니다. 따라서 cd $2평가 cd하고 ls $logfilepattern평가합니다 ls.

답변1

이것은 단순화된 버전이며, 더 중요한 것은 인용이 수정되었다는 것입니다(변수 주위에는 큰 따옴표, 필요할 경우 변수가 아닌 텍스트 주위에는 작은 따옴표).

#!/bin/bash
logfilepattern='*drupal*.gz php*.gz error*.gz'

function getlogcounts {
    echo in getlogcounts
    echo "$1"
    echo "$2"

    ssh "$1" "cd $2 ; ls -l $logfilepattern"
}

getlogcounts [email protected] /var/log/mylogs

답변2

원격 컴퓨터에서 스크립트를 실행하고 있습니다. 스크립트에는 $2and가 포함되어 있습니다 $logfilepattern(작은따옴표 사이의 텍스트는 문자 그대로 command 에 대한 인수로 전달되므로 ssh반대편에서 실행되는 코드 조각입니다). 이는 삭제 측에서 실행되는 셸의 변수를 참조합니다.

실제로 원격 측에서 두 개의 쉘을 실행하고 있지만 그다지 좋은 결과를 얻지는 못합니다. SSH는 항상 셸을 호출합니다. 여러 인수를 전달할 수 있지만 공백으로 연결될 뿐입니다. 원격 측에서 셸 실행

bash -c   \  #script string starts here
cd $2

첫 번째 줄은 두 개의 인수 와 공백 bash으로 호출됩니다 . -c이는 아무 작업도 수행하지 않는 쉘을 호출합니다. 원격 명령의 나머지 부분은 SSH가 호출한 셸에서 실행됩니다.

원하는 것을 수행하는 쉬운 방법은 다음과 같습니다.

ssh "$1" "cd $2 && ls -l $logfilepattern"

노트:

  • 구문 분석된 출력 ls은 의미가 없습니다.: for file in `ls *`작성하는 방법은 복잡하지만 파일 이름에 특수 문자가 포함되어 있으면 for file in *구문 분석된 출력이 중단됩니다.ls
  • $2$logfilepattern다 원격 측에서 실행되는 스크립트의 일부로 구문 분석됩니다. 유사한 내용이 포함되어 있으면 $(touch foo)코드 세그먼트가 실행됩니다. 이 특정 사용 사례에서는 이것이 반드시 문제가 되는 것은 아니지만 알아야 할 사항입니다.
  • &&after를 사용하면 명령이 실패할 경우 실패 상태가 즉시 반환 cd됩니다 .sshcd

SSH를 통해 수정되지 않은 콘텐츠를 원격 셸에 전달하려는 경우 전달하는 모든 내용이 원격 측에서 확장되므로 명령줄만 사용하는 것은 문제가 됩니다. 종종 작동하는 한 가지 방법은(클라이언트와 서버의 SSH 구성에 따라 항상 그런 것은 아님) LC_이름이 ;로 시작하는 변수를 사용하는 것입니다. 이는 로케일에 대한 정보로 간주되어 전송되는 경우가 많습니다.

LC_DIRECTORY=$2 LC_LOGFILEPATTERN=$logfilepattern ssh "$1" 'cd "$LC_DIRECTORY" && ls -l $LC_LOGFILEPATTERN'

인용문을 참고하세요:

  • 원격 컴퓨터에서 실행되는 명령은 입니다 cd "$LC_DIRECTORY" && ls -l $LC_LOGFILEPATTERN. 이 리터럴 텍스트를 ssh명령 에 대한 인수로 전달하려면 작은따옴표를 사용하십시오 .
  • $LC_DIRECTORYcd변수 내용에 대한 명령을 호출 하려면 원격 측에서 실행되는 스크립트에서 이를 큰따옴표로 묶습니다 .
  • LC_LOGFILEPATTERN공백으로 구분된 와일드카드 패턴 목록이므로 큰따옴표가 아닙니다. 이것이 바로 따옴표가 없는 변수 확장이 처리되는 방식입니다.

변수를 전송할 수 없는 경우 값에 특수 문자가 포함된 변수를 보호하기 위해 따옴표 레이어를 추가해야 합니다.

q_directory=$(printf %sa "$2" | sed s/\'/\'\\\'\'/g)
q_directory="'${directory%a}'"
q_logfilepattern=$(printf %sa "$logfilepattern" | sed s/\'/\'\\\'\'/g)
q_logfilepattern="'${q_logfilepattern%a}'"
ssh "$1" "logfilepattern=$q_logfilepattern; cd $q_logfilepattern && ls \$logfilepattern"

관련 정보