LinuxCommandLibrary

exenv

Execute a program with specified environment variables

TLDR

Display a list of installed versions

$ exenv versions
copy

Use a specific version of Elixir across the whole system
$ exenv global [version]
copy

Use a specific version of Elixir for the current application/project directory
$ exenv local [version]
copy

Show the currently selected Elixir version
$ exenv [version]
copy

Install a version of Elixir (requires elixir-build plugin )
$ exenv install [version]
copy

SYNOPSIS

exenv <command> [<arguments>...]

PARAMETERS

<command>
    The name of the executable command to run (e.g., `python`, `pip`, `ruby`, `bundle`, `node`). This command will be resolved and executed within the context of the currently selected language version.

[<arguments>...]
    Any additional arguments that need to be passed directly to the `<command>`. These are relayed without modification.

DESCRIPTION

exenv is a foundational utility, commonly integrated within language version managers such as pyenv (for Python), rbenv (for Ruby), or nvm (for Node.js, though less directly named 'exenv'). Its primary purpose is to enable the execution of a command using a specific version of a programming language, without altering the active environment of the current shell session.

This functionality is invaluable for one-off commands, scripts, or automated environments (like CI/CD pipelines) where precise language version control is critical. Instead of modifying the shell's PATH or using `source` commands, exenv allows direct execution with the desired interpreter. It works by leveraging a 'shim' mechanism: when a command (e.g., `python`, `gem`, `pip`) is invoked, the `exenv` shim intercepts it, determines the correct language version based on project-specific (e.g., `.python-version`) or global configurations, and then executes the actual binary from that version's installation. This approach ensures isolation, prevents environment pollution, and simplifies managing multiple language versions concurrently.

CAVEATS

  • Shim Reliance: exenv's functionality depends entirely on its 'shim' directory being correctly placed at the beginning of your shell's PATH. If shims are not found, commands managed by exenv will not resolve correctly.
  • Limited Environment Control: While it sets up the necessary language-specific environment variables, exenv does not provide the same granular control over arbitrary environment variables as tools like `env(1)`.
  • Implicit Version Resolution: The specific version of the language used is determined implicitly by the version manager's logic (e.g., local project file, global default, shell override). Users must be aware of this resolution order.

HOW <I>EXENV</I> WORKS (THE SHIM CONCEPT)

At its core, exenv (or `pyenv exec`, `rbenv exec`) operates through a directory of 'shims' that is prepended to your shell's PATH. When you type a command like `python` or `pip`, your shell finds the `pyenv` shim for that command first. This shim is a small executable script that then invokes the actual `pyenv` (or `rbenv`) command. `pyenv` then determines which specific Python version (based on `.python-version` files, global settings, or shell overrides) should be used, finds the real `python` or `pip` executable within that version's installation directory, and `exec`utes it. This process is transparent to the user and allows for dynamic, per-project language version switching without manually managing PATH variables.

USE CASES IN SCRIPTING AND CI/CD

exenv's ability to run commands in isolated, version-controlled environments makes it ideal for scripting. For instance, in a shell script or a CI/CD pipeline, instead of activating a Python version with `pyenv shell 3.9.1`, you can directly use `pyenv exec pip install -r requirements.txt`. This ensures that the `pip` command associated with the correct Python version is used, without affecting subsequent commands in the script or other jobs on the CI runner, promoting reproducibility and preventing conflicts.

HISTORY

exenv itself is not a standalone command but rather a conceptual prefix for execution utilities within language version managers. Its origin is deeply intertwined with the development of tools like rbenv (Ruby Version Manager) and later pyenv (Python Version Manager), which emerged in the early 2010s. These tools aimed to offer a lightweight, shim-based alternative to earlier, more intrusive version managers (like RVM for Ruby). The `<tool> exec` pattern, which exenv embodies, was introduced to provide a clean way to run commands using a specific language version without activating that version in the current shell, thereby avoiding shell environment pollution and simplifying scripting and CI/CD pipelines. It solved the problem of reliably executing language-specific binaries without complex PATH manipulations or shell `source` commands.

SEE ALSO

pyenv(1), rbenv(1), nvm(1), env(1), exec(3)

Copied to clipboard