Shell Arguments Format

When I check the cmd and entrypoint of one docker image, I see something like this:

1
2
cmd: zkServer.sh start-foreground
entrypoint: /docker-entrypoint.sh

It actually by default works as:

1
/docker-entrypoint.sh zkServer.sh start-foreground

Let’s see what is inside /docker-entrypoint.sh:

1
2
3
4
5
6
# Generate Zookeeper configuration
# zkGenConfig.sh is in PATH, it will be executed if condition matches
[ "$1" = 'zkServer.sh' ] && (zkGenConfig.sh || exit 1)

# execute zkServer.sh start-foreground in current process
exec "$@"

It just like a wrapper and executes the passed parameters as a new command. This pattern gives me some inspirations. Actually lots of containers use this pattern, like Envoy, please search my blog <<Docker Entrypoint Script>>

About $@, reference from https://stackoverflow.com/questions/9994295/what-does-mean-in-a-shell-script: $@ is nearly the same as $*, both meaning all command line arguments. They are often used to simply pass all arguments to another program (thus forming a wrapper around that other program).

The difference between the two syntaxes shows up when you have an argument with spaces in it:

1
2
3
4
5
6
7
8
9
10
11
12
wrappedProgram "$@"
# ^^^ this is correct and will hand over all arguments in the way
# we received them, i. e. as several arguments, each of them
# containing all the spaces and other uglinesses they have.
wrappedProgram "$*"
# ^^^ this will hand over exactly one argument, containing all
# original arguments, separated by single spaces.
wrappedProgram $*
# ^^^ this will join all arguments by single spaces (IFS)as well and
# will then split the string as the shell does on the command
# line, thus it will split an argument containing spaces into
# several arguments.

For example:

1
2
# in terminal, type:
wrapper "one two three" four five "six seven"

What you will get:

1
2
3
4
5
6
7
# the same format as we passed
"$@": "one two three" "four" "five" "six seven"
# joined each argument by IFS shell variable and produce one final argument
"$*": "one two three four five six seven"
# all separated
$*: one two three four five six seven
$@: one two three four five six seven

"$@" is by far the most useful for most situations because it preserves the integrity of each positional parameter.

0%