5

So I've got the following script:

#!/bin/bash

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

exec su -- someuser -c "/tmp/elasticsearch-6.4.2/bin/elasticsearch \"$@\""

Located at /usr/bin/elasticsearch-wrapper

Now when I run it with the following args:

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 

I end up with the following error:

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

So looking at the output of $@ shows that the first -E option is for some reason excluded which results in the error.

The output was:

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

but it should be:

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

(Notice the missing -E from the start)

But I'm not sure why that is the case if anyone could point out the reason?

kurupt_89
  • 153

1 Answers1

6

Replace your last line with:

exec su someuser -c '/tmp/elasticsearch-6.4.2/bin/elasticsearch "$@"' -- dummy-argv0 "$@"

Generally, this is the way to pass arguments through the su command:

su user -c 'command "$@"' -- argv0 "$@"

You should omit the -- on non-linux systems.

su's synopsis in the man page (su [options] [username]) is deceptive, here is some verbiage from below it:

Additional arguments may be provided after the username, in which case they are supplied to the user's login shell.

....

You can use the -- argument to separate su options from the arguments supplied to the shell.

You should also replace all the echos with printf '%s\n' ..., since the echo builtin from bash and zsh, and /bin/echo from linux will use themselves the -E argument (quite contrary to what the standard requires). Generally, there's no way to safely use echo with variables which may expand to -n, -e or -E.

Note:

Using "$@" is the only way to preserve the arguments exactly as they were passed -- any variation of su -c "command $*" will only work as long as no argument contains spaces or any other special characters that may be interpreted by the shell. Even the current example could be easily subverted by a mkdir -p repositories.url.allowed_urls=http:/snapshot.test.only.ME.and.ME.and.ME in the home directory of someuser.