Error "/usr/bin/env: unrecognized option: S" with Alpine Linux image causes CI script to fail

I am using our own image in a GitLab runner. The image is based on Alpine Linux 3.12. During a stage of the script that executes an external shell script, the command fails with the following error:

$ echo "Checking for multidev environment on Pantheon"
Checking for multidev environment on Pantheon
$ /bin/bash ./gitlab-multidev-ci.sh
/usr/bin/env: unrecognized option: S
BusyBox v1.31.1 () multi-call binary.
Usage: env [-iu] [-] [name=value]... [PROG ARGS]
Print the current environment or run PROG after setting up
the specified environment
	-, -i	Start with an empty environment
	-u	Remove variable from the environment

The CI script looks like this:

.deploy:pantheon-multidev:
  extends: .deploy:pantheon
  script:
    - *deploy_pantheon_prep
    - echo "Checking for multidev environment on Pantheon"
    - "/bin/bash ./gitlab-multidev-ci.sh"
    - *deploy_pantheon_push

So it is failing on the line:

    - "/bin/bash ./gitlab-multidev-ci.sh"

I have tried to remove the quotation marks on that line and that doesn’t make a difference. Same error.

The env command included in Alpine Linux does not support the -S switch. Unfortunately I don’t know when this started happening, but I know that this script used to work within the past year, so is there some reason why the script needs to run env -S to execute my external shell script within the container? Can I change this behaviour? Avoid it somehow? Perhaps changing my ci script somehow?

1 Like

Hi @cheekyrob

Are you pinning the version of Alpine Linux that you are using, or are you using a :latest version?

Maybe this is a silly question, but does the gitlab-multidev-ci.sh script call env explicitly? Sometimes this is used in the #! line of shell scripts?

Hi @snim2 , thanks for the reply. Yes, it is pinned at 3.12.

Here is a link to my image on docker hub. I’m using v0.6.2 in this instance, but I’ve tried with other versions of my image (notably one that uses Alpine 3.14) and /usr/bin/env never supports -S:

https://hub.docker.com/layers/cheekyrob/cmm-builder/0.6.2/images/sha256-3467e27d411ddac4fc79f72752b22537a65de8b1733cbd6dfa6e0ebe7266f3e5?context=explore

Cheers,
-R

Also, no, the script does not call env. For privacy’s sake, I don’t want to include the whole script, but it starts like this:

#!/bin/bash

# Store the mr- environment name
if [ -z "$PANTHEON_ENV" ]; then
    export PANTHEON_ENV=$CI_COMMIT_REF_NAME
fi

I believe that particular step of the CI script is being run with /usr/bin/env -S "/bin/bash ./gitlab-multidev-ci.sh" or something to that effect. I imagine that is to provide the environment variables to the script. I just don’t know when or why the -S was added, because I’m certain this script worked before and I’ve always used Alpine Linux. I’ve used it myself, it checks for and optionally creates a new multidev environment on Pantheon.

What do you get if you change this line to just ./gitlab-multidev-ci.sh? Usually each line in the script section is executed as a Bash command, so AIUI you don’t explicitly need to call /bin/bash.

Thanks again @snim2 . I’ll try that but I suspect I’ll just end up with a permission denied: ./gitlab-multidev-ci.sh since the file isn’t executable. I suppose I can chmod it to make it executable though. Will let you know. Cheers,
-R

Unfortunately it still tries to execute the entire line with env:

$ echo "Checking for multidev environment on Pantheon"
Checking for multidev environment on Pantheon
$ chmod 755 ./gitlab-multidev-ci.sh
$ ./gitlab-multidev-ci.sh
/usr/bin/env: unrecognized option: S
BusyBox v1.31.1 () multi-call binary.
Usage: env [-iu] [-] [name=value]... [PROG ARGS]
Print the current environment or run PROG after setting up
the specified environment
	-, -i	Start with an empty environment
	-u	Remove variable from the environment

Seems to want to run it with env -S no matter what :confused:

In this instance I usually do chmod +x filename.sh && ./filename.sh FWIW

Yes, I had it on one line previously with the same error, just wanted to isolate the execution of the script to its own line, but the +x is certainly more succinct than 755 :slight_smile:

So, according to this it’s more recent versions of coreutils that have the -S option. Are you able to bump the version of Alpine that you are using?

3 Likes

Well, I did try running with an image using Alpine 3.14 and had the same issue, but I’ll try env -S on something even newer and see if it works. I’m using older distros in many cases because, unfortunately, the versions of the packages I need are old as well, to work with old websites :frowning: But I’ll see what I can do. I was just hoping there was a way to avoid the -S requirement. I also wonder when that was added, or if something else changed, because like I said, this used to work.

Thank you for your thoughts, appreciate it!

1 Like

@snim2 Your mention of coreutils helped me to realize that I can just explicitly install that package on my Alpine images and get the “better” versions of those utils :slight_smile: My images were always using the utils that were included in the base installation. This does the trick!

Thanks for nudging me in the right direction, cheers!

2 Likes

@cheekyrob @snim2 amazing, thanks for documenting this!

What worked for us was to add apk add --no-cache coreutils in our Dockerfile:

FROM node:lts-alpine

# Install dependencies:
# - env to enable -S flag for custom shebang (coreutils) https://forum.gitlab.com/t/error-usr-bin-env-unrecognized-option-s-with-alpine-linux-image-causes-ci-script-to-fail/64063
RUN apk update
RUN apk add --no-cache coreutils