我有以下脚本:
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
并且我希望它支持当前支持的功能sh
。bash
答案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
由于
- 一个空字符串,以及
- 使用不带引号的。
由于该变量为空,因此使用不带引号的变量会将其从命令中完全删除,这意味着该行
if [ $installRequiredFiles = "true" ]; then
将被解释为
if [ = "true" ]; then
这又是命令使用中的错误[
;=
当没有预期的操作员时,它会看到操作员。
那么,为什么$installRequiredFiles
(and $1
) 为空?
命令
sh -c ./myscript.sh "true"
运行命令./myscript.sh
并设置为脚本中的$0
字符串。 true
in 中的值$0
通常是脚本或 shell 的名称,并且该值最常用于诊断消息(例如 shell 生成的错误消息)。
如果你曾经使用过
sh -c ./myscript.sh sh "true"
相反,then会按预期$1
设置为,并且会设置为(这是内联脚本的惯例)。在这两种情况下,脚本都会由任何不带-line 执行脚本的 shell 执行。最终运行脚本的 shell 可能取决于您计算机上的 shell,并且可能不是或。参见,例如,test
$0
sh
sh -c
#!
sh
sh
bash
哪个 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/sh
是bash
或ksh
其他dash
一些更奇特的 shell 并不重要,用户不需要担心使用正确的解释器运行脚本。
与此答案的各个部分相关: