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.