standard_init_linux。Go:190: exec用户进程导致“没有这样的文件或目录”——码头工人

当我在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
< p >尝试method1: 试着改变#!/bin/sh到#!/bin/bash但是得到相同的错误。

< p >尝试method2: 增加docker文件

中的dos2unix
RUN apt-get install -y dos2unix
RUN dos2unix /run.sh
266934 次浏览

在我的情况下,我必须将CRLF文件的行尾更改为LF,错误就消失了。

更改入口点如下所示。这对我很有效

ENTRYPOINT ["sh","/run.sh"]

正如tuomastik指出的,在评论中的文档要求第一个参数是可执行文件:

ENTRYPOINT有两种形式:

ENTRYPOINT ["executable", "param1", "param2"] (exec表单,优先)

ENTRYPOINT command param1 param2(外壳形式)

使用notepad++,点击编辑->EOL转换->从CRLF改为LF。

更新:对于VScode用户:您可以通过单击状态栏右下角的CRLF来更改CRLF

使用notepad++将CRLF替换为LF

  1. notepad++的查找/替换特性很好地处理了这个要求 好。只需打开替换对话框(CTRL+H),选择 扩展搜索模式(ALT+X),搜索“\r\n”并替换为 李“\ n”:< / >
  2. 点击全部替换(ALT+A)

重新构建并运行docker映像应该可以解决您的问题。

这是CRLF的问题。我用这个解决了这个问题:

git config --global core.eol lf


git config --global core.autocrlf input


find . -type f -print0 | xargs -0 dos2unix

将其添加到Dockerfile中

RUN cat /run.sh | tr -d '\r' > /run.sh

我在使用alpine映像时也遇到了同样的问题。

我的.sh文件有以下第一行:

#!/bin/bash

Alpine没有bash。所以把这条线改成

#!/bin/sh

或使用

apk add --no-cache bash

帮我解决了这个问题。

“没有这样的文件或目录”来自Linux,我看到了以下原因:

第一个原因是容器中没有文件。有些人试图从主机运行命令,而不将其添加到映像中。有些人通过在他们想要运行的命令之上安装一个卷来掩盖他们的命令。如果你运行相同的容器,但是使用shell而不是普通的entrypoint/cmd值,并运行ls /path/to/cmd,你会看到它是否存在。

下一个原因是运行了错误的命令。这通常出现在json/exec格式的命令不能正确解析的情况下。如果你看到一个命令试图运行["app",或类似的东西,json字符串没有被Docker解析,Linux试图使用shell将该命令解析为字符串。如果你的参数顺序错误,也会发生这种情况,例如,试图运行-it是一个标志,你试图将标志放在图像名称之后,而它们必须放在图像名称之前。

在shell脚本中,如果#!的第一行指向容器中不存在的命令,则出现此错误。对于某些人来说,这是试图在只有/bin/sh的映像中运行bash。在你的例子中,这可以来自脚本中的Windows换行。在编辑器中切换到Linux/Unix换行将会纠正这个错误。

对于二进制文件,如果缺少链接库,则出现此错误。我经常看到用libc编译的Go命令,但在alpine上用musl运行,或者根本没有任何库的scratch运行。您需要包含所有缺失的库,或者静态编译您的命令。要查看这些库链接,请在二进制文件上使用ldd /your/app

我只是想添加:对于VSCode用户,您可以通过单击状态栏中的CRLF将CRLF行结束符更改为LF,然后选择低频并保存文件。

我也有同样的问题,这个解决了它。 Steps to follow for VSCode < / p >

我解决了这个问题,设置我的设置在vscode。

    <李>文件
      <李>首选项
        <李>设置
          <李>文本编辑器
          1. 文件
          2. Eol -设置为\n
          3. 李< / ol > < / > 李< / ol > < / > 李< / ol > < / > 李< / ol > < / >

          问候

假设在alpine容器中运行go二进制时遇到这个问题。在构建bin之前导出以下变量

# CGO has to be disabled for alpine
export CGO_ENABLED=0

然后go build

请注意类似的错误,例如:

standard_init_linux.go:211: exec user process caused "no such file or directory"

如果为其构建映像的体系结构与您的系统不匹配,就会发生这种情况。例如,试图在x86_64机器上运行为arm64构建的映像会生成此错误。

我发现了一个特殊的边缘情况,我在高山容器中使用tini init,但由于我没有使用静态链接的版本,并且默认安装了Alpine使用musl libc而不是GNU libc库,它崩溃了,并出现了完全相同的错误消息。

如果我理解了这一点,并花时间正确地阅读文档,我就会发现Tini静态,在更改为后,解决了我的问题。

这是因为shell脚本是在windows中格式化的,我们需要更改为unix格式。 dos2unix命令可以在任何Linux系统上执行

dos2unix your-file.sh

如果你不能访问Linux系统,你可以使用Git Bash for Windows,它带有dos2unix.exe

dos2unix.exe your-file.sh

这里有多个正确答案。我没有看到它的VIM版本,所以在这里。在VIM中打开文件,检查底部状态行例如,执行set ff=dos(用于CRLF)或set ff=unix(用于LF)。

我在x86机器上基于ARM构建docker映像时遇到了相同的错误消息。这个问题可以通过安装QEMU和注册脚本来解决

#Install the qemu
sudo apt-get install qemu binfmt-support qemu-user-static packages


#This step will execute the registering scripts
docker run --rm --privileged multiarch/qemu-user-static --reset -p yes

我在使用CGO构建应用程序时遇到了这个问题,然后将其复制到scratch映像。Libc不存在,所以我使用alpine作为我的基映像。

我解决了一个类似的问题

< p >我的配置: →Docker桌面WSL 2后端- Windows →required CGO_ENABLED=1,因为我使用库编译了一个Kafka生产者 confluent-kafka-go.v1 /卡夫卡< / p >

我的docker映像已经构建成功,但当我使用docker-compose启动映像时,出现了同样的问题:

xxxxx:~/cp-all-in-one/cp-all-in-one-community# docker-compose up
Recreating ms-c3alert ... done
Attaching to ms-c3alert
ms-c3alert | standard_init_linux.go:211: exec user process caused "no such file or directory"
ms-c3alert exited with code 1

之后,在线程和另一个页面测试所有选项…我发现修复添加在go build句子-ldflags='-w -extldflags“-static"'

RUN CGO_ENABLED=1 GOOS=linux GOARCH=amd64 go build -ldflags='-w -extldflags "-static"' -a -installsuffix cgo -o c3alert .

对于VScode用户,在IDE的右下角角可以找到< >强CRLF /低频< / >强,因此切换到< >强劲低频< / >强并再次保存文件。恩! !你会没事的。

enter image description here

我在.sh文件的末尾多了一行。我删除了它并修复了这个问题。

你可以在Mac上使用BBEdit来排序这个问题,因为notepad++不可用。

从窗户底部就能看出来。除了字符集选项

存在的问题:

问题来自. sh文件。首先,我们必须记住窗户使用\ r \ n作为行尾,而Linux和Mac使用\ n。Git有一个叫做autoclrf的特性,在Windows上通常设置为“true”。当从Git存储库下载完成后,会自动将\ n转换为\ r \ n,但Git不会对此进行任何形式的通知,因此会生成错误。这个过程很好,至少对其他文件是这样,但对bash文件就不是这样了,就像entrypoint.sh文件一样。

立即解决方案:

打开您最喜欢的代码编辑器并更改导致冲突的文件的行结束符,在我们的示例中为entrypoint.sh。你可以在软件右下角的Visual Studio Code中做到这一点,单击它说CRLF的地方,并将文件的行尾更改为低频

从下面的链接阅读永久解决方案的整篇文章:

https://davidcasr.medium.com/docker-standard-init-linux-go-211-exec-user-process-caused-no-such-file-or-directory-en-c0cb42edb295

如果试图在从头开始的容器中运行动态链接的可执行文件,也会出现此错误。可执行文件将不能链接到共享(so)库,并将报告一个(信息不那么丰富)“没有这样的文件或目录”;错误。

让我们构建一个动态可执行文件test:

cat <<EOF | g++ -x c++ - -o test
#include <iostream>
int main() {
std::cerr << "Hello!" << std::endl;
return 0;
}
EOF

这确实是一个动态可执行文件。运行ldd test将报告如下内容(依赖于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++链接器命令中使用-static标志)来解决的,它会生成一个独立的可执行文件。

我正在构建一个应用程序,这些答案中的每一个对我来说都是错误的,所以我想分享我的解决方案。对我来说,我有一个没有Windows参与的Dockerfile(在Mac上编码,尽管在macOS 11和macOS 12上共享一个Dockerfile)。行尾是一样的)。

对我来说,最终的解决方案是,我需要将我的应用程序构建为一个静态链接的二进制文件,它可以在没有外部依赖的情况下运行。我正在为一个Go应用程序构建Dockerfile,它首先在一个Go构建器映像中构建,然后在一个草稿映像中构建。为了允许我的二进制文件从头运行,我必须添加CGO_ENABLED=0 标志。更多信息请访问reddit页面:https://www.reddit.com/r/golang/comments/pi97sp/comment/hbo0fq6/?utm_source=share&utm_medium=web2x&context=3

我的代码,它最终工作:

############################
# STEP 1 build optimized executable binary
############################
FROM golang:1.16-alpine AS builder


WORKDIR /app


COPY go.mod ./
COPY go.sum ./
RUN go mod download


COPY *.go ./


RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-w -s" -o cl-api


############################
# STEP 2 build a small image
############################
FROM scratch


COPY --from=builder /app/cl-api /


EXPOSE 8000


ENTRYPOINT ["/cl-api"]


在使用下面的代码构建时,我遇到了类似的问题

FROM golang:1.18.0-alpine3.15 AS builder


WORKDIR /go/src/blah
COPY . .


RUN go get -d -v ./...
RUN go install -v ./...


WORKDIR /go/src/blah


FROM centos AS runtime   ## NOTICE THE DISTRO CHANGE HERE
COPY --from=builder /go/bin/blah /bin/blah


CMD ["blah"]

以下是我的解决方案(与上面概述的相同,但添加了供人们检查)

FROM golang:1.18.0-alpine3.15 AS builder


WORKDIR /go/src/blah
COPY . .


RUN go get -d -v ./...
RUN export CGO_ENABLED=0 && go install -v ./...    <== added during install/build


WORKDIR /go/src/blah


FROM centos AS runtime
COPY --from=builder /go/bin/blah /bin/blah


CMD ["blah"]

欢呼。