명령 전에 쉘 변수를 설정하면 "명령을 찾을 수 없습니다"가 발생합니다.

명령 전에 쉘 변수를 설정하면 "명령을 찾을 수 없습니다"가 발생합니다.

쉘 변수를 설정하고 이를 쉘 스크립트의 일부로 명령에 전달하려고 하는데 코드는 다음과 같습니다.

SLS_DEBUG_TEXT=""
if [ "$ENABLE_DEBUG_LOGGING" = "true" ]; then
  SLS_DEBUG_TEXT="SLS_DEBUG=* "
fi

$SLS_DEBUG_TEXT sls create_domain -v $AWS_PROFILE_FLAG --stage $STAGE // gives error
#SLS_DEBUG=* sls create_domain -v $AWS_PROFILE_FLAG --stage $STAGE // works correctly

내가 받은 오류는 다음과 같습니다.

./sls-deploy.sh: line 110: SLS_DEBUG_TEXT: command not found

if설명은 대부분 관련이 없지만 변수를 조건부로 설정해야 함을 나타내고 싶었습니다(즉, 항상 디버그 로깅을 활성화하고 싶지는 않습니다). 주석 처리된 코드 조각의 마지막 줄은 디버그 로깅이 활성화되고 올바르게 작동하는 명령의 모습입니다.

여기와 Stack Overflow에서 변수를 설정할 때 등호 사이의 공백으로 인해 문제가 발생한 일부 이전 게시물을 찾았습니다()하지만 난하지 않았어요생각하다나는 여기서 이 함정에 빠졌다.

당신의 도움을 주셔서 감사합니다.

답변1

$SLS_DEBUG_TEXT쉘이 해당 값을 할당으로 처리하는 단계 이후에는 확장이 너무 늦습니다. 따라서 변수의 값은 명령으로 처리됩니다.

당신이 할 수 있는 것은 다음을 사용하는 것입니다 env:

SLS_DEBUG_TEXT='SLS_DEBUG=*'
env "$SLS_DEBUG_TEXT" sls create_domain -v "$AWS_PROFILE_FLAG" --stage "$STAGE"

주변 인용문에 주의하세요각 단일 변수가 확장됩니다..

가능 여부가 비어 있거나 설정되지 않은 경우 위의 경우 이름이 없는 명령을 시도하므로 SLS_DEBUG_TEXT오류가 발생합니다 .env

이 문제를 해결하려면 다음을 사용할 수 있습니다.

SLS_DEBUG_TEXT='SLS_DEBUG=*'
env ${SLS_DEBUG_TEXT:+"$SLS_DEBUG_TEXT"} sls create_domain -v "$AWS_PROFILE_FLAG" --stage "$STAGE"

변수가 설정되고 null이 아닌 경우 ${SLS_DEBUG_TEXT:+"$SLS_DEBUG_TEXT"}로 확장됩니다. "$SLS_DEBUG_TEXT"그렇지 않으면 아무것도 확장되지 않습니다(이 경우 빈 문자열도 확장되지 않음 "$SLS_DEBUG_TEXT").

SLS_DEBUG_TEXT='SLS_DEBUG=* '또한 코드에서와 같이 다음 공백이 있는 경우 *프로세스 환경에서 값의 일부가 됩니다. 이것이 의도적인 것인지 아닌지는 모르겠습니다.SLS_DEBUGsls


나는 또한 당신이 인용한 오류 메시지가 다음과 같은 것을 발견했습니다.

./sls-deploy.sh: line 110: SLS_DEBUG_TEXT: command not found

나에게 이것은 $변수 이름을 사용하기 전에 변수 이름을 사용하지 않고 스크립트의 어느 시점에서 변수 이름을 사용하고 있음을 의미합니다. 이는 현재 겪고 있는 주요 문제와 전혀 관련이 없을 수 있습니다. 당신의 코드전시하다대신 오류가 발생합니다.

./sls-deploy.sh: line NNN: SLS_DEBUG=*: command not found

답변2

이것쉘 문법은 어휘 분석 단계에서 할당 단어를 식별합니다., 매개변수 확장이 발생하기 훨씬 전입니다. 매개변수를 다음으로 확장할 수 있지만주문하다, 작업으로 확장할 수 없습니다. 그 시점에서는 (작성한 대로 "SLS_DEBUG=*" sls ...) 텍스트가 동일하더라도 명령으로 처리됩니다.

이는 쉘 명령 언어 구문 분석 및 평가의 이상한 측면입니다. 특정 유형의 동작은 코드를 처음 읽을 때 어휘적으로 결정되며, 이러한 동작은 정상적으로 작동하더라도 나중에 복구할 수 없습니다.나타나다텍스트 교체를 통해 작동합니다.

할 수 있는SLS_DEBUG_TEXT="eval SLS_DEBUG='*' "명령의 나머지 부분에 셸 메타 문자가 포함될 수 있으면 잠재적인 문제가 발생할 수 있지만 이 방법은 작동합니다. 또 다른 옵션은 조건부로 함수를 정의하는 것입니다.

sls_debug() { :; }
if [ "$ENABLE_DEBUG_LOGGING" = "true" ]; then
    sls_debug() {
        SLS_DEBUG='*' "$@"
    }
fi
sls_debug sls create_domain ...

또는 (아마도 더 명확하게) $ENABLE_DEBUG_LOGGING내부적으로만 확인하는 기능도 작동하거나 명시적일 수 env "$SLS_DEBUG_TEXT" ...있습니다 eval "$SLS_DEBUG_TEXT" ....

답변3

완전성을 기하기 위해 이것이 제가 문제를 해결한 방법입니다.코살로난다의 답변그리고마이클 호머의 답변.

function executeServerlessCommand() {
  if [ "$ENABLE_SLS_DEBUG_LOGGING" = "true" ]; then
    SLS_DEBUG='*' "$@"
  else
    "$@"
  fi
}

executeServerlessCommand sls create_domain -v ${AWS_PROFILE_FLAG:+"$AWS_PROFILE_FLAG"} --stage "$STAGE"

몇 가지 참고사항:

  1. 실행할 명령을 받아들이고, ENABLE_SLS_DEBUG_LOGGING변수를 확인하고, SLS_DEBUG=*true이면 명령 앞에 추가하고, 그렇지 않으면 제공된 명령을 실행하는 함수를 만들었습니다.
  2. 내가 사용하는 ${a:+"$a"}변수 구문은 AWS_PROFILE_FLAG변수 값이 이미 설정된 경우에만 추가합니다. 이전에는 이 변수가 올바르게 참조되지 않았습니다.

관련 정보