コマンドの前にシェル変数を設定すると、「コマンドが見つかりません」が発生します。

コマンドの前にシェル変数を設定すると、「コマンドが見つかりません」が発生します。

シェル変数を設定し、それをシェルスクリプトの一部としてコマンドに渡したいのですが、コードは次のようになります。

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変数値がすでに設定されている場合にのみ追加します。以前は、この変数は正しく参照されませんでした。

関連情報