2017-01-09 5 views
0

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 

は私の質問は以下のとおりです。

  • 私は#!/bin/bash
  • に最初の行を変更する必要がありそうでないときの変数は引用符を必要とするときには不明ですが、特に条件文ではここでいくつかのリソースを教えていただけますか?
  • 私は、シングルブラケット対ダブルブラケットに関する条件のバリエーションを見てきました。どちらを使うべきですか?
  • スクリプトの実行後、$ PUBLIC_IPは設定されていないように見えます。 env変数を設定する別の方法はありますか?

他のフィードバックは歓迎します。

+0

もし本当に互換性があるなら、 '#!/ bin/sh'を使って' [[$ PUBLIC_IP == $ CURRENT_PUBLIC_IP]] 'を' ["$ PUBLIC_IP" = " $ CURRENT_PUBLIC_IP "]'。 ( '=='はbashとzshの両方に存在する拡張ですが、POSIX標準で指定されている唯一の文字列比較演算子は '=')です。 –

+2

ところで、あなた自身の変数の大文字の名前は実際には悪い形式です。環境変数のPOSIX仕様では、オペレーティングシステムまたはシェルに意味を持つ名前にはすべて大文字の名前が付けられ、アプリケーションの使用には少なくとも1つの小文字の名前が予約されています。これは、 '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とは反対に、bashのを必要としませんが、それはすべてkshの誘導体(kshのは、bash、zshの)が読めるようにする必要がありますeval -safe方法で変数名を生成することが可能だということを確認するために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" 
    

    そうでなければ、私はあなたがOKだと思います。リソースに関しては、Bash manualをご覧いただくか、shellcheck.comのような施設をご利用いただくか、Bash FAQをご利用ください。

  • [[ … ]]をお使いの場合は、おそらく書かれているように問題ありません。シェル構文の通常の規則は[[ … ]]に中止されており、Bourneシェルを学んだ人の中から地獄を混乱させ、Bashのその部分を学ぶのに気を使うことはできません。

  • export PUBLIC_IP="$CURRENT_PUBLIC_IP"が呼び出し側シェルに影響するようにするには、スクリプトにドット(. script.sh)またはソース(source script.sh)を付ける必要があります。それ以外の場合は、スクリプトを実行するシェルの環境を設定しますが、呼び出し元のシェルには影響しません。

    ドットコマンドでスクリプトを使用する場合は、設定する変数の数が設定されていないと終了するまで考慮する必要があります。そして、それが始まる前にそれらのいずれかが設定されているかどうか。エクスポートする変数を除き、すべての変数がローカル変数として宣言されている関数を作成すると、より簡単に使用できます。スクリプトが別のプロセスとして実行されている場合、これについて心配する必要はありません。

関連する問題