Tomcat

来自 ArchWiki

Tomcat 是由 Apache 软件基金会开发的开源 Java Servlet 容器

注意: Tomcat 目前存在四个稳定分支:78910。这些版本均不弃用之前的版本。相反,每个分支都是对 “Servlet” 和 “JSP” Java 标准的实现。最新版本在 Arch Linux 中获得官方支持:tomcat8tomcat9tomcat10。根据您的 Web 应用程序需求检查您需要的版本。

安装

安装 tomcat8tomcat9tomcat10 之一。

如果将 Tomcat 部署到生产环境,请考虑安装 tomcat-native。Tomcat 的原生库配置服务器以使用 Apache Portable Runtime (APR) 库的网络连接(套接字)和 RNG 实现。它使用原生 32 位或 64 位代码来提高性能,有时在速度至关重要的生产环境中使用。默认 Tomcat 安装无需配置。更多信息请参见 官方 Tomcat 文档

使用 tomcat-native 将消除 catalina.err 中的以下警告

INFO: The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path [...]

文件系统层级

n 替换为您安装的版本(8、9、10)。

路径名 用途
/etc/tomcatn 配置文件。其中包括:tomcat-users.xml(定义允许使用管理工具的用户及其角色)、server.xml(Tomcat 主配置文件)、catalina.policy(安全策略配置文件)
/usr/share/tomcatn 包含脚本和指向其他目录的链接的 Tomcat 主文件夹
/usr/share/java/tomcatn Tomcat Java 库 (jars)
/var/log/tomcatn systemd 处理的日志文件(参见 #日志记录
/var/lib/tomcatn/webapps Tomcat 在此处部署您的 Web 应用程序
/var/tmp/tomcatn Tomcat 在此处存储您的 webapps 数据

初始配置

为了能够使用 manager webapp 和 admin webapp,您需要编辑 /etc/tomcatn/tomcat-users.xml

取消注释 “role and user” XML 声明并对其进行修改,以根据您的需要启用角色 tomcatadmin-guiadmin-script 和/或 manager-guimanager-scriptmanager-jmxmanager-status(参见 Configuring Manager Application Access)。简而言之,tomcat 是用于运行的强制角色,manager-* 是能够管理 Web 应用程序的角色,而 admin-* 是 Tomcat 服务器上的完全权限管理员角色。

这是一个基本的配置文件,声明了其中一些角色以及用户名和密码(请务必将以下 [CHANGE_ME] 密码更改为安全的密码)

/etc/tomcatn/tomcat-users.xml
<?xml version='1.0' encoding='utf-8'?>
<tomcat-users>
  <role rolename="tomcat"/>
  <role rolename="manager-gui"/>
  <role rolename="manager-script"/>
  <role rolename="manager-jmx"/>
  <role rolename="manager-status"/>
  <role rolename="admin-gui"/>
  <role rolename="admin-script"/>
  <user username="tomcat" password="[CHANGE_ME]" roles="tomcat"/>
  <user username="manager" password="[CHANGE_ME]" roles="manager-gui,manager-script,manager-jmx,manager-status"/>
  <user username="admin" password="[CHANGE_ME]" roles="admin-gui"/>
</tomcat-users>

请记住,每次修改此文件后都必须重启 Tomcat。

这篇 博客文章 对这些角色进行了很好的描述。

为了对配置文件具有读取权限并能与某些 IDE 良好协作,您必须将您的用户添加到 tomcatn 用户组

启动/停止 Tomcat

启动 tomcatn.service

Tomcat 启动后,您可以访问此页面查看结果:https://127.0.0.1:8080。如果显示友好的 Tomcat 本地主页,则表示您的 Servlet 容器已启动并正在运行,可以托管您的 Web 应用程序。如果启动脚本失败或您只能在浏览器中看到 Java 错误,请使用 systemd 的 journalctl 查看启动日志。Google 上有很多关于 Tomcat 日志中经常出现的问题的解答。

本文或本节已过时。

原因: /etc/conf.d/tomcatn 至少在 tomcat{9,10} 上不存在。检查新的 CATALINA_OPTS 存在于何处。(在 Talk:Tomcat 中讨论)
注意: 为了提高安全性,Arch Linux 的 Tomcat 软件包使用来自 Apache common-daemonsjsvc 二进制文件。Tomcat 的 systemd 服务以 root 权限运行此 Apache 二进制文件,该文件本身以非特权用户(Arch Linux 中的 tomcatn:tomcatn)启动 Tomcat。这可以防止可能在不良 Web 应用程序中执行的恶意代码造成过大的损害。这也允许在需要时使用 1024 以下的端口。有关可用选项,请参阅 man jsvc,并通过在 /etc/conf.d/tomcatn 中声明的 CATALINA_OPTS 环境变量传递它们。

备选的 “手动” 方式

Tomcat 也可以使用上游脚本直接控制

/usr/share/tomcat/bin/{startup.sh,shutdown.sh,..}

这对于调试应用程序甚至调试 Tomcat 可能很有用,但不要首次使用它来启动 Tomcat,因为这样做可能会错误地设置某些权限并阻止 Web 应用程序工作。为了能够使用这些脚本,可能需要进行一些进一步的配置。请注意,使用这些脚本会阻止上述 jsvc 安全优势。

部署和处理 Web 应用程序

Tomcat 捆绑了 5 个已部署的 Web 应用程序(如果需要,请将 localhost 更改为服务器的 FQDN)

图形界面方式

可能最简单的方法是使用 manager webapp https://127.0.0.1:8080/manager/html。使用您在 tomcat-users.xml 中定义为 manager 的用户名/密码。登录后,您可以看到五个已部署的 Web 应用程序。通过 “Deploy” 区域添加您的应用程序,然后使用 “Applications” 区域停止/启动/取消部署它。

命令行界面方式

也可以只将应用程序的 WAR 文件复制到目录 /usr/share/tomcatn/webapps。为此,请确保 autoDeploy 选项仍设置为正确的 host,如此处所示

/etc/tomcatn/server.xml
...
<Host name="localhost"  appBase="webapps"
      unpackWARs="true" autoDeploy="true">
...

否则只需重启 tomcat 服务。

在 webapps 文件夹之外托管文件

如果您想将项目保留在 webapps 文件夹之外,可以通过创建 Context 来实现。转到 /etc/tomcatn/Catalina/localhost/ 并创建您的 context。context 是一个简单的 xml 文件,用于指定 tomcat 应在何处查找项目。该文件的基本格式是

/etc/tomcatn/Catalina/localhost/whatShouldFollowLocalhost.xml
<Context path="/whatSholdFollwLocalhost" docBase="/where/your/project/is/" reloadable="true"/>

以下是一个工作示例。这假设项目托管在用户的 /home 文件夹中的某个位置。

/etc/tomcatn/Catalina/localhost/myProject.xml
<Context path="/myProject" docBase="/home/archie/code/jsp/myProject" reloadable="true"/>

现在可以将文件托管在 /home/archie/code/jsp/myProject/ 中。要在 Web 浏览器中查看项目,请转到 https://127.0.0.1:8080/myProject。如果 tomcat 无法加载文件,则可能是权限问题。使 /home/archie/code/jsp/myProject 可执行 应该可以解决问题。

日志记录

Tomcat 与官方 Arch Linux 软件包一起使用时,使用 systemd 的 journalctl 用于启动日志。这意味着 /var/log/tomcatn/catalina.err/var/log/tomcatn/catalina.out 文件使用。在 /etc/tomcatn/server.xml 中定义为 Valve 的其他日志(例如访问日志和业务日志)仍然默认最终位于 /var/log/tomcatn/ 中。

要恢复上游风格的日志记录,请使用 drop-in file 来更改 SYSLOG 以获取日志文件的绝对路径。

进一步设置

可以通过虚拟主机管理器 Web 应用程序进行基本配置:https://127.0.0.1:8080/host-manager/html。提供您在 tomcat-users.xml 中设置的用户名/密码。其他选项在 /etc/tomcatn 中的配置文件中进行调整,其中最重要的是 server.xml。使用这些文件超出了本 101 Wiki 页面的范围。有关更多详细信息,请查看 最新的官方 Tomcat 文档

从旧版本 Tomcat 迁移

正如引言中所述,Tomcat 10 不会弃用 Tomcat 9,Tomcat 9 不会弃用 Tomcat 8,依此类推。它们都是 Servlet/JSP 标准的实现。因此,您必须首先确定根据您的应用程序使用的 Servlet/JSP 版本,您需要 哪个版本 的 Tomcat。如果您需要迁移,官方网站提供了 关于如何处理此类过程的说明

将 Tomcat 与不同的 JRE/JDK 结合使用

除了安装所需的 JRE/JDK 之外,唯一的要求是使用 drop-in file 设置 TOMCAT_JAVA_HOME 变量

/etc/systemd/system/tomcatn.service.d/start.conf
[Service]
Environment=TOMCAT_JAVA_HOME=/usr/lib/jvm/java-8-openjdk

安全配置

本文或本节已过时。

原因: 引用的指南均在讨论早已 EOL 的 tomcat 版本。(在 Talk:Tomcat 中讨论)

本页面提供了使您的第一个 Web 应用程序在 Tomcat 上运行的最基本信息。它并非旨在成为管理 Tomcat 的权威指南(这本身就是一项工作)。官方 Tomcat 网站将提供所有必要的官方资料。也可以参考这篇 O'Reilly 页面 和这篇 unidata 页面。不过,这里有一些安全提示可帮助您入门

  • 保持 Tomcat 安装为最新版本,以获取针对安全问题的最新修复程序
  • 删除不需要的默认应用程序,例如 examplesdocs、默认主页 ROOTmanager webapp 中的 “_”)。这可以防止潜在的安全漏洞被利用。为此,请使用 manager

为了更高的安全性,您甚至可以删除 host-manager 和 manager Web 应用程序。请记住,后者对于部署 Web 应用程序很有用。

  • 禁用 WAR 自动部署选项。这将防止获得服务器受限访问权限的人员将 WAR 复制到 /usr/share/java/webapps 目录以使其运行。编辑 server.xml 并将 autoDeploy 设置为 false
/etc/tomcatn/server.xml
...
<Host name="localhost"  appBase="webapps"
      unpackWARs="true" autoDeploy="false">
...
  • 匿名化 Tomcat 的默认错误页面,以防止潜在的攻击者检索 Tomcat 的版本。要查看 Tomcat 默认显示的内容,只需访问一个不存在的页面,例如 https://127.0.0.1:8080/I_dont_exist。您将获得一个 404 错误页面,底部显示 Tomcat 的版本。

要匿名化此页面,请编辑/打开以下 JAR(像 vim 这样的编辑器可以直接编辑 zip 文件)

/usr/share/tomcatn/lib/catalina.jar

并编辑以下文件

org/apache/catalina/util/ServerInfo.properties
...
server.info=
server.number=
server.built=
...
  • 禁用 server.xml 中未使用的 connectors
  • 保持对 /etc/tomcatn/server.xml 的受限访问。只有 tomcat 用户和/或 root 应该能够读取和写入此文件。
  • 保留 jsvc 的使用。除非有特殊原因,否则不要使用上游启动脚本,如上面的安全说明中所述。
  • tomcat-users.xml 中的每个用户使用强而不同的密码,为真正需要的用户分配角色,甚至禁用您不使用/不需要的用户名/角色。

甚至可以使用以下上游脚本加密 tomcat-users.xml 密码

/usr/share/tomcatn/bin/digest.sh -a sha-512 -h org.apache.catalina.realm.MessageDigestCredentialHandler NEW_PASSWORD

这将输出类似以下内容

NEW_PASSWORD:58adca01951a24aebce28f4d7a759aa30ef2f38bc54e41e51071c257ed4a1a9b$1$b4ccaafa86c26dea13825d35da73f9d11ce63f5deae15a13aafb835bdaf710d38922843c8065f35f245a20b1d2df9b20ddf2c005990512c598a62514f78cf3d2

将哈希部分粘贴到 tomcat-users.xml 中的明文密码的位置,并将以下内容添加到 server.xml

/etc/tomcatn/server.xml
<Realm className="org.apache.catalina.realm.LockOutRealm">
        <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
               resourceName="UserDatabase">
               <CredentialHandler className="org.apache.catalina.realm.MessageDigestCredentialHandler"
                                  algorithm="sha-512"/>
        </Realm>
      </Realm>
  ...
/>

请注意,这可能无关紧要,因为只有 root 和/或 tomcat 应该具有对该文件的读/写访问权限。如果入侵者设法获得 root 访问权限,他们无论如何都不需要这些密码来破坏您的应用程序/数据。请务必保持对该文件的受限读写访问权限,并始终了解您正在部署的内容!

故障排除

Tomcat 服务已启动,但页面未加载

首先,检查 /etc/tomcatn/tomcat-users.xml 是否有任何语法错误。如果一切正常且 tomcatn 正在正确运行,请以 root 身份运行 journalctl -r 以检查日志中是否有任何异常抛出(参见 #日志记录)。如果您看到类似 java.lang.Exception: Socket bind failed: [98] Address already in use 的内容,这是由于某些其他服务正在侦听同一端口。例如,Apache HTTP Server 和 Tomcat 可能正在侦听同一端口(例如,如果您的 Apache 在端口 8080 上运行,而 Nginx 在端口 80 上将其用作代理)。如果是这种情况,请编辑 /etc/tomcatn/server.xml 文件,并将 Connector 端口更改为 <Service name="Catalina"> 下的其他端口。

/etc/tomcatn/server.xml
<?xml version='1.0' encoding='utf-8'?>
...
...
<!-- Change port from 8080 to something else, like 8090 -->
<Service name="Catalina">
    <Connector executor="tomcatThreadPool"
                 port="8090" protocol="HTTP/1.1"
                 connectionTimeout="20000"
                 redirectPort="8443" />
...
...
</Service>

最后,重启 tomcatnhttpd 服务。

如果您没有解决方案并且您在 VM 中,则删除 /dev/random 并重新创建它可能会有所帮助(参见 Solution: FUTEX_WAIT hangs Java on Linux / Ubuntu in vmware or virtual box

# rm /dev/random 
# mknod -m 644 /dev/random c 1 9

或者,即使在重启后也要保留它的另一个解决方案是修改 /usr/lib/jvm/java-8-openjdk/jre/lib/security/java.security(例如)以指向 /dev/urandom/