exec Command: Tutorial & Examples

Replace the current shell process with a new command or program

The exec command is a shell built-in that replaces the current process with a specified command or program without creating a new process. Unlike most commands that spawn child processes, exec overlays the current shell or script process with the new one. This behavior is useful in scripting and system management when you want to hand off control to another program without returning to the original shell. This article explains how exec works, its parameters, practical examples, common pitfalls, and advanced usage scenarios.

What exec Command Does

The exec command replaces the current shell or process with the command or program you specify. This means the current process image is replaced by the new process image, and the process ID (PID) remains the same. After replacement, the original process ceases to exist, and control never returns to it.

For example, running

exec echo "Hello World"

will print "Hello World" to standard output and then immediately terminate the current shell or script, because the shell process is replaced by the echo command. Once echo finishes, no shell remains to continue.

Typical usage includes replacing the current shell with another shell or running a program directly from a script without spawning a new process.

Why exec Is Important and Its Origin

The exec command was introduced to allow efficient process replacement without spawning additional processes, saving system resources and avoiding process proliferation. It is fundamental in Unix-like systems for managing process lifecycles and control flow.

Replacing the current process is useful when you want to completely hand over execution to another program or shell, such as switching shells, running a login shell, or executing a command that should fully replace the script context.

How exec Works: Technical Background

At the operating system level, exec corresponds to the execve() system call, which replaces the current process image with a new program loaded from disk. The current process's memory, stack, and code are discarded and replaced by the executable's code and data. The process retains its PID and open file descriptors (unless explicitly closed).

Because it does not fork a new process, no child process is created. This behavior differs from most commands that create child processes using fork().

The shell's exec built-in wraps around this system call, allowing scripts and interactive shells to replace themselves with another program.

Common Command Parameters

Although exec is primarily used by specifying the command to run, some shells support options modifying its behavior:

  • -a name
    Use name as the zeroth argument (argv[0]) of the executed command instead of the command name. This affects how the command appears in process listings like ps.

  • -c
    Clear all environment variables before executing the command. Use with caution, as it can affect program behavior.

  • -l
    Make the shell act as if it had been invoked as a login shell. This option is shell-dependent and mainly affects shell initialization files.

Note: Not all shells support these options; consult your shell's manual page (man bash, man zsh) for details.

Practical Examples Using exec

Example 1: Replacing the Shell with Another Shell

To replace your current bash shell with zsh, run:

exec zsh

This command replaces the current shell process with zsh. After this, your terminal session runs zsh without creating a new process.

Example 2: Using exec in a Script

Consider the script replace.sh:

#!/bin/bash
echo "Starting script"
exec ls -l /tmp
echo "This line will never execute"

Running ./replace.sh will output the listing of /tmp and then terminate. The last echo is never reached because exec replaces the script's shell process.

Sample output:

Starting script
total 16
-rw-r--r-- 1 user user 1234 Jun 10 12:00 file1
drwxr-xr-x 2 user user 4096 Jun 10 12:01 dir1

Example 3: Redirecting File Descriptors with exec

You can use exec to redirect file descriptors for the duration of the shell or script.

exec 3>output.txt
echo "Writing to file descriptor 3" >&3
exec 3>&-

This opens file descriptor 3 for writing to output.txt, writes a line, and then closes fd 3.

Example 4: Starting a Login Shell

To replace your shell with a login shell (which reads login configuration files):

exec -l bash

This invokes bash as a login shell, applying login-specific environment setup.

Potential Problems and Pitfalls

  • No Return to Original Shell: Once exec replaces the shell or script, control never returns to the original process. This can cause unexpected termination if used unintentionally.

  • Misunderstanding Subshell Behavior: Contrary to some beliefs, exec works inside subshells but replaces only the subshell's process. The parent shell remains unaffected. For example:

    (exec echo "In subshell")
    

    This prints the message, and the subshell terminates, but the parent shell continues.

  • Environment and File Descriptor Changes Persist: When using exec to redirect file descriptors or modify environment variables, changes persist in the current shell or script. Care must be taken to avoid unintended side effects.

  • Compatibility Issues: Some options like -a, -c, or -l are shell-dependent and may not be available everywhere.

Common Errors and Troubleshooting

  • Command Not Found: Using exec with a command that does not exist will terminate the shell with an error. For example:

    exec nonexistentcommand
    

    results in:

    bash: exec: nonexistentcommand: not found
    
  • Unexpected Shell Termination: Using exec in interactive shells without knowing its effects can cause the terminal to close or the session to end.

  • File Descriptor Mismanagement: Improper use of exec for redirection can leave file descriptors open or closed unexpectedly, affecting subsequent commands.

To troubleshoot, verify commands exist, test scripts without exec first, and use exec cautiously.

Advanced Usage and Scripting Integration

The exec command is invaluable in scripting for:

  • Replacing the script with another program to save resources.
  • Managing file descriptors without launching additional processes.
  • Launching login shells or alternative shells within scripts.
  • Implementing wrappers that hand off execution.

Example: Using exec to replace a shell script with a Python interpreter:

#!/bin/bash
exec python3 "$@"

This script replaces itself with python3, passing all arguments.

Security Considerations

Because exec replaces the current process, any malicious or buggy program executed with exec can terminate your shell or script unexpectedly. Ensure commands passed to exec are trusted and properly validated, especially in scripts exposed to external input.

Possible Alternatives and Related Commands

  • bash, sh: shells that interpret exec.
  • ps: view process list and check process names and PIDs.
  • fork: creating child processes, complementary to exec.
  • kill: terminate processes, sometimes used after exec.
  • nohup: run commands immune to hangups, alternative process management.

See Also

Further Reading

As an Amazon Associate, I earn from qualifying purchases.

The text above is licensed under CC BY-SA 4.0 CC BY SA