仅使用“sh -c”调用 shell 脚本时出现错误:“意外的运算符”

仅使用“sh -c”调用 shell 脚本时出现错误:“意外的运算符”

我有以下脚本:

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选项的用途。您通常不给它一个文件,而是给它 shell 命令。它的目的是做这样的事情:

$ 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

您收到的错误来自 shell dash(用于在您的系统上实现的 shell /bin/sh)。这是$installRequiredFiles由于

  1. 一个空字符串,以及
  2. 使用不带引号的。

由于该变量为空,因此使用不带引号的变量会将其从命令中完全删除,这意味着该行

if [ $installRequiredFiles = "true" ]; then

将被解释为

if [ = "true" ]; then

这又是命令使用中的错误[=当没有预期的操作员时,它会看到操作员。

那么,为什么$installRequiredFiles(and $1) 为空?

命令

sh -c ./myscript.sh "true"

运行命令./myscript.sh并设置为脚本中的$0字符串。 truein 中的值$0通常是脚本或 shell 的名称,并且该值最常用于诊断消息(例如 shell 生成的错误消息)。

如果你曾经使用过

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

相反,then会按预期$1设置为,并且会设置为(这是内联脚本的惯例)。在这两种情况下,脚本都会由任何不带-line 执行脚本的 shell 执行。最终运行脚本的 shell 可能取决于您计算机上的 shell,并且可能不是或。参见,例如,test$0shsh -c#!shshbash哪个 shell 解释器运行不带 shebang 的脚本?

您可能想#!在脚本中添加一行指向/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请注意,在最后两种情况下,执行脚本的不是 shell ,而是#!脚本中的 -line 引用的任何 shell,就像./myscript.sh "test"直接运行一样。与添加 -line 之前的区别#!在于,您现在可以确定这是 shell /bin/sh,而不是其他 shell。

/bin/sh该脚本仅使用 POSIX shell 语法,这意味着无论/bin/sh在任何给定系统上使用什么 shell 来实现,它都可以由 执行。如果/bin/shbashksh其他dash一些更奇特的 shell 并不重要,用户不需要担心使用正确的解释器运行脚本。

与此答案的各个部分相关:

相关内容