docker - 在 docker 上运行的 Tomcat 9 - 找不到/usr/local/to

我在 docker 上运行 tomcat (tomcat:9-jre11),启动它时,它会记录以下内容,然后崩溃:

Cannot find /usr/local/tomcat/bin/setclasspath.sh
This file is needed to run this program

我的第一个问题实际上是进入容器,因为我不能在崩溃的容器上使用 docker exec,但我通过在 Rancher 中将入口点设置为/bin/bash 来管理它。

现在setclasspath.sh非常多在/usr/local/tomcat/bin/容器里面。它以前具有所有读取和执行权限,我将其设置为 777 只是为了确定,仍然有同样的问题。更改所有者也是如此(tomcat 似乎正在使用 root,即使我在另一个用户上手动启动 catalina.sh,更改了文件所有者)。我使用了笨手笨脚的方法,将整个该死的文件夹设置为 777,但还是一样:

drwxrwxrwx 1 root root   4096 Jun 29 14:53 .
drwxr-xr-x 1 root root   4096 Jun 29 14:31 ..
-rwxrwxrwx 1 root root  34699 Jun  2 21:08 bootstrap.jar
-rwxrwxrwx 1 root root  25523 Jun 29 14:00 catalina.sh
-rwxrwxrwx 1 root root   1664 Jun  2 21:08 catalina-tasks.xml
-rwxrwxrwx 1 root root   2007 Jun 28 03:01 ciphers.sh
-rwxrwxrwx 1 root root  25410 Jun  2 21:08 commons-daemon.jar
-rwxrwxrwx 1 root root 211777 Jun  2 21:08 commons-daemon-native.tar.gz
-rwxrwxrwx 1 root root   1932 Jun 28 03:01 configtest.sh
-rwxrwxrwx 1 root root   9110 Jun 28 03:01 daemon.sh
-rwxrwxrwx 1 root root   1975 Jun 28 03:01 digest.sh
-rwxrwxrwx 1 root root   3392 Jun 28 03:01 makebase.sh
-rwxrwxrwx 1 root root   3718 Jun 28 03:01 setclasspath.sh
-rwxrwxrwx 1 root root   1912 Jun 28 03:01 shutdown.sh
-rwxrwxrwx 1 root root   1914 Jun 28 03:01 startup.sh
-rwxrwxrwx 1 root root  46898 Jun  2 21:08 tomcat-juli.jar
-rwxrwxrwx 1 root root   5550 Jun 28 03:01 tool-wrapper.sh
-rwxrwxrwx 1 root root   1918 Jun 28 03:01 version.sh

我查看了 catalina.sh 脚本,导致问题的部分如下:

  if [ -r "$CATALINA_HOME"/bin/setclasspath.sh ]; then
    . "$CATALINA_HOME"/bin/setclasspath.sh
  else
    echo "Cannot find $CATALINA_HOME/bin/setclasspath.sh"
    echo "This file is needed to run this program"
  fi

条件中的 -r 是无聊的。我读过它,看看文件是否存在并且可读,它满足所有条件。我添加了带有 -a-f 条件的 elif 并且 do 返回 true,但尽管它们被设置为 777 或没有,但权利似乎是问题所在。我还在脚本中添加了一个 whoami,它是 root 用户,所以不是所有权问题。

startup.sh 脚本有一个类似的问题,有一个 -x 条件,它找不到 catalina.sh ...

最佳答案

我们今天偶然发现了这个问题。

我们有一台从 16.04 升级而来的 Ubuntu 18.04 服务器。 docker 包的版本如下:

docker-ce/now 5:19.03.1~3-0~ubuntu-xenial amd64
docker-ce-cli/now 5:19.03.1~3-0~ubuntu-xenial amd64
docker-compose/bionic,bionic,now 1.17.1-2 all

内核是:4.15.0-154-generic x86_64

在这台机器上,运行当前版本的 tomcat:9-jre11 [0] 会导致与您的问题中描述的问题相同的问题。

为了缩小范围,我们像这样开始了 bash:

docker run -it --rm --entrypoint=/bin/bash tomcat:9-jre11

现在出现了您观察到的奇怪行为,这与 tomcat 完全无关:

root@f338debf92f6:/usr/local/tomcat# [[ -r /bin/bash ]]
root@f338debf92f6:/usr/local/tomcat# echo $?
1

在我们测试的任何其他机器上,结果都符合预期,例如:

root@0083a80a9ec2:/usr/local/tomcat# [[ -r /bin/bash ]]
root@0083a80a9ec2:/usr/local/tomcat# echo $?
0

不幸的是,我无法使用新安装的 Ubuntu 18.04 重现该行为。我什至降级了内核版本并从 xenial 存储库安装了 docker。

尝试用谷歌搜索我发现的解决方案: https://github.com/alpinelinux/docker-alpine/issues/156#issuecomment-912645029

所以我尝试了 strace,这里的问题是可见的:

在我们的 Ubuntu 18.04 上:

...
read(255, "#!/bin/bash\n[[ -r /bin/bash ]]\n", 31) = 31
faccessat2(AT_FDCWD, "/bin/bash", R_OK, AT_EACCESS) = -1 EPERM (Operation not permitted)
read(255, "", 31)                       = 0
...

在我测试过的任何其他机器上:

...
read(255, "#!/bin/bash\n[[ -r /bin/bash ]]\n", 31) = 31
faccessat2(AT_FDCWD, "/bin/bash", R_OK, AT_EACCESS) = -1 ENOSYS (Function not implemented)
faccessat(AT_FDCWD, "/bin/bash", R_OK)  = 0
read(255, "", 31) 
...

研究 faccessat2 系统调用表明它不应返回 EPERM [1]。我无法完全确定引入此行为的位置 - 在 glibc 和 seccomp 之间的某个地方,但这一切都归结为运行时对于这个新的系统调用来说太旧了。

以下是我们提出的解决方案:

  1. 升级你的机器——虽然这可能不可行:)
  2. 使用基于旧版 Debian/Ubuntu 的 tomcat 镜像。为了我们 tomcat:9.0.64-jre11-openjdk-slim-bullseye 工作正常。
  3. 使用--privileged 开关运行容器。这规避了系统调用权限问题,但通常不是一个好主意

引用

  1. 摘要 sha256:f0c2eb420166a7d609c0031699e0778e11256f280cc2bfb5bfd61cde7ae45c61
  2. https://man7.org/linux/man-pages/man2/faccessat.2.html

关于docker - 在 docker 上运行的 Tomcat 9 - 找不到/usr/local/tomcat/bin/setclasspath.sh,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72801984/

相关文章:

perl - 安装 perl 模块时不能使用数组作为引用

python - 由于 OSError : [Errno 2] No such file or di

c++ - 从样板代码到模板实现

javascript - 如何声明 useState() 初始值为 null,然后再给它一个对象值?

python - 删除 pandas 列中的前导零,但仅适用于数字

python - 我怎么能实现 “HH:MM:SS” 格式

r - 在R中按组计算每两行值的比例

javascript - 通过 :even and :odd 向 querySelectorAll

typescript - 使用类转换器 : Nest js 序列化嵌套对象

r - 如果数据集的某些列为空,我想在 R 中删除那些列