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

Calling script without shebang results into "Exec format error" on alpine, but not on other linux distros or macos #404

Open
hwo411 opened this issue Jun 26, 2024 · 4 comments

Comments

@hwo411
Copy link

hwo411 commented Jun 26, 2024

The problem

Hello alpine maintainers! I wasn't sure which repo to report this problem, but decided to use this repo, since all we do is in docker.

Let me start with minimal example of the problem

echo "echo 1" > qwe
chmod +x qwe
env -i ./qwe

The following code results into "env: can't execute './qwe': Exec format error", but only in alpine images (the one I used was 3.20.0).

I tested this code also on debian and on my macos and it outputs 1 and doesn't cause the error.

Why is it important?

This is a minimal example of reproducing a problem that we had with building react native app in docker container on our CI.

A similar situation happens when a script without shebang from react native build tools is called from java process in gradle. I'm not a linux expert, but I reduced this problem to the minimal example above, which works on MacOS (like the original react native build script), but doesn't work on alpine.

The part of build log looks like this

 Caused by: net.rubygrapefruit.platform.NativeException: Could not start '/app/mobile/app/node_modules/react-native-reanimated/android/build/intermediates/cxx/RelWithDebInfo/364h4n30/logs/arm64-v8a/prefab_command'
 	at net.rubygrapefruit.platform.internal.DefaultProcessLauncher.start(DefaultProcessLauncher.java:27)
 	at org.gradle.process.internal.ExecHandleRunner.startProcess(ExecHandleRunner.java:122)
 	at org.gradle.process.internal.ExecHandleRunner.lambda$run$0(ExecHandleRunner.java:80)
 	at org.gradle.internal.operations.CurrentBuildOperationRef.with(CurrentBuildOperationRef.java:80)
 	at org.gradle.process.internal.ExecHandleRunner.run(ExecHandleRunner.java:79)
 	... 5 more
 Caused by: java.io.IOException: Cannot run program "/app/mobile/app/node_modules/react-native-reanimated/android/build/intermediates/cxx/RelWithDebInfo/364h4n30/logs/arm64-v8a/prefab_command" (in directory "/app/mobile/app/node_modules/react-native-reanimated/android"): error=8, Exec format error
 	at java.base/java.lang.ProcessBuilder.start(ProcessBuilder.java:1143)
 	at java.base/java.lang.ProcessBuilder.start(ProcessBuilder.java:1073)
 	at net.rubygrapefruit.platform.internal.DefaultProcessLauncher.start(DefaultProcessLauncher.java:25)
 	... 9 more
 Caused by: java.io.IOException: error=8, Exec format error
 	at java.base/java.lang.ProcessImpl.forkAndExec(Native Method)
 	at java.base/java.lang.ProcessImpl.<init>(ProcessImpl.java:314)
 	at java.base/java.lang.ProcessImpl.start(ProcessImpl.java:244)
 	at java.base/java.lang.ProcessBuilder.start(ProcessBuilder.java:1110)
 	... 11 more

We investigated different reasons why it could happen (e.g., including architecture mismach), but in the end the minimal example above is what we came with. Since my understanding of the problem isn't deep enough, there is still a chance that these are 2 different problems, but I hope this background is helpful.

Questions

  1. Is it possible to somehow make the example above work without adding shebang? E.g., by passing some env variable? Or by enabling some setting? I'm asking this in a hope that we might do the same in our build system so that we don't have to migrate from alpine to another distro. I'm going to report this problem to RN, since they might also update their scripts to add shebang and then it works, but it might take quite some time.

  2. Can it be changed in alpine distro? And is it a bug or a normal behavior that can vary between distros?

  3. Could you please explain why it happens like this in alpine, but not in other distros? I'm quite curios why it happens and it might be helpful for others.

@fossdd
Copy link

fossdd commented Jul 1, 2024

the behaviour comes from busybox sh.

Is it possible to somehow make the example above work without adding shebang? E.g., by passing some env variable? Or by enabling some setting? I'm asking this in a hope that we might do the same in our build system so that we don't have to migrate from alpine to another distro. I'm going to report this problem to RN, since they might also update their scripts to add shebang and then it works, but it might take quite some time.

you could apk add bash and use bash instead of the default busybox sh.

Can it be changed in alpine distro? And is it a bug or a normal behavior that can vary between distros?
Could you please explain why it happens like this in alpine, but not in other distros? I'm quite curios why it happens and it might be helpful for others.

i guess this is because busybox sh used another exec* function to execute the file than bash. you may want to ask in more busybox related channels.

@hwo411
Copy link
Author

hwo411 commented Jul 2, 2024

@fossdd thanks for your answer!

Unfortunately, it didn't work for me with bash either.

I started a container running sleep 10000000, then connected to it via docker exec, installed bash and exited. Then connected with exec using bash command (so that sh is not executed) and executed the commands above. It still resulted into env: can't execute './qwe': Exec format error.

Commands that I executed:

docker run --rm -d --name testalpine alpine:latest sleep 100000000000
docker exec testalpine apk add bash
docker exec -it testalpine bash

and then execute the commands above.

I then tried to symlink /bin/sh to /bin/bash instead of /bin/busybox and it also didn't help.

So it doesn't seem to be just a busybox issue.

Also I tried to install busybox on debian and tried the same thing (using the same approach with sleep and exec) to execute commands from busybox and no error occured.

Do you have any other ideas why it might happen? Or did I do anything wrong with this?

@fossdd
Copy link

fossdd commented Jul 2, 2024

oh, yeah. I didn't realized that you're using env to execute the commands. env on alpine, is also busybox, which maybe is the problem here. so you might be lucky invoking it directly with ./qwe.

othewise the difference could maybe come from musl treating the function differently than glibc. but im no expert there.

@hwo411
Copy link
Author

hwo411 commented Jul 5, 2024

Thanks @fossdd! I did some additional investigations to verify your idea and got the following:

  1. Installing busybox on debian and using busybox env (even if you install it) doesn't run into this error
  2. Copying env from debian and using it on alpine (you need gcompat for that) still results into the same error

This makes me think it's likely to be alpine issue, not busybox one.

I'm also not expert here, but hope someone manages to clarify this behavior

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants