I don't understand the bash command
exec. I have seen it used inside scripts to redirect all output to a file (as seen in this). But I don't understand how it works or what it does in general. I have read the man pages but I don't understand them.
I don't understand the bash command
man bash says:
exec [-cl] [-a name] [command [arguments]] If command is specified, it replaces the shell. No new process is created. The arguments become the arguments to command. If the -l option is supplied, the shell places a dash at the beginning of the zeroth argument passed to command. This is what login(1) does. The -c option causes command to be executed with an empty environment. If -a is supplied, the shell passes name as the zeroth argument to the executed command. If command cannot be executed for some reason, a non-interactive shell exits, unless the execfail shell option is enabled. In that case, it returns failure. An interactive shell returns failure if the file cannot be executed. If command is not specified, any redirections take effect in the current shell, and the return status is 0. If there is a redirection error, the return status is 1.
The last two lines are what is important: If you run
exec by itself, without a command, it will simply make the redirections apply to the current shell. You probably know that when you run
command > file, the output of
command is written to
file instead of to your terminal (this is called a redirection). If you run
exec > file instead, then the redirection applies to the entire shell: Any output produced by the shell is written to
file instead of to your terminal. For example here
bash-3.2$ bash bash-3.2$ exec > file bash-3.2$ date bash-3.2$ exit bash-3.2$ cat file Thu 18 Sep 2014 23:56:25 CEST
I first start a new
bash shell. Then, in this new shell I run
exec > file, so that all output is redirected to
file. Indeed, after that I run
date but I get no output, because the output is redirected to
file. Then I exit my shell (so that the redirection no longer applies) and I see that
file indeed contains the output of the
date command I ran earlier.
97This is only partial explanation.
execserves to also replace current shell process with a command, so that parent goes a way and child owns pid. This is not only for redirection. Please add this info Aug 31, 2016 at 13:23
16Following up on @SergiyKolodyazhnyy's comment, the example I've just encountered which led me to this page is a docker-entrypoint.sh, where after performing various actions on the nginx config, the final line of the script is
exec nginx <various nginx arguments>. This means that nginx takes over the pid of the bash script and now nginx is the main running process of the container, not the script. I assume this is just for cleanliness, unless someone else knows a more concrete reason for it? Nov 21, 2018 at 19:56
6@Luke This is called "wrapper script". Example of that is also
gnome-terminal, which at least on 14.04 had a wrapper script to set up arguments. And that's their only purpose, really - set arts and environment. Another case would be to clean up - kill previous instance of a process first and launch new one Nov 21, 2018 at 20:18
execexample similar to the
nginxexample given by @LukeGriffiths is the
vncserveruses to configure a VNC server process and then
exec startkdeand so on. Jan 22, 2019 at 13:57
9@LukeGriffiths, the main reason for
execin a container startup script is that the PID 1, the container's ENTRYPOINT, has a special significance in Docker. It is a main process that receives signals, and when it exists, the container exits too.
execjust a way to take
shout of this chain of command, and make the daemon the main process of the container.– kkmFeb 13, 2019 at 22:39
exec is a command with two very distinct behaviors, depending on whether at least one argument is used with it, or no argument is used at all.
If at least one argument is passed, the first one is taken as a command name and
exectry to execute it as a command passing the remaining arguments, if any, to that command and managing the redirections, if any.
If the command passed as first argument doesn't exist, the current shell, not only the
execcommand, exits in error, unless the shell is interactive or the bash option
execfailis set (
shopt -s execfail). See also https://superuser.com/questions/992204/why-does-exec-non-existent-file-exits-the-shell-when-in-a-script-that-is-sourc
If the command exists and is executable, it replaces the current shell. That means that if
execappears in a script, the instructions following the exec call will never be executed (unless
execis itself in a subshell). A successful
execnever returns. Shell traps like "EXIT" won't get triggered either.
If no argument is passed,
execis only used to redefine the current shell file descriptors. The shell continue after the
exec, unlike with the previous case, but the standard input, output, error or whatever file descriptor has been redirected take effect.
If some of the redirections uses
/dev/null, any input from it will return EOF and any output to it will be discarded.
You can close file descriptors by using
-as source or destination, e.g.
exec <&-. Subsequent read or writes will then fail.
Here are two examples:
echo foo > /tmp/bar exec < /tmp/bar # exec has no arguments, will only affect current shell descriptors, here stdin cat # simple command that read stdin and write it to stdout
This script will output "foo" as the cat command, instead of waiting for user input as it would have done in the usual case will take its input from the /tmp/bar file which contains foo.
echo foo > /tmp/bar exec wc -c < /tmp/bar # exec has two arguments, the control flow will switch to the wc command cat
This script will display
4 (the number of bytes in /tmp/bar) and immediately ends. The
cat command won't be executed.
9`Some old posts never really get old ... +1.– CbhiheMar 23, 2017 at 11:33
4If some of the redirections uses /dev/null, the associated file descriptor is closed. No, it really does redirect to/from
/dev/null, so writes still succeed and reads return EOF.
close(2)on an fd would cause read/write system calls to return errors, and you do that with
exec 2>&-for example. Jul 7, 2017 at 2:59
3Try it yourself:
ls -l /proc/self/fd: note that fd 3 will be open read-only on /dev/null. Then close it again with
exec 3<&-, and you can see (with
ls -l /proc/$$/fdagain) that your shell process has no fd 3 anymore. (closing stdin with
exec <&-can be useful in scripts, but interactively it's a logout.) Jul 7, 2017 at 3:01
4This answer is great because it explains the two use-cases of
execthe current most-upvoted answer only talks about the one use-case and the other answer by g_p only talks about the other use-case. And this answer is nice and concise/readable for such a complex subject matter. Jan 22, 2019 at 14:09
1@ctrl-alt-delor That's a way to describe it but might deserve some rephrasing. The exec command is simple to implement, there isn't even the need for it to handle the redirections, as the shell does it already. "Skip fork" indeed: the exec command never forks.– jlliagreJan 27, 2021 at 21:09
exec you need to first understand
fork. I am trying to keep it short.
When you come to a fork in the road you generally have two options. Linux programs reach this fork in the road when they hit a
Normal programs are system commands that exist in a compiled form on your system. When such a program is executed, a new process is created. This child process has the same environment as its parent, only the process ID number is different. This procedure is called forking.
- Forking provides a way for an existing process to start a new one. However,
there may be situations where a child process is not the part of the same
program as parent process. In this case
execwill replace the contents of the currently running process with the information from a program binary.
- After the forking process, the address space of the child process is overwritten with the new process data. This is done through an exec call to the system.
4can you explain why
execcan redirect a script output, as in the link I posted?– a06eSep 18, 2014 at 21:45
8I found this unclear "However, there may be situations where a child process is not the part of the same program as parent process"– cdosbornOct 15, 2018 at 22:34
Indeed, is it possible to rephrase "part of the same program as parent process"?– ArtfaithMay 28, 2022 at 6:31
bash, if you do
$ help exec exec: exec [-cl] [-a name] [command [arguments ...]] [redirection ...] Replace the shell with the given command. Execute COMMAND, replacing this shell with the specified program. ARGUMENTS become the arguments to COMMAND. If COMMAND is not specified, any redirections take effect in the current shell. Options: -a name pass NAME as the zeroth argument to COMMAND -c execute COMMAND with an empty environment -l place a dash in the zeroth argument to COMMAND If the command cannot be executed, a non-interactive shell exits, unless the shell option `execfail' is set. Exit Status: Returns success unless COMMAND is not found or a redirection error occurs.
The relevant bit:
If COMMAND is not specified, any redirections take effect in the current shell.
exec is a shell builtin, which is the shell equivalent of the
exec family of system calls that G_P speaks of (and whose manpages you appear to have read). It just has the POSIX mandated functionality of affecting the current shell if no command is specified.
execin a special way which can be explained much more simply, I will write an answer.
execis not about processes. It does not create a process.