zl程序教程

您现在的位置是:首页 >  Java

当前栏目

docker运行tomcat报错Cannot find /usr/local/tomcat/bin/setclasspath.sh

2023-04-18 16:30:39 时间

docker运行tomcat报错

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

经过尝试,使用用dockerfile打包加入命令

RUN unset CATALINA_HOME

尝试后无效

搜索后,同样的问题有一篇文章:https://www.5axxw.com/questions/content/fypkh1

具体排查过程如下

提示是找不到setclasspath.sh,由于这个tomcat反复重启,、

所以用命令拷贝一份bin目录到当前文件夹

docker cp 容器id:/usr/local/tomcat/bin ./


结果发现setclasspath.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 命令表示测试这个文件是否是只读,类似的-x 测试这个文件是否可执行

在有问题的系统中,容器里-r命令调用不正常。

尝试启动一个临时的tomcat8验证,

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


备注:执行docker run命令带--rm命令选项,等价于在容器退出后,执行docker rm -v。
执行命令

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

$?  命令 表示上个命令的退出状态,或函数的返回值。
对退出状态来说 0表示没有错误,其他任何值表明有错误。一般情况下,大部分命令执行成功会返回 0,失败返回 1,也有一些命令返回其他值,表示不同类型的错误。

如何解决?
这与faccessat2系统调用有关,由于 runc 中的 bug,如果您的内核不支持 faccessat2,它将失败。有文章说升级内核到5.8以上可能好使,我试过了不好使,因为出现问题的内核时5.10的。
方法1:更新 runc >= 1.0.0-rc93 

方法2:--privileged开关运行容器

方法1具体实现:

查看原有runc版本

runc -v

下载1.0.0-rc95版本的runc.amd64

下载地址:Releases · opencontainers/runc · GitHub

改名 加执行权限

mv runc.amd64 runc && chmod +x runc

查看并备份原有runc

whereis runc

有的系统在/usr/bin/目录下 有的系统在 /usr/local/bin/目录下,以下命令以/usr/local/bin/为准/usr/bin/的自行更改目录

mv /usr/local/bin/runc /usr/local/bin/runcbak

覆盖原有runc

cp runc /usr/local/bin/runc

查看runc新版本

runc -v

重启docker

systemctl restart docker

方法2具体实现

docker run执行

docker run --privileged=true -p 8080:8080 tomcat:8

docker-compose.yml添加

version: '2'
services:
    tomcat:
     container_name: tomcat
     image: tomcat:8
     ports:
         - '8080:8080'
     environment:
         - TZ=Asia/Shanghai
     privileged: true
     restart: always