Kernel#exec

exec(command) -> never returns
Returns: Never returns (process replaces itself) · Updated March 13, 2026 · Kernel Methods
processes system execution subprocess

The exec method replaces the current Ruby process with an external program. After calling exec, the Ruby interpreter stops and the new program runs in its place. The process never returns from exec.

How It Works

When you call exec, the current process image is replaced with the new program. Unlike system or backticks, exec doesn’t create a subprocess—it becomes the subprocess.

Basic Usage

# Replace with a shell command
exec("ls -la")

# After this, Ruby is gone, ls runs
puts "This never prints"

Common Examples

Running Commands

# Simple command
exec("echo hello")

# With arguments
exec("ruby", "-v")

# Via shell
exec("ls *.rb | head -5")

Environment Variables

# Set environment for the new process
exec({ "HOME" => "/tmp" }, "ls")

Replace Self

# Common pattern for process replacement
exec("ruby", "other_script.rb", *ARGV)

Shell Expansion

# Without shell: separate arguments
exec("ls", "-la", "-h")

# With shell: glob expansion, pipes work
exec("ls -la *.rb")

Practical Examples

Shebang Scripts

#!/usr/bin/env ruby
# Common pattern to run another Ruby version
exec("ruby3.0", $0, *ARGV)

Wrapper Scripts

#!/usr/bin/env ruby
# Load environment, then exec

ENV.each { |k, v| ENV[k] = v }  # Ensure env is set
exec("/path/to/real/binary")

Process Interpreter

# Switch to different interpreter
exec("python", "script.py")
exec("node", "app.js")

Important Notes

No Return

# Code after exec never runs (unless exec fails)
exec("false")
puts "Never prints"

# Use system if you need to continue
system("ls")
puts "This prints after ls"

Error Handling

begin
  exec("nonexistent_command")
rescue Errno::ENOENT => e
  puts "Command not found: #{e}"
end

Comparison

# exec - replaces current process
exec("ls")

# system - runs in subprocess, returns after
system("ls")
puts "Runs after"

# spawn - runs in subprocess, returns immediately
spawn("ls")
puts "Runs immediately"

Exit Status

# The exit status is the program's exit status
# Use at_exit to handle
at_exit { exit! }
exec("ruby -e 'exit 42'")

The exec method is used when you want to completely replace your Ruby process with another program, such as in wrapper scripts or when switching interpreters.

See Also