Goal
Across the shell scripts in this repository, external commands (e.g. rm, mkfifo, and other frequently-used utilities) are invoked repeatedly. Each such invocation forks/execs a separate process, which carries overhead. Bash provides an optional mechanism — "loadable builtins" — that allows certain commands to run as builtins directly inside the running shell process instead of forking an external binary. This issue proposes investigating and adopting that mechanism where it is safe and beneficial to do so, without breaking compatibility with non-bash shells.
Background
- Bash ships (in its source distribution, under
examples/loadables/) a set of optional "loadable builtins" — small pieces of code that can be compiled into shared objects and loaded into a running bash session via the enable -f builtin command. Examples include unlink (wraps the unlink(2) syscall to remove a single file) and mkfifo (creates a FIFO), among others.
- When loaded, these run inside the bash process itself rather than forking a new process, which is faster for scripts that call these commands often.
- These loadable builtins are not compiled into bash by default on most systems. They are typically made available via a separate distro package (e.g. Debian/Ubuntu's
bash-builtins package), and even then must be explicitly loaded at runtime with enable -f.
- Because this mechanism is bash-specific and depends on an optional package being installed, it cannot be assumed to be present. The repository's shell scripts need to remain functional in its absence, and also need to remain functional under non-bash shells (e.g.
dash, busybox ash), which have no equivalent loadable-builtin mechanism at all.
Specific ask
- Survey
rm usage: There are multiple occurrences of the rm command across the .sh files in this codebase. These should all be identified.
- Introduce an internal wrapper function, e.g.
_otel_rm:
- In
api.sh (or wherever the shared/bootstrap logic lives), check whether bash's unlink loadable builtin is available.
- If it is available, load it and expose it under the internal name
_otel_rm (e.g. via enable -f ... unlink followed by aliasing/renaming to _otel_rm, however that ends up being implemented).
- If it is not available, declare a shell function named
_otel_rm that simply wraps/calls the regular external rm command, so behavior is identical to today.
- Replace all direct occurrences of
rm in all .sh files in the repository with calls to _otel_rm.
- Do the same for
mkfifo: survey all occurrences of mkfifo across the .sh files, and introduce an analogous internal wrapper (e.g. _otel_mkfifo) that uses bash's loadable mkfifo builtin when available, and falls back to a function wrapping the external mkfifo command otherwise. Replace all occurrences accordingly.
- Generalize the search: Beyond
rm and mkfifo, search the codebase for other frequently-used external commands that have a known bash loadable-builtin equivalent (for example — not exhaustive — things like sleep, pwd, printenv, basename, dirname, head, stat, tee, uname, id, ln, mkdir, rmdir, whoami, hostname, etc., to the extent bash ships or has shipped loadable equivalents for them). For every such command that is used frequently in this codebase and has a suitable loadable-builtin equivalent, apply the same pattern: internal wrapper function, conditional load of the builtin if available, fallback function wrapping the external command if not.
- Portability constraint (hard requirement): All of this must keep working correctly under non-bash shells (e.g.
dash, busybox ash) where:
- There is no
enable -f mechanism at all.
- Loadable builtins are not a concept.
- The wrapper functions must transparently fall back to invoking the plain external commands in that environment, with identical observable behavior to what the scripts do today.
- Packaging/dependency metadata: Wherever this repository lists recommended or optional dependencies for system package managers (deb, rpm, apk, and any others already referenced in the repo's packaging/dependency files), the relevant bash loadable-builtins package should be added as a recommended (not required/hard) dependency, for each package manager where such a package actually exists (e.g.
bash-builtins on Debian/Ubuntu-based deb packaging). Where no such package exists for a given package manager/distro family, none should be added there.
Non-goals / clarifications
- The change must be purely behavior-preserving: whether or not the loadable builtin is available at runtime,
_otel_rm, _otel_mkfifo, and any other introduced wrapper must behave identically to the current direct calls to rm, mkfifo, etc., from the perspective of the rest of the codebase.
- The detection/loading of builtins should happen centrally (e.g. in
api.sh, as it's described as the common/shared entry point) rather than being repeated ad hoc in every script.
- Any additional commands identified in step 4 should only be adopted if a real bash loadable-builtin equivalent exists and the command is genuinely used frequently enough in this codebase to justify the wrapper.
Goal
Across the shell scripts in this repository, external commands (e.g.
rm,mkfifo, and other frequently-used utilities) are invoked repeatedly. Each such invocation forks/execs a separate process, which carries overhead. Bash provides an optional mechanism — "loadable builtins" — that allows certain commands to run as builtins directly inside the running shell process instead of forking an external binary. This issue proposes investigating and adopting that mechanism where it is safe and beneficial to do so, without breaking compatibility with non-bash shells.Background
examples/loadables/) a set of optional "loadable builtins" — small pieces of code that can be compiled into shared objects and loaded into a running bash session via theenable -fbuiltin command. Examples includeunlink(wraps theunlink(2)syscall to remove a single file) andmkfifo(creates a FIFO), among others.bash-builtinspackage), and even then must be explicitly loaded at runtime withenable -f.dash,busybox ash), which have no equivalent loadable-builtin mechanism at all.Specific ask
rmusage: There are multiple occurrences of thermcommand across the.shfiles in this codebase. These should all be identified._otel_rm:api.sh(or wherever the shared/bootstrap logic lives), check whether bash'sunlinkloadable builtin is available._otel_rm(e.g. viaenable -f ... unlinkfollowed by aliasing/renaming to_otel_rm, however that ends up being implemented)._otel_rmthat simply wraps/calls the regular externalrmcommand, so behavior is identical to today.rmin all.shfiles in the repository with calls to_otel_rm.mkfifo: survey all occurrences ofmkfifoacross the.shfiles, and introduce an analogous internal wrapper (e.g._otel_mkfifo) that uses bash's loadablemkfifobuiltin when available, and falls back to a function wrapping the externalmkfifocommand otherwise. Replace all occurrences accordingly.rmandmkfifo, search the codebase for other frequently-used external commands that have a known bash loadable-builtin equivalent (for example — not exhaustive — things likesleep,pwd,printenv,basename,dirname,head,stat,tee,uname,id,ln,mkdir,rmdir,whoami,hostname, etc., to the extent bash ships or has shipped loadable equivalents for them). For every such command that is used frequently in this codebase and has a suitable loadable-builtin equivalent, apply the same pattern: internal wrapper function, conditional load of the builtin if available, fallback function wrapping the external command if not.dash,busybox ash) where:enable -fmechanism at all.bash-builtinson Debian/Ubuntu-based deb packaging). Where no such package exists for a given package manager/distro family, none should be added there.Non-goals / clarifications
_otel_rm,_otel_mkfifo, and any other introduced wrapper must behave identically to the current direct calls torm,mkfifo, etc., from the perspective of the rest of the codebase.api.sh, as it's described as the common/shared entry point) rather than being repeated ad hoc in every script.