当我在windows 10上运行docker映像时。我得到这个错误:
standard_init_linux.go:190: exec user process caused "no such file or directory"
我的docker文件是:
FROM openjdk:8
EXPOSE 8080
VOLUME /tmp
ADD appagent.tar.gz /opt/app-agent
ADD services.jar app.jar
ADD run.sh /run.sh
# Install compiler and perl stuff
RUN apt-get update
RUN apt-get install -y build-essential
RUN apt-get install -y gcc-multilib
RUN apt-get install -y perl
# Install Percona Toolkit
RUN apt-get install --yes percona-toolkit
RUN ["chmod", "+x", "/run.sh"]
ENTRYPOINT ["/run.sh"]
脚本以#!开头/bin/sh
#!/bin/sh
set -e
JAVA_OPTS="-Dfile.encoding=UTF-8 -Djava.security.egd=file:/dev/urandom"
if [ "${APPD_APP_NAME}" != "" ]; then
JAVA_AGENT="-javaagent:/opt/app-agent/javaagent.jar
fi
exec java ${JVM_OPTS} ${JAVA_OPTS} ${JAVA_AGENT} -jar /app.jar
尝试method1:
试着改变#!/bin/sh到#!/bin/bash但是得到同样的错误。
尝试method2:
docker文件中新增dos2unix
RUN apt-get install -y dos2unix
RUN dos2unix /run.sh
存在的问题:
The problem comes from the .sh file. First we must remember that Windows uses \r\n as the end of the line, while Linux and Mac use \n. Git has a feature called autoclrf that is generally set to “true” on Windows. This automatically converts \n to \r\n upon completion of the download from a Git repository, but Git does not make any kind of notice of this, hence the error is generated. This process is good, at least for the other files, but it is not the case for bash files, as is the case for the entrypoint.sh file.
立即解决方案:
打开您最喜欢的代码编辑器并更改导致冲突的文件的行结束符,在我们的示例中是:entrypoint.sh。你可以在软件右下角的Visual Studio Code中做到这一点,单击CRLF,并将文件行的末尾更改为LF。
从下面的链接阅读整篇文章,找到永久的解决方案:
https://davidcasr.medium.com/docker-standard-init-linux-go-211-exec-user-process-caused-no-such-file-or-directory-en-c0cb42edb295
如果试图在从头开始的容器中运行动态链接的可执行文件,也会出现此错误。可执行文件将不能链接到共享库,并将报告一个(不是很有信息量)。"没有这样的文件或目录"错误。
让我们构建一个动态可执行测试:
cat <<EOF | g++ -x c++ - -o test
#include <iostream>
int main() {
std::cerr << "Hello!" << std::endl;
return 0;
}
EOF
这确实是一个动态可执行文件。运行ldd测试将报告如下内容(依赖于libc等):
linux-vdso.so.1 (0x00007ffd699fc000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007ff570f7a000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007ff570c76000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007ff570a5f000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007ff5706c0000)
/lib64/ld-linux-x86-64.so.2 (0x00007ff5714fe000)
现在,让我们用以前的可执行文件从头构建一个映像。Dockerfile将是:
FROM scratch
COPY test /
CMD [ "/test" ]
构建映像。然后,运行一个来自image的动态容器:
docker build . -t local/test
docker run --rm local/test
容器失败的退出码1,我得到:
standard_init_linux.go:219: exec user process caused: no such file or directory
这个问题是通过使用静态链接(在之前的gcc/g++ linker命令中使用-static flag)来解决的,它会生成一个独立的可执行文件。
“没有这样的文件或目录”来自Linux,我看到了以下原因:
第一个原因是容器中没有文件。有些人试图从主机运行命令,而不将其添加到映像中。有些人通过在他们想要运行的命令之上安装一个卷来掩盖他们的命令。如果你运行相同的容器,但是使用shell而不是普通的entrypoint/cmd值,并运行ls /path/to/cmd,你会看到它是否存在。
下一个原因是运行了错误的命令。这通常出现在json/exec格式的命令不能正确解析的情况下。如果你看到一个命令试图运行["app",或类似的东西,json字符串没有被Docker解析,Linux正试图使用shell将该命令解析为字符串。如果你打乱了参数的顺序,这也会发生,例如,试图运行-这是一个标志,你试图把标志放在图像名称之后,而它们必须放在图像名称之前。
对于shell脚本,如果第一行带有#!指向容器中不存在的命令。对于某些人来说,这是试图在只有/bin/sh的映像中运行bash。在你的例子中,这可以来自脚本中的Windows换行。在编辑器中切换到Linux/Unix换行将会纠正这个错误。
对于二进制文件,如果缺少链接库,则出现此错误。我经常看到这样的情况:使用libc编译的Go命令,但在alpine上使用musl或scratch运行,根本没有任何库。您需要包含所有缺失的库,或者静态编译您的命令。要查看这些库链接,请在二进制文件中使用ldd /your/app。