0

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.

  • Thanks! I don't know why I didn't add docker-entrypoint parts to my search queries! If a mod wants to lock/delete this they can, just felt it was more appropriate to ask here. – John Von Neumann Sep 5 '18 at 12:20
1

The "$@" bit will expand to the list of positional parameters (usually the command line arguments), individually quoted to avoid word splitting and filename generation ("globbing").

The exec will replace the current process with the process resulting from executing its argument.

In short, 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).

  • So it's a way of hot-swapping the purpose of a process? So instead of allowing it to die, we just repurpose it for something else? – John Von Neumann Sep 5 '18 at 16:20
  • 1
    @JohnVonNeumann Yes, and it makes the signal handling easier to handle as Stephen Kitt wrote in his answer. – Kusalananda Sep 5 '18 at 16:36
  • It's funny, I'm studying my Linux Foundation SysAdmin atm and I literally just got to a section describing this procedure. You made it a lot easier to understand. I'd never really thought of running bash commands as spawning new processes, dunno what I did think, but it hadn't occurred that that's the way it works. – John Von Neumann Sep 5 '18 at 17:12
  • @JohnVonNeumann Yes, that's what happens in shell scripts, except for when executing built-in commands such as printf and true etc. (unless the external version of these are explicitly used). – Kusalananda Sep 5 '18 at 17:20
3

Two other answers explain what exec "$@" does. This answer on Stack Overflow explains why it’s important for Docker, and as you surmise, it does have to do with signals:

This is important in Docker for signals to be proxied correctly. For example, if Redis was started without exec, it will not receive a SIGTERM upon docker stop and 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 supervisord or similar when running multiple processes in a container, as it will forward signals appropriately.

1

"$@" 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 exec with echo, some test, and x y as arguments which will execute echo (in most sh implementations, /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.

  • So if I'm understanding this correctly, basically, you can use it to say, run a script multiple times with a variety of arguments? Or have I completely missed it? – John Von Neumann Sep 5 '18 at 16:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.