簡體   English   中英

standard_init_linux.go:190: exec 用戶進程導致“沒有這樣的文件或目錄” - Docker

[英]standard_init_linux.go:190: exec user process caused "no such file or directory" - Docker

當我在 Windows 10 上運行我的 docker 映像時。我收到此錯誤:

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

我的碼頭文件是:

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

嘗試的方法1:嘗試將 #!/bin/sh 更改為 #!/bin/bash但得到相同的錯誤。

嘗試的方法2:在docker文件中添加了dos2unix

RUN apt-get install -y dos2unix
RUN dos2unix /run.sh

使用記事本++,進入編輯-> EOL 轉換-> 從CRLF 更改為LF。

更新:對於 VScode 用戶:您可以通過單擊狀態欄右下方的 CRLF 將 CRLF 更改為 LF

如下更改入口點。 它對我有用

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

正如 tuomastik 在評論中指出的那樣,文檔要求第一個參數是可執行文件:

ENTRYPOINT 有兩種形式:

ENTRYPOINT ["executable", "param1", "param2"] (執行形式,首選)

ENTRYPOINT command param1 param2 (shell 形式)

使用alpine圖像時我遇到了同樣的問題。

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

#!/bin/bash

Alpine 沒有 bash。 所以將行更改為

#!/bin/sh

或安裝 bash

apk add --no-cache bash

為我解決了這個問題。

假設您在 alpine 容器中運行 go 二進制文件時遇到了這個問題。 在構建 bin 之前導出以下變量

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

然后go build

在我的情況下,我不得不將run.sh文件的行結尾從CRLF更改為LF並且錯誤消失了。

我只是想補充一點:對於 VSCode 用戶,您可以通過單擊狀態欄中的CRLF將 CRLF 行結尾更改為 LF,然后選擇LF並保存文件。

我有同樣的問題,這解決了它。 VSCode 要遵循的步驟

“沒有這樣的文件或目錄”來自 Linux,我看到了以下原因:

第一個原因實際上並沒有在您的容器中包含文件。 有些人試圖從主機運行命令而不將其添加到他們的圖像中。 有些人通過在他們想要運行的命令之上安裝一個卷來隱藏他們的命令。 如果您運行相同的容器,但使用 shell 而不是正常的 entrypoint/cmd 值,並運行ls /path/to/cmd您會看到它是否存在。

下一個原因是運行錯誤的命令。 這通常出現在運行命令的 json/exec 格式無法正確解析的情況下。 如果您看到一個命令試圖運行["app",或類似的東西,則 Docker 沒有解析 json 字符串,Linux 正在嘗試使用 shell 將命令解析為字符串。 如果您對 args 進行了錯誤排序,例如嘗試運行,也可能會發生這種情況-it這是您嘗試在圖像名稱之后放置標志的標志,而它們必須放在圖像名稱之前。

使用 shell 腳本,如果第一行帶有#!則會出現此錯誤。 指向容器內不存在的命令。 對於某些人來說,這是試圖在只有/bin/sh的圖像中運行bash 在您的情況下,這可以來自腳本中的 Windows 換行符。 在你的編輯器中切換到 Linux/Unix 換行將糾正這個問題。

對於二進制文件,如果缺少鏈接庫,則會出現此錯誤。 我經常在使用libc編譯的 Go 命令時看到這種情況,但在 alpine 上使用musl或從頭開始運行時根本沒有任何庫。 您需要包含所有缺少的庫或靜態編譯您的命令。 要查看這些庫鏈接,請在二進制文件上使用ldd /your/app

這是一個 CRLF 問題。 我用這個解決了這個問題:

git config --global core.eol lf

git config --global core.autocrlf input

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

請注意類似的錯誤,例如:

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

如果構建映像的架構與您的系統不匹配,則可能會發生這種情況。 例如,嘗試在x86_64機器上運行為arm64構建的映像可能會產生此錯誤。

我在使用 CGO 構建應用程序時遇到了這個問題,然后將其復制到scratch圖像。 那里不存在 Libc,所以我使用alpine作為我的基本映像。

使用 Notepad++ 將 CRLF 替換為 LF

  1. Notepad++ 的查找/替換功能很好地處理了這個要求。 只需打開替換對話框(CTRL+H),選擇擴展搜索模式(ALT+X),搜索“\r\n”並替換為“\n”:
  2. 點擊全部替換 (ALT+A)

重建並運行 docker 映像應該可以解決您的問題。

這是因為shell腳本在windows中是格式化的,我們需要改成unix格式。 您可以在任何 Linux 系統上運行 dos2unix 命令。

dos2unix your-file.sh

如果您無法訪問 Linux 系統,您可以使用帶有 dos2unix.exe 的 Git Bash for Windows

dos2unix.exe your-file.sh 

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 

對於VScode用戶,在 IDE的右下角可以找到CRLF/LF ,因此將其切換為LF並再次保存文件。 多田!! 你會好起來的。

在此處輸入圖像描述

我正在構建一個Go應用程序,這些答案中的每一個對我來說都是錯誤的,所以我想分享我的解決方案。 對我來說,我有一個不涉及 Windows 的 Dockerfile(在 Mac 上編碼,盡管在 macOS 11 上的一個和 macOS 12 上的另一個之間共享。但行結尾是相同的)。

對我來說,解決方案最終是我需要將我的應用程序構建為一個靜態鏈接的二進制文件,該二進制文件將在沒有外部依賴項的情況下運行。 我正在為一個 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"]

問題:

問題來自.sh文件。 首先我們必須記住, Windows使用\r\n作為行尾,而Linux 和 Mac使用\n Git 有一個名為 autoclrf 的功能,在 Windows 上通常設置為“true”。 這會在從 Git 存儲庫完成下載后自動將\n轉換為\r\n ,但 Git 不會對此進行任何形式的通知,因此會生成錯誤。 這個過程是好的,至少對於其他文件來說是這樣,但對於 bash 文件卻不是這樣,對於entrypoint.sh文件也是如此。

即時解決方案:

打開您最喜歡的代碼編輯器並更改導致沖突的文件的行尾,在我們的例子中: 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

將此添加到您的 Dockerfile

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

我解決了一個類似的問題

我的配置: -> Docker Desktop WSL 2 后端 - Windows -> 需要 CGO_ENABLED=1,因為我使用 Lib confluent-kafka-go.v1/kafka 編譯了一個 Kafka Producer

我的 docker 鏡像已經構建成功,但是當我使用 docker-compose-up 啟動鏡像時,會出現同樣的問題:

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 .

我的.sh文件末尾多了一行。 我刪除了它並解決了這個問題。

如果嘗試在從頭開始的容器中運行動態鏈接的可執行文件,也會出現此錯誤。 可執行文件將無法鏈接到共享 ( 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" ]

構建圖像。 然后,從圖像運行一個即時容器:

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標志)解決了該問題,該鏈接產生了一個獨立的可執行文件。

我解決了這個問題,在 vscode 中設置了我的設置。

  1. 文件
    1. 喜好
      1. 設置
        1. 文本編輯器
          1. 文件
          2. Eol - 設置為 \n

問候

我發現了一個特殊的邊緣案例,我在alpine容器中使用了tini init ,但是由於我沒有使用靜態鏈接版本,並且Alpine 使用 musl libc 而不是默認安裝的 GNU LibC 庫,因此它與相同的崩潰錯誤信息。

如果我理解這一點並花時間正確閱讀文檔,我會發現Tini Static ,它在更改為后解決了我的問題。

這里有多個正確答案。 我沒有看到它的 VIM 版本,所以在這里。 在 VIM 中打開文件,例如檢查底部狀態行,執行set ff=dos (對於 CRLF)或set ff=unix (對於 LF)。

您可以在 Mac 上使用 BBEdit 來解決此問題,因為 Notepad++ 不可用。

在窗口底部很明顯。 除了字符集選項

git config core.autocrlf false  
git rm --cached -r .   
git reset --hard

https://www.codegrepper.com/code-examples/shell/How+to+change+all+files%27+default+eol+to+LF+in+windows

我在使用以下構建時遇到了類似的問題

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"]

干杯。

當在運行時找不到動態庫時,它會返回這個

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM