Bash's exec Replaces Shell
This is a quick look at Bash’s exec
builtin with a simple example.
bash(1)
explains exec [command]
:
If command is specified, it replaces the shell. No new process is created.
This is mainly useful for wrapper scripts, where we
do not want to have a Bash process lingering around. Take this script
named test
:
#!/bin/bash
sleep inf
When run as ./test
, the current shell creates a new Bash instance (the
interpreter specified in the first line of the script with the shebang
#!/bin/bash
), and then creates a new process for the sleep
command.
So, we have 2 processes running: a Bash and a sleep
process:
$ ps -o pid,ppid,cmd -T
PID PPID CMD
2443 969 -bash
5348 2443 /bin/bash ./test
5349 5348 sleep inf
5358 2443 ps -o pid,ppid,cmd -T
When we background ./test
with Ctrl-Z and use ps(1)
with the
-T
flag, it prints the processes associated with the current terminal
session. PID 2443 is the current terminal. We see that 2443 spawned
/bin/bash ./test
(PID 5348) which in its turn begat sleep inf
(PID
5349).
Now we modify the script to use exec
to execute sleep
:
#!/bin/bash
exec sleep inf
Again, the current shell executes a new Bash process. But instead of
it creating a new sleep
process, the sleep process replaces it. Now we
only have single process (sleep
) running:
$ ps -o pid,ppid,cmd -T
PID PPID CMD
2443 969 -bash
5399 2443 sleep inf
5407 2443 ps -o pid,ppid,cmd -T
Here, we see that sleep inf
has as its parent the shell that invoked
./test
: it has replaced /bin/bash ./test
.