Ubuntuコンテナ内で実行されるスクリプトがあります。
#!/bin/sh
name=$(cat < /etc/os-release | grep "^NAME" | cut -d "=" -f 2)
if [ $name = "Ubuntu" ]
then
echo "This should return"
else
echo "This is wrong"
fi
以下を実行してコンテナを起動します。
docker run -it -v $(pwd):/scripts ubuntu:latest /bin/sh /scripts/test.sh
私が受け取った出力は「This iswrong」です。これは間違っています。私のラップトップはUbuntuなので、$nameの出力が「Ubuntu」であることを知っていますが、これが起こる理由を見つけることができません。スクリプトにパスがあるのはなぜですか?コンテナ外のノートブックでも同じことを行います。
答え1
このファイルには、/etc/os-release
シェル互換変数割り当てのリストが含まれています。シェルスクリプトで解析する必要はなく、関連変数を使用するだけsource
です。.
$ cat ex.sh
#!/bin/sh
. /etc/os-release
echo "$NAME"
$ ./ex.sh
Ubuntu
答え2
Debian では、この特定の行は次のようになります。
NAME="Debian GNU/Linux"
右側の引用符に注意してください。 Ubuntuでも使用できる場合、name
引用符は特別なものではないため、文字通り引用符を受け取りますcut
。別の問題は、文字列にスペースを含めることができることです。この場合、トークン化は文字列内の引用符なしの変数拡張に達し、[ $name = "Ubuntu" ]
テストでエラーが発生する可能性があります。
このような問題を回避するには、変数拡張を引用し、比較文字列の周りにリテラル引用を追加します。
if [ "$name" = '"Ubuntu"' ]; then ...
または、文字列の先頭と末尾から引用符を削除し、name=${name#\"}; name=${name%\"}
まだquoteを使用します"$name"
。
答え3
この特別なケースでは、次のようにスクリプトを単純化できます。
#!/bin/sh
if grep -q Ubuntu /etc/os-release; then
echo "This should return"
else
echo "This is wrong"
fi
grep
、この-q
オプションを渡すと何も印刷されませんが、文字列が見つかった場合はコード0で終了し、それ以外の場合はゼロ以外のコードで終了します。if
結局、それが私たちが期待するものです。
答え4
シンプル
$ grep -q Ubuntu /etc/os-release && echo "This should return" || echo "This is wrong"
または
$ . /etc/os-release && echo "$NAME"
または、lsb_release
次のコマンドを使用することもできます。
$ lsb_release -i -s