Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parallel cannot identify the default shell #5339

Open
1 task done
hajapy opened this issue Feb 29, 2024 · 19 comments · May be fixed by #5320
Open
1 task done

Parallel cannot identify the default shell #5339

hajapy opened this issue Feb 29, 2024 · 19 comments · May be fixed by #5320
Labels
bug Something isn't working O: backlog 🤖 Backlog, stale ignores this label

Comments

@hajapy
Copy link

hajapy commented Feb 29, 2024

Is there an existing issue for this?

  • I have searched the existing issues

Current Behavior

Running super-linter images locally fails with multiple error message /bin/sh: BuildFileArrays: not found.

x-ref: #5335 (comment)

Expected Behavior

The parallel command should not fail in this way and the /bin/sh: BuildFileArrays: not found. should not occur.

Super-Linter version

Tested with slim-6.2.0 and slim-latest

Relevant log output

Full log.txt

{
    "Seq": 42,
    "Host": ":",
    "Starttime": 1709166454.902,
    "JobRuntime": 0.036,
    "Send": 0,
    "Receive": 0,
    "Exitval": 127,
    "Signal": 0,
    "Command": "BuildFileArrays /tmp/lint/test/linters/xml/xsd_bad_1.xsd /tmp/lint/test/linters/xml/xsd_good_1.xsd /tmp/lint/test/linters/yaml/yml_bad_1.yml /tmp/lint/test/linters/yaml/yml_good_1.yml /tmp/lint/test/run-super-linter-tests.sh /tmp/lint/test/validate-docker-labels.sh /tmp/lint/version.txt /tmp/lint",
    "V": [
      "/tmp/lint/test/linters/xml/xsd_bad_1.xsd",
      "/tmp/lint/test/linters/xml/xsd_good_1.xsd",
      "/tmp/lint/test/linters/yaml/yml_bad_1.yml",
      "/tmp/lint/test/linters/yaml/yml_good_1.yml",
      "/tmp/lint/test/run-super-linter-tests.sh",
      "/tmp/lint/test/validate-docker-labels.sh",
      "/tmp/lint/version.txt",
      "/tmp/lint"
    ],
    "Stdout": "",
    "Stderr": "/bin/sh: BuildFileArrays: not found
"
  }

...

/bin/sh: BuildFileArrays: not found
/bin/sh: BuildFileArrays: not found
/bin/sh: BuildFileArrays: not found
/bin/sh: BuildFileArrays: not found
/bin/sh: BuildFileArrays: not found
------
2024-02-29 00:27:35 [FATAL]   Error when building the list of files and directories to lint.
2024-02-29 00:27:35 [DEBUG]   Captured exit code: 1
2024-02-29 00:27:35 [DEBUG]   Removing temporary files and directories
2024-02-29 00:27:35 [DEBUG]   LOG_FILE_PATH: /tmp/lint/super-linter.log
2024-02-29 00:27:35 [DEBUG]   Skipping the moving of the log file from /tmp/tmp.k9y3EiHek2 to /tmp/lint/super-linter.log
make: *** [lint-codebase] Error 1

Steps To Reproduce

  1. Clone this repo (super-linter/super-linter)
  2. git rev-parse HEAD
    6c1f40c
  3. make SUPER_LINTER_TEST_CONTAINER_URL=ghcr.io/super-linter/super-linter:slim-latest@sha256:5c73796a5ba0a5b6811712bfb2a58cc39346a92ccafd28f570ab46ea16e68e61 lint-codebase | tee log.txt

Anything else?

I believe this is occurring because the SHELL environment variable is not set and gnu parallel is choosing to use /bin/sh as a default even though bash is the desired shell. I suspect this can be resolved by exporting env var SHELL=/bin/bash (or setting this in the dockerfile).

Example from testing in the slim-latest image:

e7bc280fd46d:/# doit() { echo "$@"; }
e7bc280fd46d:/# export -f doit
e7bc280fd46d:/# parallel --will-cite doit ::: 1 2 3
/bin/sh: doit: not found
/bin/sh: doit: not found
/bin/sh: doit: not found
e7bc280fd46d:/# SHELL=$(type -p bash) parallel --will-cite doit ::: 1 2 3
1
2
3
@hajapy hajapy added the bug Something isn't working label Feb 29, 2024
@hajapy
Copy link
Author

hajapy commented Feb 29, 2024

FYI, if I add the flag -e SHELL=/bin/bash to docker run commands when using these images, the immediate issue is resolved.

@ferrarimarco
Copy link
Collaborator

Hi @hajapy! Thanks for reporting this.

I tried the steps you posted, and I couldn't reproduce the issue. In my case, lining reports a success.

What is your runtime environment like?

We have a similar report in #5070 (comment) about running this on a arm64 machine (which we don't support (yet?))

@hajapy
Copy link
Author

hajapy commented Feb 29, 2024

I am running on an M1 macbook pro (macOS 14.3.1) with Docker Desktop 4.27.2 (137060) which runs the amd64 image under emulation.

@ferrarimarco
Copy link
Collaborator

I see. That looks like the same issue that's reported in the comment I linked.

The SHELL variable is currently set to /bin/ash:

docker run --rm -it --entrypoint /bin/bash ghcr.io/super-linter/super-linter:slim-latest@sha256:5c73796a5ba0a5b6811712bfb2a58cc39346a92ccafd28f570ab46ea16e68e61
blabla:/# echo $SHELL
/bin/ash

I think it makes sense to set it to /bin/bash, given that is what we assume.

@ferrarimarco
Copy link
Collaborator

Given that you already cloned the super-linter repository, if you feel adventurous, you can try this:

Add the following line after line 396 in Dockerfile:

ENV SHELL=/bin/bash

Then run:

make docker
make lint-codebase

This should hopefully resolve this particular issue. If so, we can create a PR to implement that.

Thanks!

@hajapy
Copy link
Author

hajapy commented Feb 29, 2024

I gave it a try with --platform linux/amd64 flag passed to docker buildx build command since I am an arm64 but it is erroring out for me during the build

 => ERROR [standard  9/15] RUN PS_INSTALL_FOLDER="$(cat /tmp/PS_INSTALL_FOLDER)"     && echo "PS_INSTALL_FOLDER: ${PS_INSTALL_FOL  1.8s
------
 > [standard  9/15] RUN PS_INSTALL_FOLDER="$(cat /tmp/PS_INSTALL_FOLDER)"     && echo "PS_INSTALL_FOLDER: ${PS_INSTALL_FOLDER}"     && ln -s "${PS_INSTALL_FOLDER}/pwsh" /usr/bin/pwsh     && chmod a+x,o-w "${PS_INSTALL_FOLDER}/pwsh"     && pwsh -c "Install-Module -Name PSScriptAnalyzer -RequiredVersion 1.21.0 -Scope AllUsers -Force"     && rm -rf /tmp/PS_INSTALL_FOLDER:
0.122 PS_INSTALL_FOLDER: /opt/microsoft/powershell/7
1.759 'Mandatory' property specified was not found.
1.759 
------
Dockerfile:476

🤷‍♂️

FWIW, I think I may have a clue why this is happening: https://git.savannah.gnu.org/cgit/parallel.git/tree/src/parallel#n2246
It seems gnu parallel tries to determine the shell with various fallbacks:

 $Global::shell = $ENV{'PARALLEL_SHELL'} || parent_shell($$)
	|| $ENV{'SHELL'} || "/bin/sh";

So even defining SHELL env var won't override its priority logic if we're using a different shell which it can determine.

However, it seems under emulation parent_shell may not work?

cat /proc/$pid/cmdline
/run/rosetta/rosetta/bin/bash/bin/bash

also

readlink /proc/$$/exe
/run/rosetta/rosetta

I looks to me like it doesn't understand the parent shell using its various tricks for docker under rosetta emulation, thus falls back to $SHELL or /bin/sh.

@ferrarimarco
Copy link
Collaborator

I see, thanks for going far in triaging this.

So, if I read that logic correctly, PARALLEL_SHELL might work, instead of setting SHELL?

@hajapy
Copy link
Author

hajapy commented Feb 29, 2024

I believe both would work, with PARALLEL_SHELL being a forced override and SHELL being a fallback in case it can't automatically determine the shell correctly.

https://www.gnu.org/software/parallel/parallel_design.html#which-shell-to-use

If GNU parallel guesses wrong in these situation, set the shell using $PARALLEL_SHELL.

@ferrarimarco
Copy link
Collaborator

ferrarimarco commented Feb 29, 2024

I gave it a try with --platform linux/amd64 flag passed to docker buildx build command since I am an arm64 but it is erroring out for me during the build

 => ERROR [standard  9/15] RUN PS_INSTALL_FOLDER="$(cat /tmp/PS_INSTALL_FOLDER)"     && echo "PS_INSTALL_FOLDER: ${PS_INSTALL_FOL  1.8s
------
 > [standard  9/15] RUN PS_INSTALL_FOLDER="$(cat /tmp/PS_INSTALL_FOLDER)"     && echo "PS_INSTALL_FOLDER: ${PS_INSTALL_FOLDER}"     && ln -s "${PS_INSTALL_FOLDER}/pwsh" /usr/bin/pwsh     && chmod a+x,o-w "${PS_INSTALL_FOLDER}/pwsh"     && pwsh -c "Install-Module -Name PSScriptAnalyzer -RequiredVersion 1.21.0 -Scope AllUsers -Force"     && rm -rf /tmp/PS_INSTALL_FOLDER:
0.122 PS_INSTALL_FOLDER: /opt/microsoft/powershell/7
1.759 'Mandatory' property specified was not found.
1.759 
------
Dockerfile:476

🤷‍♂️

Maybe we have better luck with the slim image?

make IMAGE=slim docker
make lint-codebase

@ferrarimarco
Copy link
Collaborator

Also, I'd like to reproduce this in our CI environment somehow, so we can have feedback about the proposed fix. I wasn't able to reproduce this in a Linux-based environment.

@ferrarimarco
Copy link
Collaborator

Another observation about export -f doit: I don't think that the Dash shell support exporting functions, does it?

@hajapy
Copy link
Author

hajapy commented Feb 29, 2024

Maybe we have better luck with the slim image?

make IMAGE=slim docker
make lint-codebase

Yes, this worked.

Another observation about export -f doit: I don't think that the Dash shell support exporting functions, does it?

AFAIK, this is bash-specific. I don't know what (if any) other shells support it. But it is how super-linter is making the function available to parallel: https://github.com/super-linter/super-linter/blob/main/lib/functions/buildFileList.sh#L511

Also, I'd like to reproduce this in our CI environment somehow, so we can have feedback about the proposed fix. I wasn't able to reproduce this in a Linux-based environment.

You could configure a macos arm runner to run a test of a built amd64 image under emulation? https://github.blog/2023-10-02-introducing-the-new-apple-silicon-powered-m1-macos-larger-runner-for-github-actions/

@ferrarimarco
Copy link
Collaborator

The GNU parallel manual states, in line with what you observed in its source code:

$PARALLEL_SHELL

Use this shell for the commands run by GNU parallel:

- $PARALLEL_SHELL. If undefined use:
- The shell that started GNU parallel. If that cannot be determined:
- $SHELL. If undefined use:
- /bin/sh

The shell that started GNU Parallel is /usr/bin/env bash, as the hashbang specifies, so it's probably falling the

However, it seems under emulation parent_shell may not work?

case you listed above.

@ferrarimarco
Copy link
Collaborator

Ah! We crossed the streams :)

Maybe we have better luck with the slim image?

make IMAGE=slim docker
make lint-codebase

Yes, this worked.

Another observation about export -f doit: I don't think that the Dash shell support exporting functions, does it?

AFAIK, this is bash-specific. I don't know what (if any) other shells support it. But it is how super-linter is making the function available to parallel: https://github.com/super-linter/super-linter/blob/main/lib/functions/buildFileList.sh#L511

Yeah, I think so.

Also, I'd like to reproduce this in our CI environment somehow, so we can have feedback about the proposed fix. I wasn't able to reproduce this in a Linux-based environment.

You could configure a macos arm runner to run a test of a built amd64 image under emulation? https://github.blog/2023-10-02-introducing-the-new-apple-silicon-powered-m1-macos-larger-runner-for-github-actions/

Yeah, saw that. We dynamically generate part of the workflow matrix, so I'm thinking about the best way to do this ;)

@ferrarimarco
Copy link
Collaborator

Also, there are a few interesting debug statement in the parent_shell function (https://git.savannah.gnu.org/cgit/parallel.git/tree/src/parallel#n2246), but I didn't figure out how to enable debug logging when running parallel...

@ferrarimarco ferrarimarco added the O: backlog 🤖 Backlog, stale ignores this label label Feb 29, 2024
@ferrarimarco ferrarimarco changed the title Error running super-linter locally Parallel cannot identify the default shell Feb 29, 2024
@hajapy
Copy link
Author

hajapy commented Mar 1, 2024

I figured out you can add -D all flag to enable those debug statements, though it does not seem documented. It didn't provide a ton of insight on its own, but I believe this is failing because the command under emulation begins with /run/rosetta/rosetta, which breaks the regexp used to determine the shell.

f9d55c3f3b5a:/# ps 
PID   USER     TIME  COMMAND
    1 root      0:00 {bash} /run/rosetta/rosetta /bin/bash /bin/bash
   12 root      0:00 /bin/ps ps

@ferrarimarco
Copy link
Collaborator

Thanks for these details!

To me, this looks like something that Parallel should address, although the lowest hanging fruit might be to explicitly set the SHELL variable in the super-linter Dockerfile, although I'm not sure about which side effects it might have on other processes.

@hajapy
Copy link
Author

hajapy commented Mar 1, 2024

If you're worried about unintended side effects you could just add the SHELL=/bin/bash when building the parallel command.

I'll have a look into created a bug report in the parallel project.

Once arm64 images become available this becomes moot, as there shouldn't be as much need to run super-linter under emulation. There is also the workaround of just feeding the env variable in docker run invocation.

@ferrarimarco
Copy link
Collaborator

Maybe we can try with PARALLEL_SHELL first?

@ferrarimarco ferrarimarco mentioned this issue Apr 16, 2024
1 task
@ferrarimarco ferrarimarco linked a pull request May 3, 2024 that will close this issue
8 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working O: backlog 🤖 Backlog, stale ignores this label
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants