exec
Replace current process with a new program
TLDR
Execute a specific command using the current environment variables
SYNOPSIS
`exec` [options] [command [arguments...]] [redirection...]
PARAMETERS
command
The name of the program to execute,
which will replace the current shell.
[arguments...]
Optional arguments passed to the
executed program.
[-l]
Place a dash (`-`) as the first
character of the zeroth argument
(`argv[0]`) passed to the
command. This simulates
login shell behavior.
[-a name]
Use name as the zeroth argument
(`argv[0]`) to the command.
This overrides the default behavior
of using the command's name.
[redirection...]
Any I/O redirections (e.g.,
`<`, `>`, `>>`, `&>`, `<&`, `>&`)
that are applied. If no
command is specified, these
redirections apply to the
current shell process
itself for its remaining
lifetime.
DESCRIPTION
The exec command is a
shell builtin that
replaces the current shell
process with a specified program.
Unlike running a command normally,
which typically forks a new
child process to execute the
command and then returns to the
parent shell, exec
does not create a new process.
Instead, the current shell's process
space is overlaid with the new program.
This means that once the new program
starts, the original shell ceases to
exist, and control will not return
to it.
Common use cases for exec include:
permanently changing the shell
for a session (e.g., exec zsh),
running a command that should be the
last action of a script or
session (e.g., exec ssh user@host
so that the shell exits immediately
after ssh terminates), or
applying I/O redirections
that persist for the remainder of
the current shell's life
(e.g., exec > logfile to redirect
all subsequent standard output
from the current shell to logfile).
It's a powerful command for
optimizing resource usage by
avoiding unnecessary process
creation and for precise
control over shell behavior.
CAVEATS
- Once exec is called, the current
shell process is permanently
replaced. Control will not
return to the calling script or
shell environment after the
executed command finishes. - exec is a shell builtin
in most shells (like bash, zsh, ksh).
There is no standalone
/usr/bin/exec executable.
Consequently, its behavior and
available options might vary
slightly between different shells. - Permissions: The command
specified must be executable by the
current user.
SHELL BUILTIN VS. EXTERNAL COMMAND
It's crucial to understand that
exec is a shell builtin,
not a separate executable located
in your system's PATH (like
/usr/bin/ls). This means that
when you type exec, the shell
itself executes the instruction
directly, without spawning a new
process to run an 'exec' program.
This is precisely why exec can
replace the current shell process,
as it's the shell itself that
invokes the underlying execve(2)
system call on its own process ID.
PERSISTENT I/O REDIRECTION
One of the most powerful and often
underestimated uses of exec is
to apply I/O redirections that
persist for the entire remaining
lifetime of the current shell
session. For example,
exec > logfile will redirect
all subsequent standard output
from commands run in that shell
(unless explicitly redirected again)
to logfile. Similarly,
exec 3<> /dev/tcp/hostname/port
can open a network connection on a
specific file descriptor for the
current shell and all subsequent
commands within it. When used this
way, exec is typically called
without a command argument.
REPLACING THE LOGIN SHELL
A common practice in shell
configuration files (like
~/.profile or ~/.bash_profile)
is to use exec to switch
to a preferred shell. For instance,
exec zsh -l executed from
your .bash_profile will replace
the login bash shell with a
login zsh shell. This ensures that
your desired shell becomes the
primary process for your session,
avoiding an extra layer of
process nesting.
HISTORY
The concept of exec is deeply
rooted in the fundamental design of
Unix-like operating systems. It directly
corresponds to the execve(2)
system call (and its variants
like execl(3), execvp(3), etc.),
which is responsible for loading a
new program into the address space
of the current process. This allows
a process to transform itself into
another, rather than always needing
to create a new process via fork(2)
first.
As a shell builtin, exec has been
a standard feature of Unix shells
since their early days (e.g., Bourne Shell).
Its inclusion as a builtin is crucial
because it allows the shell to
directly perform the `exec` system
call, thereby replacing itself without
creating an intermediate child
process for the new program. This
design minimizes overhead and enables
its specific use cases like persistent
I/O redirection or final program
execution in a session.