Bash 스크립트는 SSH를 통해 호출할 때만 "바인딩되지 않은 변수" 오류를 발생시킵니다.

Bash 스크립트는 SSH를 통해 호출할 때만 "바인딩되지 않은 변수" 오류를 발생시킵니다.

내가 실행할 때 :

ssh [email protected] bash -c "/home/devops_staging/deployJob.sh example"

다음 오류가 발생합니다.

/home/devops_staging/deployJob.sh: line 4: $1: unbound variable

해당 부분 없이 실행 하면 bash -c예상대로 작동합니다.

ssh [email protected] /home/devops_staging/deployJob.sh example
deploy success

왜 이런 일이 발생합니까?

ssh ... bash -c "commands param1 param2"나는 항상 이 구문을 아무 문제 없이 사용했던 것을 기억하는 것 같기 때문에 이것은 매우 예상치 못한 일입니다 .

문제의 스크립트는 매우 간단합니다. 4행에서 제가 하는 일은 변수를 할당하는 것뿐입니다 $1(이것이 첫 번째 매개변수여야 합니다).

#!/usr/bin/env bash
set -euo pipefail

CI_PROJECT_NAME="$1"
...

디버깅하는 동안 bash -x -c ...다음과 같은 의심스러운 줄이 표시됩니다.

 + '[' -z '' ']'
 + return
 + case $- in
 + return
 + /home/devops_staging/deployJob.sh
/home/devops_staging/deployJob.sh: line 4: $1: unbound variable

답변1

나는 이것이 다음 질문과 중복된 것이라고 생각합니다.인용된 SSH 명령. 이미 알아차렸지만 저자는 여기서 다음과 같이 지적합니다.

이 글을 읽은 후에도 왜 이렇게 작동하는지 잘 모르겠습니다.

따라서 이 답변은 현재 질문에 사용된 코드의 맥락에서 문제를 구체적으로 설명하려고 시도합니다.

가장 중요한 정보는 여기에서 나옵니다.연결된 질문에 대한 좋은 답변예:

SSH는 셸에서 원격 명령을 실행합니다. 매개변수 목록 대신 문자열을 원격 셸에 전달합니다. 명령에 전달된 매개변수는 ssh공백으로 구분됩니다.

로컬로 실행하는 경우

ssh [email protected] /home/devops_staging/deployJob.sh example

그러면 ssh매개변수가 원격 엔드에 전달되는 것으로 식별되는 코드는 다음과 같습니다 /home/devops_staging/deployJob.sh. example연결된 매개변수 문자열은 다음과 같습니다.

/home/devops_staging/deployJob.sh example

이는 원격 측에서 실행되는 쉘 코드입니다. 이것이 당신이 원하는 문자열인 경우가 있습니다.

하지만 로컬에서 실행하면

ssh [email protected] bash -c "/home/devops_staging/deployJob.sh example"

그러면 매개변수는 다음과 같습니다. 원격 bash쉘 의 문자열은 다음과 같습니다.-c/home/devops_staging/deployJob.sh example

bash -c /home/devops_staging/deployJob.sh example

bash(매개변수가 , -c, /home/devops_staging/deployJob.sh, 인 것처럼 example) 이는 다음과 같습니다.아니요원격 측에서 실행하려는 쉘 코드입니다. 이것은 example옵션 매개변수가 아닙니다 ( 두 번째 매개변수 -c와 같습니다).sh이건 또 다른 질문이에요).

이 문자열을 원격 코드로 사용하려면 다음을 수행하세요.

bash -c "/home/devops_staging/deployJob.sh example"

그런 다음 가장 쉬운 방법은 ssh문자열을 단일 인수로 로컬에 전달하는 것입니다.

ssh [email protected] 'bash -c "/home/devops_staging/deployJob.sh example"'

작은따옴표 인수에는 원격 SSH 서버가 시작한 셸에 전달될 모든 셸 코드가 포함됩니다.

이 작업은 로컬에서도 수행할 수 있습니다.

ssh [email protected] 'bash -c "/home/devops_staging/deployJob.sh' 'example"'

큰따옴표(원격 쉘의 경우)가 두 개의 개별 로컬 매개변수에 속하는 경우 원격 쉘의 결과 문자열은 동일합니다.


(원격) 코드가 deployJob.sh실행될 때까지 얼마나 많은 도구가 이 명령을 해석하고 소화하는지 확인하세요.

  1. 로컬 쉘은 단어 분할, 인용 제거(그리고 종종 몇 가지 다른 작업)를 수행합니다. 결과는 ssh하나 이상의 매개변수일 수 있으며, 이는 원격 엔드에 전달될 코드로 해석됩니다.

  2. ssh단일 문자열을 원격 셸에 전달하려면 이러한 인수를 중간 공백과 연결하세요.

  3. 원격 셸은 자체적으로 단어 분할, 인용 제거(및 일반적으로 몇 가지 다른 작업)를 수행합니다. 몇 가지 명령을 실행합니다.

  4. 명령이 bash -c …다른(원격) 명령인 경우 쉘은 코드를 옵션 인수로 구문 분석합니다 -c. 토큰화, 따옴표 제거 및 기타 작업도 셸에서 수행됩니다.

  5. deployJob.sh제정신의 shebang이 포함된 경우 (아니면) 그러면 다른 (원격) 쉘이 파일을 차례로 해석하게 됩니다.

일반적으로 이전의 모든 도구가 해당 매개변수를 소화한 후에는 어떤 도구가 어떤 매개변수를 얻을지, 어떤 매개변수가 다음 도구에 전달될지 예측하고 전략을 세워야 합니다. 최종 도구가 원하는 결과를 정확히 얻을 수 있도록 기본 명령을 디자인해야 합니다.

관련 정보