The previous days I've made some
experiments with Alpine Linux
into creating some lightweight
development containers for Erlang and Elixir
to be run with bwrap
.
Long story short,
see the previous article about deterministic OS's,
I didn't want to run Alpine's busybox
package install hooks,
and as such basic UNIX tool (such as basename
and dirname
)
weren't available on the PATH.
Which should be fine, because unless I explicitly call them from within Elixir or Erlang they should'n matter...
Boy was I in a surprise (though not an unexpected one)...
Because in fact all Erlang's and Elixir's
"user-facing tools", as in erl
, erlc
, iex
, etc.
are actually sh
scripts that
call beam.smp
(or plain beam
)
after shuffling some environment variables
and stuffing some command line arguments...
This wasn't though an unexpected surprise, because I knew from experience this to be the case... In fact this is the case also for Java, many Lisp and Scheme runtimes, and many-many other tools (including browsers, Electron apps, etc.)
So, why am I all up-in-arms?
Because sh
(any flavour from bash
to zsh
)
is not a programming language,
and it is not fit for being the entry point
for any general-purpose tool, let alone
language runtimes!
(In fact, we've already learnt this lesson
with system service startup scripts,
which on Linux have been already superseded by systemd
unit files.)
I don't even want to point out why
any flavor of sh
is not suitable for these
very sensitive use-cases...
I'll resume myself to just naming a few important issues:
- reliability!
(by default
sh
just chugs along through commands regardless if they fail or succeed!) - security! (how many times have we been bitten by unquoted shell expansions?)
- performance;
(many required operations are not builtins, and require calling
complicated pipelines made from tools like
grep
,sed
,tr
,head
,tail
, etc.)
What could we (or the developers of said runtimes) do about all this?
Write launchers with in a proper language, preferably a compiled one!
And these days we have lots of good options; I'm going to skip C (which requires some effort to program in), and name if not C++, Go, or Rust, then at least Zig, Nim or a plethora of other up-and-coming languages in this category. Alternatively, if your code is already written in an interpreted language, then you could choose Python (which seems to be installed everywhere today) or even Deno or (and I don't believe I'm saying this) even NodeJS (the runtime). (BTW, there is a Google project for "writing better scripts" in NodeJS at github.com/google/zx.)
Anything is far better than sh
.
If not for ease of development reasons,
then at least for reliability and our sanity...
Thus, just like I've done a few years ago with Erlang,
I'll try to write my own erl
and iex
launchers in Rust...