传递给包装脚本的第一个参数被忽略

kur*_*_89 5 bash shell-script arguments

所以我有以下脚本:

#!/bin/bash

echo '-------------------------'
echo $0
echo $1
echo $@
echo '-------------------------'

exec su -- someuser -c "/tmp/elasticsearch-6.4.2/bin/elasticsearch \"$@\""
Run Code Online (Sandbox Code Playgroud)

位于 /usr/bin/elasticsearch-wrapper

现在,当我使用以下参数运行它时:

elasticsearch-wrapper \
  -E cluster.name=elasticsearch-test-24efcbba4c68  \
  -E node.name=node-1  \
  -E http.port=9250  \
  -E path.data=/tmp/elasticsearch_test  \
  -E path.logs=/tmp/log/elasticsearch  \
  -E cluster.routing.allocation.disk.threshold_enabled=false  \
  -E network.host=127.0.0.1  \
  -E node.attr.testattr=test  \
  -E path.repo=/tmp  \
  -E repositories.url.allowed_urls=http://snapshot.test*  \
  -E discovery.zen.minimum_master_nodes=0  \
  -E node.max_local_storage_nodes=1  \
  -E logger.level=DEBUG 
Run Code Online (Sandbox Code Playgroud)

我最终出现以下错误:

root@24efcbba4c68:/app# elasticsearch-wrapper \
>   -E cluster.name=elasticsearch-test-24efcbba4c68  \
>   -E node.name=node-1  \
>   -E http.port=9250  \
>   -E path.data=/tmp/elasticsearch_test  \
>   -E path.logs=/tmp/log/elasticsearch  \
>   -E cluster.routing.allocation.disk.threshold_enabled=false  \
>   -E network.host=127.0.0.1  \
>   -E node.attr.testattr=test  \
>   -E path.repo=/tmp  \
>   -E repositories.url.allowed_urls=http://snapshot.test*  \
>   -E discovery.zen.minimum_master_nodes=0  \
>   -E node.max_local_storage_nodes=1  \
>   -E logger.level=DEBUG
-------------------------
/usr/bin/elasticsearch-wrapper

cluster.name=elasticsearch-test-24efcbba4c68 -E node.name=node-1 -E http.port=9250 -E path.data=/tmp/elasticsearch_test -E path.logs=/tmp/log/elasticsearch -E cluster.routing.allocation.disk.threshold_enabled=false -E network.host=127.0.0.1 -E node.attr.testattr=test -E path.repo=/tmp -E repositories.url.allowed_urls=http://snapshot.test* -E discovery.zen.minimum_master_nodes=0 -E node.max_local_storage_nodes=1 -E logger.level=DEBUG
-------------------------
cluster.name=elasticsearch-test-24efcbba4c68: -c: line 0: unexpected EOF while looking for matching `"'
cluster.name=elasticsearch-test-24efcbba4c68: -c: line 1: syntax error: unexpected end of file
Run Code Online (Sandbox Code Playgroud)

所以查看$@显示的输出,第一个-E选项由于某种原因被排除在外,这会导致错误。

输出是:

cluster.name=elasticsearch-test-24efcbba4c68 -E node.name=node-1.....

但它应该是:

-E cluster.name=elasticsearch-test-24efcbba4c68 -E node.name=node-1....

(注意-E一开始的缺失)

但是如果有人能指出原因,我不确定为什么会这样?

mos*_*svy 5

将最后一行替换为:

exec su someuser -c '/tmp/elasticsearch-6.4.2/bin/elasticsearch "$@"' -- dummy-argv0 "$@"
Run Code Online (Sandbox Code Playgroud)

通常,这是通过su命令传递参数的方式:

su user -c 'command "$@"' -- argv0 "$@"
Run Code Online (Sandbox Code Playgroud)

您应该--在非 linux 系统上省略。

su手册页 ( su [options] [username]) 中的概要具有欺骗性,以下是它下面的一些措辞:

可以在用户名之后提供其他参数,在这种情况下,它们将提供给用户的登录 shell。

....

您可以使用 -- 参数将 su 选项与提供给 shell 的参数分开。

您还应该将所有echos替换为printf '%s\n' ...,因为echo来自bashandzsh/bin/echo来自 linux的内置-E函数将使用它们自己的参数(与标准要求完全相反)。通常,无法安全地使用echo可能扩展为-n,-e或 的变量-E

笔记:

Using"$@"是唯一的方法来完全保留传递的参数——su -c "command $*"只要没有参数包含空格或任何其他可以被 shell 解释的特殊字符,任何变体都将起作用。即使是目前的例子可以通过轻易颠覆mkdir -p repositories.url.allowed_urls=http:/snapshot.test.only.ME.and.ME.and.ME中的主目录someuser