1

I am trying to run jython.sh from my Docker container and below are the Jython and Java versions.
We really need to suppress this error, this is very misleading and looks messy. This error is displayed before the execution of every call to Jython and looks like it cannot find the shell.
Is there a way I can fix the error/exception thrown below?
How to make shell visible to java in docker?

Commands used:

docker run -d <image_name>
docker exec -it <container_name> bash

Dockerfile

FROM alpine:latest

ARG IMAGE_NAME

ENV PATH=$PATH:/bin:/opt/user/jre/bin
ENV LIBRARY_PATH=$LIBRARY_PATH:/opt/user/jre/lib/amd64/server:/opt/user/jre/lib/amd64/jli:/opt/user/jre/lib/amd64

USER user

VOLUME /opt/user/etc/
VOLUME /var/log/user

EXPOSE 6800

ENTRYPOINT ["/bin/bash", "/opt/user/bin/startup.sh", "user"]
#startup.sh script contains some container specific initialization

System requirements

Jython 2.7.1 (default:0df7adb1b397, Jun 30 2017, 19:02:43)
[OpenJDK 64-Bit Server VM (AdoptOpenJDK)] on java1.8.0_292
Type "help", "copyright", "credits" or "license" for more information.

Actual result

$ ./jython.sh
[ERROR] Failed to construct terminal; falling back to unsupported
java.io.IOException: Cannot run program "sh": error=2, No such file or directory
        at java.lang.ProcessBuilder.start(ProcessBuilder.java:1048)
        at org.python.jline.internal.TerminalLineSettings.exec(TerminalLineSettings.java:308)
        at org.python.jline.internal.TerminalLineSettings.stty(TerminalLineSettings.java:282)
        at org.python.jline.internal.TerminalLineSettings.get(TerminalLineSettings.java:143)
        at org.python.jline.internal.TerminalLineSettings.<init>(TerminalLineSettings.java:108)
        at org.python.jline.internal.TerminalLineSettings.getSettings(TerminalLineSettings.java:123)
        at org.python.jline.UnixTerminal.<init>(UnixTerminal.java:60)
        at org.python.jline.UnixTerminal.<init>(UnixTerminal.java:50)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
        at java.lang.Class.newInstance(Class.java:442)
        at org.python.jline.TerminalFactory.getFlavor(TerminalFactory.java:211)
        at org.python.jline.TerminalFactory.create(TerminalFactory.java:102)
        at org.python.jline.TerminalFactory.get(TerminalFactory.java:186)
        at org.python.jline.TerminalFactory.get(TerminalFactory.java:192)
        at org.python.jline.console.ConsoleReader.<init>(ConsoleReader.java:243)
        at org.python.util.JLineConsole.install(JLineConsole.java:107)
        at org.python.core.Py.installConsole(Py.java:1744)
        at org.python.core.PySystemState.initConsole(PySystemState.java:1269)
        at org.python.core.PySystemState.doInitialize(PySystemState.java:1119)
        at org.python.core.PySystemState.initialize(PySystemState.java:1033)
        at org.python.core.PySystemState.initialize(PySystemState.java:989)
        at org.python.core.PySystemState.initialize(PySystemState.java:984)
        at org.python.util.jython.run(jython.java:263)
        at org.python.util.jython.main(jython.java:142)
Caused by: java.io.IOException: error=2, No such file or directory
        at java.lang.UNIXProcess.forkAndExec(Native Method)
        at java.lang.UNIXProcess.<init>(UNIXProcess.java:247)
        at java.lang.ProcessImpl.start(ProcessImpl.java:134)
        at java.lang.ProcessBuilder.start(ProcessBuilder.java:1029)
        ... 26 more

Jython 2.7.1 (default:0df7adb1b397, Jun 30 2017, 19:02:43)
[OpenJDK 64-Bit Server VM (AdoptOpenJDK)] on java1.8.0_292
Type "help", "copyright", "credits" or "license" for more information.
>>>

Expected result

$ ./jython.sh
Jython 2.7.1 (default:0df7adb1b397, Jun 30 2017, 19:02:43)
[OpenJDK 64-Bit Server VM (AdoptOpenJDK)] on java1.8.0_292
Type "help", "copyright", "credits" or "license" for more information.
>>> 

Working environment

However, I'm able to run Jython without any error/exception with Alpine image & OpenJDK8

Dockerfile

FROM alpine:latest
RUN apk update && apk add --no-cache openjdk8 \
  && apk add --no-cache bash \
bash-5.1$ ./jython.sh
Jython 2.7.1 (default:0df7adb1b397, Jun 30 2017, 19:02:43)
[OpenJDK 64-Bit Server VM (IcedTea)] on java1.8.0_302
Type "help", "copyright", "credits" or "license" for more information.
>>>
β.εηοιτ.βε
  • 33,893
  • 13
  • 69
  • 83
PoornimaCR
  • 41
  • 8
  • check contents of `jython.sh`, is it possible that the first line contains something like `!/bin/sh`? – Lei Yang Mar 15 '22 at 08:00
  • It has #!/usr/bin/env bash – PoornimaCR Mar 15 '22 at 08:06
  • i'm not familiar with jython but seems it is trying to run `sh` command, can you confirm `sh` command exists, and if not, try change that line to `#!/usr/bin/bash`? – Lei Yang Mar 15 '22 at 08:10
  • yes `sh` command exists. bash-5.1# ./jython.sh bash: ./jython.sh: /usr/bin/bash: bad interpreter: No such file or directory – PoornimaCR Mar 15 '22 at 08:16
  • what about `#!/bin/bash`? – Lei Yang Mar 15 '22 at 08:25
  • `#!/bin/bash` throws the same exception as above. It looks it can't find the SHELL. – PoornimaCR Mar 15 '22 at 08:28
  • Try running `bash -x ./jython.sh`, this should give you a better idea what it's actually executing. – Joachim Sauer Mar 15 '22 at 08:48
  • The only difference I see after running `bash -x ./jython.sh` is the working environment has alpine with openjdk8. The non-working environment has alpine by using the JDK in the project zip file. Seems the error is related to the OS and the java installation. – PoornimaCR Mar 15 '22 at 09:05
  • Then change the JAVA_HOME and PATH variable to point to openjdk8 in your docker file adjust and print the path variable or java -v – Senthil Mar 15 '22 at 10:07
  • That's the pain I'm enduring - not supposed to use openjdk8 instead use the JDK which is bundled in the project application zip file. – PoornimaCR Mar 15 '22 at 10:43
  • Could you add, in an [edit] of your question, the result of `docker run ls -la $(which sh)` for both the working and non-working image? – β.εηοιτ.βε Mar 16 '22 at 18:49

1 Answers1

3

The Alpine distribution does not come with bash, but a lightweight shell called ash.

From there on, you have two possibilities, either your script is simple enough to be executed by ash, and you can adapt your shebang and usage accordingly, or, you install bash in your Alpine container.

So, either, in your script:

#!/usr/bin/env ash

echo 'I work'

Or, in your Dockerfile

FROM alpine:latest

RUN apk add --no-cache bash

# the rest of your container comes here

If your script does confuse sh for bash, what you could also do is to change the shell where /bin/sh points, which is, per default /bin/busybox by changing the symlink of /bin/sh, this way:

FROM alpine:latest

RUN apk add --no-cache bash \
    && ln -sf /bin/bash /bin/sh

# the rest of your container comes here

And that is actually what you are doing already in the other container that you said is working

FROM alpine:latest
RUN apk update && apk add --no-cache openjdk8 \
  && apk add --no-cache bash
###                      ^--- Here you are installing bash

Extra note: apk update is not needed when installing packages with the --no-cache flag.
Worth reading: Alpine Dockerfile Advantages of --no-cache Vs. rm /var/cache/apk/*

β.εηοιτ.βε
  • 33,893
  • 13
  • 69
  • 83
  • 1. Added `#!/usr/bin/env ash` in the script it throws syntax error: unexpected "(" (expecting "fi") 2. Also, in dockerfile `apk add --no-cache bash` but still, no luck ended up with the same error/exception as mentioned in the post. – PoornimaCR Mar 16 '22 at 10:03
  • 1. it means your script is not compatible with ash, so install bash is better option 2. seems the python or java program is using `sh` in a hardcoded way. it it possible that `bash` is installed but `sh` still not found? – Lei Yang Mar 16 '22 at 14:59
  • 2. Or it assumes the shell per default is bash, which is not, but that can be changed or you forgot to rebuild the image? – β.εηοιτ.βε Mar 16 '22 at 18:42
  • Knowing the content of jython.sh could actually help. – β.εηοιτ.βε Mar 16 '22 at 18:43
  • @PoornimaCR I updated the answer is case your script does confuses `sh` for `bash`. – β.εηοιτ.βε Mar 16 '22 at 19:40