エラー:「sh -c」のみを使用してシェルスクリプトを呼び出すときに「予期しない演算子」が発生する

エラー:「sh -c」のみを使用してシェルスクリプトを呼び出すときに「予期しない演算子」が発生する

次のスクリプトがあります。

installRequiredFiles=$1

install_with_pkg()
{
    arg1=$1
        echo $arg1
    echo "[+] Running update: $arg1 update."
}

if [ $installRequiredFiles = "true" ]; then
    if [ -x "$(command -v apt)" ]; then
          install_with_pkg "apt"
        elif [ -x "$(command -v yum)" ]; then
          install_with_pkg "yum"
        elif [ -x "$(command -v apk)" ]; then
          install_with_pkg "apk"
        else
          echo "[!] Can't install files."
    fi
fi

直接実行するとうまくいきます。

root@ubuntu:/# ./myscript.sh "true"
apt
[+] Running update: apt update.
Printing installRequiredFiles: true
Printing arg1: apt

ただし、使用すると、sh -c次のエラーが発生します。

root@ubuntu:/# sh -c ./myscript.sh "true"
./c.sh: 11: [: =: unexpected operator
Printing installRequiredFiles:
Printing arg1:

正しく実行したい、sh -c現在サポートされている機能をサポートしたいと思いますshbash

答え1

これはこのオプションの目的ではありません-c。通常、ファイルを提供せずにシェルコマンドを提供します。その目的は、次のことを行うことです。

$ sh -c 'echo hello'
hello

これでファイルを提供し、ファイルを読み取り、そこにあるコマンドを実行しようとしましたが、パラメータはスクリプト(myscript.sh)に渡されず、パラメータはコマンドsh自体にのみ渡されます。パラメータ:

$ cat script.sh
echo "ARGS: $@"

$ sh ./script.sh true
ARGS: true
$ sh -c ./script.sh true
ARGS: 

あなたがしなければならないことは使用しないこと-cだけであり、期待どおりに機能します。

sh ./myscript.sh "true"

または何らかの理由で使用する必要がある場合は、-cスクリプトを渡してください。そして一重引用符で囲まれた引数としてスクリプトのパラメータsh

sh -c './myscript.sh "true"'

答え2

あなたが受けているエラーは、シェルdash(システムに実装されているシェルの場合/bin/sh)で発生します。この$installRequiredFilesためです

  1. 空の文字列、そして
  2. 引用符なしで使用してください。

変数は空であるため、引用符なしで変数を使用すると、コマンドから変数が完全に削除されます。

if [ $installRequiredFiles = "true" ]; then

次のように解釈されます。

if [ = "true" ]; then

これはコマンドの再利用のバグです[=予想される人がいない場合、演算子が表示されます。

では、なぜ$installRequiredFiles(および$1)が空ですか?

注文する

sh -c ./myscript.sh "true"

コマンドを実行し./myscript.sh、スクリプトの文字列に設定します$0trueinの値は$0通常スクリプトまたはシェルの名前であり、診断メッセージ(シェルによって生成されたエラーメッセージなど)に最も一般的に使用されます。

使ってみた方なら

sh -c ./myscript.sh sh "true"

代わりに、$1期待どおり then が に設定され、 は (インラインスクリプトのルールです) に設定されます。どちらの場合も、スクリプトは -line なしでスクリプトを実行するすべてのシェルによって実行されます。スクリプトを実行するシェルは、コンピュータのシェルによって異なる場合があり、同じでない場合があります。たとえば、次を参照してください。test$0shsh -c#!shshbashShebangなしでスクリプトを実行するシェルインタプリタとは何ですか?

#!以下を指すスクリプトに行を追加できます/bin/sh

#!/bin/sh

# ... rest of script here ...
# ... just remember to quote all expansions ...

これは、次のようにスクリプトを実行できることを意味します。

$ ./myscript.sh test

または同じ

$ sh -c './myscript.sh "test"'

または、

$ sh -c './myscript.sh "$@"' sh test

sh -c最後の2つのケースでは、スクリプトを実行するシェルではなく直接実行する#!のと同じように、スクリプトの-lineが参照するシェルは何でも構いません。./myscript.sh "test"-lineを追加する前との違いは、これが他の#!シェルではなくシェルであることを確認できることです。/bin/sh

/bin/shスクリプトはPOSIXシェル構文のみを使用します。つまり、/bin/sh特定のシステムでスクリプトを実装するために使用されるすべてのシェルで実行できます。/bin/shそれがシェルかそれ以上にbashエキゾチックkshdashシェルかは問題ではありません。ユーザーは、スクリプトを実行するために正しいインタプリタを使用することを心配する必要はありません。

この回答のさまざまな部分に関連して:

関連情報