请分享您的想法在 2024 年 Clojure 状态调查!

欢迎!有关如何使用本网站的更多信息,请查看 关于 页面。

+1
tools.deps

我遇到了这个错误,花了一些时间才弄清楚。

由于某种原因,下载 eclipse 文件失败。
这非常令人沮丧。
我发现问题出在了 $HOME/.m2/repository 下目录的权限设置不正确。

下载依赖项时无法向本地 Maven 仓库写入任何文件,这导致了我的项目中依赖项解析失败。
错误与 FileNotFoundException 有关 - 而不是“无法写入此目录”。
这更加令人困惑,因为我在该目录中还有一些依赖项(可能来自以前的下载)。

我认为目录权限是在将本地 Maven 仓库挂载到 Docker 容器时发生改变的。

我在 Slack 上报告了这个问题,并按照 Alex Miller 的建议提出了这个问题。
他提到这可能是由 Maven 库引起的问题,超出了 tools.deps 的控制范围。

在我看来,这很奇怪,因为 Maven 库在尝试创建本地文件时不会出错,而当 tools.deps 尝试读取文件时会抛出异常。

复现步骤

rm -rf ~/.m2/repository/org/eclipse 
mkdir -p ~/.m2/repository/org/eclipse/
chown root:root ~/.m2/repository/org/eclipse
clojure -Sdeps '{:deps {info.sunng/ring-jetty9-adapter {:mvn/version "0.22.0"}}}'

异常

clojure -Sdeps '{:deps {info.sunng/ring-jetty9-adapter {:mvn/version "0.22.0"}}}'
警告:加载 S3TransporterFactory 类失败
警告:加载 S3TransporterFactory 类失败
警告:加载 S3TransporterFactory 类失败
警告:加载 S3TransporterFactory 类失败
SLF4J:无法加载类 "org.slf4j.impl.StaticLoggerBinder"。
SLF4J:默认使用无操作(NOP)日志实现
SLF4J:有关详细信息,请参阅 http://www.slf4j.org/codes.html#StaticLoggerBinder
警告:加载 S3TransporterFactory 类失败
警告:加载 S3TransporterFactory 类失败
警告:加载 S3TransporterFactory 类失败
警告:加载 S3TransporterFactory 类失败
构建类路径错误。无法读取 org.eclipse.jetty.websocket:websocket-servlet:jar:11.0.15 的工件描述符
org.eclipse.aether.resolution.ArtifactDescriptorException:无法读取 org.eclipse.jetty.websocket:websocket-servlet:jar:11.0.15 的工件描述符

    at org.apache.maven.repository.internal.DefaultArtifactDescriptorReader.loadPom(Unknown Source)
    at org.apache.maven.repository.internal.DefaultArtifactDescriptorReader.readArtifactDescriptor(Unknown Source)
    at org.eclipse.aether.internal.impl.DefaultRepositorySystem.readArtifactDescriptor(Unknown Source)
    at clojure.tools.deps.extensions.maven$read_descriptor.invokeStatic(maven.clj:115)
    at clojure.tools.deps.extensions.maven$read_descriptor.invoke(maven.clj:106)
    at clojure.tools.deps.extensions.maven$fn__825.invokeStatic(maven.clj:146)
    at clojure.tools.deps.extensions.maven$fn__825.invoke(maven.clj:143)
    at clojure.lang.MultiFn.invoke(MultiFn.java:244)
    at clojure.tools.deps$expand_deps$children_task__463$fn__465$fn__466.invoke(deps.clj:407)
    at clojure.lang.AFn.applyToHelper(AFn.java:152)
    at clojure.lang.AFn.applyTo(AFn.java:144)
    at clojure.core$apply.invokeStatic(core.clj:667)
    at clojure.core$with_bindings_STAR_.invokeStatic(core.clj:1990)
    at clojure.core$with_bindings_STAR_.doInvoke(core.clj:1990)
    at clojure.lang.RestFn.invoke(RestFn.java:425)
    at clojure.lang.AFn.applyToHelper(AFn.java:156)
    at clojure.lang.RestFn.applyTo(RestFn.java:132)
    at clojure.core$apply.invokeStatic(core.clj:671)
    at clojure.core$bound_fn_STAR_$fn__7194.doInvoke(core.clj:2020)
    at clojure.lang.RestFn.invoke(RestFn.java:397)
    at clojure.lang.AFn.call(AFn.java:18)
    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
    at java.base/java.lang.Thread.run(Thread.java:1583)

原因:org.eclipse.aether.resolution.ArtifactResolutionException:无法从 central (https://repo1.maven.org/maven2/) 传输工件 org.eclipse.jetty.websocket:websocket-servlet:pom:11.0.15:/home/ieugen/.m2/repository/org/eclipse/jetty/websocket/websocket-servlet/11.0.15/websocket-servlet-11.0.15.pom.part.lock (没有找到该文件或目录)

    at org.eclipse.aether.internal.impl.DefaultArtifactResolver.resolve(Unknown Source)
    at org.eclipse.aether.internal.impl.DefaultArtifactResolver.resolveArtifacts(Unknown Source)
    at org.eclipse.aether.internal.impl.DefaultArtifactResolver.resolveArtifact(Unknown Source)
    ... 25 more

原因:org.eclipse.aether.transfer.ArtifactTransferException:无法从 central (https://repo1.maven.org/maven2/) 传输工件 org.eclipse.jetty.websocket:websocket-servlet:pom:11.0.15:/home/ieugen/.m2/repository/org/eclipse/jetty/websocket/websocket-servlet/11.0.15/websocket-servlet-11.0.15.pom.part.lock (没有找到该文件或目录)

    at org.eclipse.aether.connector.basic.ArtifactTransportListener.transferFailed(Unknown Source)
    at org.eclipse.aether.connector.basic.BasicRepositoryConnector$TaskRunner.run(Unknown Source)
    at org.eclipse.aether.util.concurrency.RunnableErrorForwarder$1.run(Unknown Source)
    at org.eclipse.aether.connector.basic.BasicRepositoryConnector$DirectExecutor.execute(Unknown Source)
    at org.eclipse.aether.connector.basic.BasicRepositoryConnector.get(Unknown Source)
    at org.eclipse.aether.internal.impl.DefaultArtifactResolver.performDownloads(Unknown Source)
    ... 28 more

原因:java.io.FileNotFoundException:/home/ieugen/.m2/repository/org/eclipse/jetty/websocket/websocket-servlet/11.0.15/websocket-servlet-11.0.15.pom.part.lock (没有找到该文件或目录)

1 个回答

0

当你使用卷将 ~/.m2 及其类似物品挂载到 Docker 中以避免再次下载工件时,这是一个常见问题。如果在 Docker 内部仍然下载了某些内容,该文件可能会以 root 权限写入用户的主目录。我多年来也遇到过这种现象至少几次。上一次是上周。 :slightly_smiling_face: 我也不是 Docker 高手,并且我可能在使用它时犯了一些错误。当这种情况发生时,不明显发生了什么,并且如果记得曾经遇到过,那么你就很幸运了。

我们过去也遇到过这个问题。我们多年来一直在做的是有一个名为 "run-as-user.sh" 的脚本,其内容如下

```
#!/usr/bin/env bash

set -eu

NEW_UID=$(stat -c '%u' /app)
NEW_GID=$(stat -c '%g' /app)

groupmod -g "$NEW_GID" -o hop >/dev/null 2>&1
usermod -u "$NEW_UID" -o hop >/dev/null 2>&1

exec chpst -u hop:hop -U hop:hop env HOME="/home/hop" "$@"
```

我们将它用作容器的入口点。然后在容器中 Dockerfile 我们也添加以下代码行(在此基础上添加容器所需的代码),以及在 Docker 镜像使用的发行版中安装 `runit` 软件包所需的命令(该包提供了 `chpst` 命令)

```
RUN useradd --home-dir /home/hop --create-home --shell /bin/bash --user-group hop
COPY run-as-user.sh /usr/local/bin
WORKDIR /app
ENTRYPOINT ["run-as-user.sh"]
```

然后,在运行容器时,我们使用容器内的卷挂载所需的任何目录(~/.m2、Clojure 应用程序目录等)。我们在容器内部将 Clojure 应用程序目录挂载于 `/app`(`run-as-user.sh` 脚本将寻找的位置)。然后 `run-as-user.sh` 脚本负责将容器内部使用的帐户的 UID 和 GID 改变为拥有 `/app` 目录的用户(外部用户)。

希望这能有所帮助。
...