![](/img/trans.png)
[英]java.io.IOException: Cannot run program “…”: java.io.IOException: error=2, No such file or directory
[英]Docker ENV LD_PRELOAD prevent container crash but throw java.io.IOException: Cannot run program "ls": error=2, No such file or directory
我在 Quarkus 服務器內的 Java 應用程序中調用com.google.firebase.cloud.FirestoreClient.getFirestore()
時遇到問題,該服務器在 Docker 容器內的 Alpine 3.15.4 上運行。
我創建了一個小演示。 結果是:
配置1
在 docker 文件中啟用
RUN apk update
RUN apk --no-cache add curl ca-certificates openjdk11-jre-headless
結果:
初始化正常
外殼失敗
配置2
在 docker 文件中禁用
#RUN apk update
#RUN apk --no-cache add curl ca-certificates openjdk11-jre-headless
結果:
初始化失敗
外殼沒問題
如果初始化失敗,則會記錄此錯誤
[de.ibe.DemoResource] (executor-thread-0) getFirestore
#
# A fatal error has been detected by the Java Runtime Environment:
#
# SIGSEGV (0xb) at pc=0x0000000000003efe, pid=1, tid=142
#
# JRE version: OpenJDK Runtime Environment (11.0.15+10) (build 11.0.15+10-alpine-r0)
# Java VM: OpenJDK 64-Bit Server VM (11.0.15+10-alpine-r0, mixed mode, tiered, compressed oops, g1 gc, linux-amd64)
# Problematic frame:
# C 0x0000000000003efe
#
# No core dump will be written. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
#
# An error report file with more information is saved as:
# /deployments/hs_err_pid1.log
#
# If you would like to submit a bug report, please visit:
# https://gitlab.alpinelinux.org/alpine/aports/issues
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
如果 shell 失敗,則會記錄此錯誤
java.io.IOException: Cannot run program "ls": error=2, No such file or directory
at java.base/java.lang.ProcessBuilder.start(ProcessBuilder.java:1128)
at java.base/java.lang.ProcessBuilder.start(ProcessBuilder.java:1071)
at de.ibe.DemoResource.shell(DemoResource.java:72)
at de.ibe.DemoResource.demo(DemoResource.java:37)
如果發現一些錯誤報告,例如
https://github.com/grpc/grpc-java/issues/8751 (see varpa89 commented on 28 Apr)
https://github.com/micrometer-metrics/micrometer/issues/2776
一種解決方法是創建兩個具有不同 docker 文件的容器。 但我更喜歡一個容器..
希望有人能抱我!
這是演示的代碼
package de.ibe;
import java.io.IOException;
import java.io.InputStream;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.jboss.logging.Logger;
import org.jboss.resteasy.annotations.jaxrs.PathParam;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.firebase.FirebaseApp;
import com.google.firebase.FirebaseOptions;
import com.google.firebase.cloud.FirestoreClient;
@Path("/demo")
public class DemoResource {
private static final Logger LOG = Logger.getLogger(DemoResource.class);
@GET
@Produces(MediaType.TEXT_PLAIN)
@Path("/{command}")
public String demo(@PathParam String command) {
try {
if (command == null || command.equals("")) {
return "command null or empty";
} else if (command.equals("init")) {
LOG.info("run init");
return this.init();
} else if (command.equals("shell")) {
LOG.info("run shell");
return this.shell();
} else {
return "unkown command";
}
} catch (Exception e) {
LOG.error(e);
return e.getMessage();
}
}
private String init() throws IOException {
try (InputStream in = this.getClass().getResourceAsStream("/demo-b9aa8a6.json")) {
if (in == null) {
return "init in is null";
}
GoogleCredentials credentials = GoogleCredentials.fromStream(in);
LOG.info("options");
FirebaseOptions options = new FirebaseOptions.Builder().setCredentials(credentials).build();
LOG.info("initializeApp");
FirebaseApp.initializeApp(options);
LOG.info("getFirestore");
FirestoreClient.getFirestore();
}
return "init ok";
}
private String shell() {
try {
final ProcessBuilder builder = new ProcessBuilder("ls");
builder.start();
} catch (IOException e) {
e.printStackTrace();
return "shell error";
}
return "shell ok";
}
}
碼頭工人文件
FROM alpine:3.15.4
ARG RUN_JAVA_VERSION=1.3.8
ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en'
# Install java and the run-java script
RUN apk update
RUN apk --no-cache add curl ca-certificates openjdk11-jre-headless
# init ok but shell false, enable
#RUN apk add gcompat
#ENV LD_PRELOAD=/lib/libgcompat.so.0
RUN mkdir /deployments
RUN chmod "g+rwX" /deployments
RUN curl https://repo1.maven.org/maven2/io/fabric8/run-java-sh/${RUN_JAVA_VERSION}/run-java-sh-${RUN_JAVA_VERSION}-sh.sh -o /deployments/run-java.sh
RUN chmod 540 /deployments/run-java.sh
# Configure the JAVA_OPTIONS, you can add -XshowSettings:vm to also display the heap size.
ENV JAVA_OPTIONS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager"
# We make four distinct layers so if there are application changes the library layers can be re-used
COPY target/quarkus-app/lib/ /deployments/lib/
COPY target/quarkus-app/*.jar /deployments/
COPY target/quarkus-app/app/ /deployments/app/
COPY target/quarkus-app/quarkus/ /deployments/quarkus/
EXPOSE 8080
ENTRYPOINT [ "/deployments/run-java.sh" ]
我無法解決問題,所以我找到了第二個“解決方法”。 解決方法 1.使用 2 個具有不同配置的容器。2 2.使用 alpin 以外的其他操作系統。
我使用 debian 而不是 alpin,問題就消失了。
FROM debian:11.3
ARG RUN_JAVA_VERSION=1.3.8
ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en'
#debian special--------------------------------------------
#install curl -y=send yes to input
RUN apt-get update; apt-get install curl -y
#install jdk
RUN mkdir -p /usr/share/man/man1 /usr/share/man/man2
RUN apt-get install -y --no-install-recommends openjdk-11-jre
#----------------------------------------------------------
RUN mkdir /deployments
RUN chmod "g+rwX" /deployments
RUN curl https://repo1.maven.org/maven2/io/fabric8/run-java-sh/${RUN_JAVA_VERSION}/run-java-sh-${RUN_JAVA_VERSION}-sh.sh -o /deployments/run-java.sh
RUN chmod 540 /deployments/run-java.sh
# Configure the JAVA_OPTIONS, you can add -XshowSettings:vm to also display the heap size.
ENV JAVA_OPTIONS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager"
# We make four distinct layers so if there are application changes the library layers can be re-used
COPY target/quarkus-app/lib/ /deployments/lib/
COPY target/quarkus-app/*.jar /deployments/
COPY target/quarkus-app/app/ /deployments/app/
COPY target/quarkus-app/quarkus/ /deployments/quarkus/
EXPOSE 8080
ENTRYPOINT [ "/deployments/run-java.sh" ]
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.