I've been seeing this in a lot of
docker-entrypoint.sh scripts recently, and can't find an explanation online. My first thoughts are that it is something to do with signaling but that's a pretty wild guess.
"$@" bit will expand to the list of positional parameters (usually the command line arguments), individually quoted to avoid word splitting and filename generation ("globbing").
exec will replace the current process with the process resulting from executing its argument.
exec "$@" will run the command given by the command line parameters in such a way that the current process is replaced by it (if the
exec is able to execute the command at all).
"$@" in Bourne-like shells, in list contexts expands to all the positional parameters as separate arguments.
In a script, initially, the positional parameters are the arguments that the script itself received.
exec is to run a command in the same process as the shell. That's the last command a script will execute because after that, the process will be running another command than the shell.
So if your script is
#! /bin/sh - exec "$@"
And you call your script using a shell command line like:
/path/to/your-script 'echo' "some test" 'x y'
It will call
some test, and
x y as arguments which will execute
echo (in most
/bin/echo as opposed to the
echo shell builtin) in the same process that was previously running the shell interpreting your script with
some test and
x y as arguments.
This is important in Docker for signals to be proxied correctly. For example, if Redis was started without
exec, it will not receive a
docker stopand will not get a chance to shutdown cleanly. In some cases, this can lead to data loss or zombie processes.
If you do start child processes (i.e. don't use
exec), the parent process becomes responsible for handling and forwarding signals as appropriate. This is one of the reasons it's best to use
supervisordor similar when running multiple processes in a container, as it will forward signals appropriately.