SHELL environment variable not set! (FLAME)

Greetings! I’ve been trying to get up and running on fly with an Elixir app that uses FLAME to elastically scale headless browsers. I’ve fought through many errors at this point. But I’m stuck on this one:

SHELL environment variable not set! [exec.cpp:607]

It causes the app to immediately terminate and write an erl_crash.dump.

I was able to fix this in my main machines by adding this to the env portion of my fly.toml:

SHELL = "/bin/bash"

However, it doesn’t seem to work for my spawned FLAME nodes. I can’t figure out what’s gone wrong in the first place, that I would actually need to set that variable at all. So any help in this regard would be tremendously appreciated.

Hi… It appears that this is by design and/or a known limitation, :dragon:. The docs for the Fly.io FLAME backend say:

The FLAME Fly machines do not inherit the environment variables of the parent. You must explicit[ly] provide the environment that you would like to forward to the machine.

Hope this helps a little!


Aside: On the Fly.io platform, in general, you probably also have to be careful about compile-time versus runtime environment.

1 Like

Added distributed, elixir

That did it! Thank you.

I’m still wondering - why do I need to set this ENV variable in the first place? Shouldn’t my machines already know what SHELL to use?

1 Like

Hm… Looking at your other question, you’re possibly unknowingly running a build system—along the lines of make—at runtime (which you generally shouldn’t).

I’ve seen some Makefiles in the past that wanted to turn SHELL into env PATH=$(PATH) $(SHELL), for example.

If you posted your Dockerfile and more of the context from the logs (from when SHELL was unset), then people might be able to help narrow this down more…

1 Like

It’s a pretty standard Dockerfile, plus a section for installing Chromedriver which I basically copied from the World Page Speed dockerfile.

Without re-breaking my app I can basically say the machine would spin up, and then I’d just about immediately get this:

2024-10-01T18:37:09.203 app[...] ewr [info] SHELL environment variable not set! [exec.cpp:607]

2024-10-01T18:37:09.206 app[...] ewr [info] Runtime terminating during boot (terminating)

2024-10-01T18:37:09.358 app[...] ewr [info] WARN Reaped child process with pid: 380 and signal: SIGUSR1, core dumped? false

Le Dockerfile:

# Find eligible builder and runner images on Docker Hub. We use Ubuntu/Debian
# instead of Alpine to avoid DNS resolution issues in production.
#
# https://hub.docker.com/r/hexpm/elixir/tags?page=1&name=ubuntu
# https://hub.docker.com/_/ubuntu?tab=tags
#
# This file is based on these images:
#
#   - https://hub.docker.com/r/hexpm/elixir/tags - for the build image
#   - https://hub.docker.com/_/debian?tab=tags&page=1&name=bullseye-20240926-slim - for the release image
#   - https://pkgs.org/ - resource for finding needed packages
#   - Ex: hexpm/elixir:1.17.3-erlang-27.1-debian-bullseye-20240926-slim
#
ARG ELIXIR_VERSION=1.17.3
ARG OTP_VERSION=27.1
ARG DEBIAN_VERSION=bullseye-20240926-slim

ARG BUILDER_IMAGE="hexpm/elixir:${ELIXIR_VERSION}-erlang-${OTP_VERSION}-debian-${DEBIAN_VERSION}"
ARG RUNNER_IMAGE="debian:${DEBIAN_VERSION}"

FROM ${BUILDER_IMAGE} as builder

# install build dependencies
RUN apt-get update -y && apt-get install -y build-essential git \
    && apt-get clean && rm -f /var/lib/apt/lists/*_*

# prepare build dir
WORKDIR /app

# install hex + rebar
RUN mix local.hex --force && \
    mix local.rebar --force

# set build ENV
ENV MIX_ENV="prod"

# install mix dependencies
COPY mix.exs mix.lock ./
RUN mix deps.get --only $MIX_ENV
RUN mkdir config

# copy compile-time config files before we compile dependencies
# to ensure any relevant config change will trigger the dependencies
# to be re-compiled.
COPY config/config.exs config/${MIX_ENV}.exs config/
RUN mix deps.compile

COPY priv priv

COPY lib lib

COPY assets assets

# compile assets
RUN mix assets.deploy

# Compile the release
RUN mix compile

# Changes to config/runtime.exs don't require recompiling the code
COPY config/runtime.exs config/

COPY rel rel
RUN mix release

# start a new build stage so that the final image will only contain
# the compiled release and other runtime necessities
FROM ${RUNNER_IMAGE}

RUN apt-get update -y && \
  apt-get install -y libstdc++6 openssl libncurses5 locales ca-certificates unzip wget \
  && apt-get clean && rm -f /var/lib/apt/lists/*_*

# Set the locale
RUN sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && locale-gen

ENV LANG en_US.UTF-8
ENV LANGUAGE en_US:en
ENV LC_ALL en_US.UTF-8

WORKDIR "/app"

RUN wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb \
    && wget https://storage.googleapis.com/chrome-for-testing-public/129.0.6668.70/linux64/chromedriver-linux64.zip \
    && apt-get update -y \
    && apt install -y ./google-chrome-stable_current_amd64.deb \
    && unzip chromedriver-linux64.zip \
    && mv chromedriver-linux64/chromedriver /usr/bin/chromedriver

RUN chown nobody /app

# set runner ENV
ENV MIX_ENV="prod"

# Only copy the final release from the build stage
COPY --from=builder --chown=nobody:root /app/_build/${MIX_ENV}/rel/twfex ./

USER nobody

# If using an environment that doesn't automatically reap zombie processes, it is
# advised to add an init process such as tini via `apt-get install`
# above and adding an entrypoint. See https://github.com/krallin/tini for details
# ENTRYPOINT ["/tini", "--"]

CMD ["/app/bin/server"]