2017-01-09 4 views
0

Bash 환경에서 올바르게 실행되도록 수정하려는 쉘 스크립트가 있습니다. ,쉘 스크립트에서 환경 변수를 이식 가능하게 설정합니다.

  • 내가 #!/bin/bash
  • 그것은 변수는 따옴표를 필요로 할 때 불분명하고 그들이하지 않을 때의 첫 번째 라인을 변경해야합니다 : 여기
    #!/bin/zsh 
    
    # Some constants. The first two will become env variables. 
    UPDATE_DNS_API_HOST="https://example.com" 
    UPDATE_DNS_API_URL="$UPDATE_DNS_API_HOST/my_end_point" 
    CURRENT_PUBLIC_IP=$(curl -s "$UPDATE_DNS_API_URL" | grep -o '".*"' | tr -d '"') 
    
    if [[ $PUBLIC_IP == $CURRENT_PUBLIC_IP ]]; then 
        echo "Current IP: "$CURRENT_PUBLIC_IP" already set." 
    else 
        response=$(curl -s -H "Content-Type: application/json" \ 
          --data "$CURRENT_PUBLIC_IP" "$UPDATE_DNS_API_URL") 
        echo $response 
        export PUBLIC_IP="$CURRENT_PUBLIC_IP" 
    fi 
    

    내 질문은 다음과 같습니다

    여기에 스크립트의 특히 조건문에서. 여기서 몇 가지 자료를 가르쳐 주시겠습니까?

  • 단일 브래킷 대 더블 브래킷에 대한 조건부 변형을 보았습니다. 어느 것을 사용해야합니까?
  • 스크립트를 실행 한 후 $ PUBLIC_IP가 설정되지 않은 것처럼 보입니다. env 변수를 설정해야하는 다른 방법이 있습니까?

기타 의견을 환영합니다.

+0

만약 당신이 호환성을 원한다면'#!/bin/sh'을 사용하고'[[$ PUBLIC_IP == $ CURRENT_PUBLIC_IP]]'를'[ "$ PUBLIC_IP"= " $ CURRENT_PUBLIC_IP "]'. ('=='는 bash와 zsh 양쪽에 존재하는 확장이지만, POSIX 표준에 의해 지정된 유일한 문자열 비교 연산자는'=')입니다. –

+2

사실, 자신의 변수에 대한 모든 대문자는 실제로 나쁜 형식입니다. 환경 변수에 대한 POSIX 스펙은 운영 체제 또는 쉘에 의미가있는 이름이 모두 대문자로 된 이름을 가지며 응용 프로그램 사용을 위해 하나 이상의 소문자가있는 이름을 예약하도록 지정합니다. 이것은'PUBLIC_IP'는 장래 버전의 bash ('/ dev/tcp'가 어디서 바뀌는가?)를 바꾸는 것을 의미 할 수있는 반면,'public_ip'라는 변수는 다른 것을 쾅쾅 거리지 않을 것이라고 보장합니다. –

+0

... http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html re : 위에 언급 된 명명 규칙을 참조하십시오. –

답변

1

한 적절한 것은 UNIX 프로세스들이 시작 자신과 미래의 어린이를위한 환경 변수를 수정할 수 있다는 것입니다. 당신의 의도를 둘러싸는 쉘에서 변수를 설정하는 경우


,이 작업을 수행하는 하나의 매우 일반적인 방법은 표준 출력에 쉘 명령을 방출하는 것입니다. 즉, 이 아닌 것은이 아니므로 쉘 명령을 stderr로 이동해야합니다. stderr는 정보 텍스트 및 상태 내용에 적절하게 지정되므로 적절하게 적용됩니다.

이 버전은 /bin/sh 반대로, 떠들썩한 파티를 필요로하지 않습니다,하지만 모든 KSH 유도체 (KSH, 배쉬, zsh을)를 읽을 수 있어야 eval - 안전 방식으로 변수 이름을 생성 할 수 있다는 보장하기 위해 printf '%q'를 사용합니다.

#!/bin/bash 
# note that while this runs with bash, ksh and zsh will also be able to eval its output 
# ...POSIX sh too, when there aren't nonprintable characters causing $''-style quoting 
# ...to be used. 

# usage: emit_cmd varname ... 
# 
# emit code that defines a variable when evaluated on stdout 
emit_cmd() { 
    for varname; do 
    printf 'export %q=%q; ' "$varname" "${!varname}" 
    done 
} 

# Some constants. The first two will become env variables. 
UPDATE_DNS_API_HOST="https://example.com" 
UPDATE_DNS_API_URL="$UPDATE_DNS_API_HOST/my_end_point" 

# print definitions of those variables to stdout 
emit_cmd UPDATE_DNS_API_HOST UPDATE_DNS_API_URL 

CURRENT_PUBLIC_IP=$(curl -s "$UPDATE_DNS_API_URL" | grep -o '".*"' | tr -d '"') 

if [[ $PUBLIC_IP = $CURRENT_PUBLIC_IP ]]; then 
    echo "Current IP: $CURRENT_PUBLIC_IP already set." >&2 
else 
    response=$(curl -s -H "Content-Type: application/json" \ 
      --data "$CURRENT_PUBLIC_IP" "$UPDATE_DNS_API_URL") 
    echo "$response" >&2 
    PUBLIC_IP="$CURRENT_PUBLIC_IP" emit_cmd PUBLIC_IP 
fi 

이 스크립트는 이름 ip-lookup 아래에 저장되어있는 경우, 그것은 정의하는 변수와 현재 쉘로 가져올 수 있습니다 :이 규칙을 사용

eval "$(ip-lookup)" 

같은 ssh-agent 같은 기존 UNIX 도구와의 호환성을 유지하는 환경 변수를 수정해야합니다. 내가 변수 이름에 대한 기존의 규칙을 유지하고있어,하지만 당신은 기회가 있다면, 당신은 relevant POSIX convention을 준수 소문자 이름을 전환해야


참고.

1
  • 당신은 당신이 오두막을 수정해야합니다, script.sh를 호출 누군가가 bash 대신 zsh에서 실행하십시오.

  • 에서 따옴표의 내부 쌍 :

    echo "Current IP: "$CURRENT_PUBLIC_IP" already set." 
    

    가 정통이고 좋은 생각. 사용

    echo "Current IP: $CURRENT_PUBLIC_IP already set." 
    

    당신은 아마 주위에 따옴표를 원하는 :

    echo "$response" 
    

    그렇지 않으면, 당신은 확인을 것 같아요. 리소스에 관해서는 Bash manual을 보거나 shellcheck.com과 같은 시설을 사용하거나 Bash FAQ을 참조하십시오.

  • [[ … ]]을 사용하는 경우 작성한대로 잘 될 것입니다. 쉘 구문의 일반적인 규칙은 [[ … ]]에 일시 중지되어 있으며 Bourne 쉘을 배운 사람들로부터 혼란스러워하며 Bash의 일부를 배울 수 없습니다.

  • 당신은 점해야 할 것

    (. script.sh) 또는 소스 (source script.sh)에 export PUBLIC_IP="$CURRENT_PUBLIC_IP"의 스크립트는 호출하는 쉘에 어떤 영향을 미칠 수 있습니다. 그렇지 않으면 스크립트를 실행하는 쉘 환경을 설정하지만 호출 쉘에는 영향을 미치지 않습니다.

    dot 명령과 함께 스크립트를 사용하기로 결정했다면 설정하기 전에 설정해야하는 변수의 수를 설정해야합니다. 그리고 아마 그들이 시작하기 전에 설정되어 있는지 여부. 내보내려는 변수를 제외하고 모든 변수가 지역 변수로 선언 된 함수를 만들면 삶의 편의성이 향상됩니다. 스크립트가 별도의 프로세스로 실행될 때 걱정할 필요가 없습니다.하지 그들의 부모, 그 부모 프로세스에 직접 참여하지 않고 - 여기서 명심해야 할