CentOS 8 安装 Apache JSPWiki 2.12.5 指南

CentOS 8 从 0 到 1 安装 Apache JSPWiki 2.12.5:切换 vault 源、安装 JDK 17、官方 Tomcat 9、firewalld 放行、安装向导、systemd 自启、建页/搜索验证与卸载 FAQ。

Apache JSPWikiApache JSPWiki2026/10/13

CentOS 8 安装 Apache JSPWiki 2.12.5 指南

目标:在 CentOS 8 服务器上从零安装并运行 Apache JSPWiki 2.12.5(官方 WAR 包 + 官方 Tomcat 9 二进制包),完成初始化安装向导、firewalld 放行、systemd 开机自启与功能验证。已在 CentOS 8.5.2111(JDK 17.0.1 + Tomcat 9.0.123 + JSPWiki 2.12.5)环境实测通过。

一、环境信息

  • 操作系统:CentOS Linux 8.5.2111(x86_64)
  • JDK:OpenJDK 17.0.1(java-17-openjdk 1:17.0.1.0.12-2.el8_5,dnf 安装)
  • Servlet 服务器:Apache Tomcat 9.0.123(官方二进制包 apache-tomcat-9.0.123.tar.gz,解压安装)
  • JSPWiki:2.12.5(官方 WAR 包,36752001 字节)
  • 服务端口:Tomcat HTTP 连接器 8080
  • 部署上下文:http://<服务器IP>:8080/JSPWiki/
  • 关键路径:
    • Tomcat 程序目录:/opt/tomcat/
    • JVM 堆参数:/opt/tomcat/bin/setenv.sh
    • Web 应用目录:/opt/tomcat/webapps/
    • Tomcat 日志:/opt/tomcat/logs/catalina.out
    • JSPWiki 页面存储:/var/lib/jspwiki/pages/
    • JSPWiki 工作目录(索引/缓存):/var/lib/jspwiki/work/
    • systemd 单元:/etc/systemd/system/tomcat.service
  • 演示管理账号:admin / q1w2e3r4

二、前置条件

  1. 一台 CentOS 8 服务器,拥有 root 权限(本文以 root 执行)。
  2. 服务器可访问外网(下载 dnf 包与官方 WAR;离线环境可将 WAR 提前下载后上传)。
  3. 内存 ≥ 2GB(本文将 JVM 堆限制在 256–512MB,1GB 内存亦可运行)。
  4. 端口 8080 未被占用(如需调整见"配置说明")。

三、版本选型说明

Apache JSPWiki 官方当前维护两条版本线(发布日期均为 2026-08-22):

版本线最新版本Servlet 命名空间配套服务器说明
2.12.x2.12.5javax.servletTomcat 9.x传统稳定线,生态兼容性最好,本文选择
3.0.x3.0.0jakarta.servletTomcat 10.x+新一代版本,包名迁移至 jakarta,配套服务器不同

💡 JSPWiki 2.12.x 使用 javax.servlet 命名空间,必须部署在 Tomcat 9(或更早的 javax 系服务器)上;放在 Tomcat 10+ 会因命名空间不匹配而无法运行。本文按官方 2.12.5 发行包 + Tomcat 9.0.123 官方二进制包组合实测。

获取最新稳定版本号的方式(以官方下载目录实际列表为准):

curl -fsSL https://dlcdn.apache.org/jspwiki/ | grep -oE 'href="[0-9.]+/"' | sort -u

实测输出(撰写本文时):

href="2.12.5/"
href="3.0.0/"

另一个 CentOS 8 特有前提:CentOS 8 已于 2021-12-31 停止维护(EOL),官方镜像源 mirror.centos.org 已下线,安装软件包前必须把 dnf 源切换到 vault 归档源(见 4.1)。

四、部署方案 A:dnf 安装 JDK 17 + 官方 Tomcat 9 二进制包 + 官方 WAR 部署(推荐)

4.1 切换 dnf 软件源到 vault 归档源

CentOS 8 停止维护后,系统自带的 CentOS-Linux-*.repo 全部指向已下线的 mirror.centos.org,任何 dnf install 都会报 Failed to download metadata。切换到阿里云的 centos-vault 归档镜像(保留原始配置便于回退):

mkdir -p /etc/yum.repos.d/backup
mv /etc/yum.repos.d/CentOS-Linux-*.repo /etc/yum.repos.d/backup/

写入新的源配置(8.5.2111 是 CentOS 8 的最终版本号):

cat > /etc/yum.repos.d/CentOS-Base.repo <<'EOF'
[baseos]
name=CentOS Linux 8.5.2111 - BaseOS
baseurl=https://mirrors.aliyun.com/centos-vault/8.5.2111/BaseOS/x86_64/os/
gpgcheck=1
enabled=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial

[appstream]
name=CentOS Linux 8.5.2111 - AppStream
baseurl=https://mirrors.aliyun.com/centos-vault/8.5.2111/AppStream/x86_64/os/
gpgcheck=1
enabled=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial

[extras]
name=CentOS Linux 8.5.2111 - Extras
baseurl=https://mirrors.aliyun.com/centos-vault/8.5.2111/extras/x86_64/os/
gpgcheck=1
enabled=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
EOF
dnf repolist

实测输出:

repo id                     repo name
appstream                   CentOS Linux 8.5.2111 - AppStream
baseos                      CentOS Linux 8.5.2111 - BaseOS
extras                      CentOS Linux 8.5.2111 - Extras

⚠️ mv CentOS-Linux-*.repo 的通配符一次移动多个文件,属文件整理而非批量启停命令,可用。若服务器在内网无法访问 mirrors.aliyun.com,把 baseurl 换成任意可用的 centos-vault 镜像地址即可,其余不变。

4.2 安装 OpenJDK 17 与基础工具

dnf install -y wget java-17-openjdk java-17-openjdk-devel

安装完成后确认版本:

java -version

实测输出:

openjdk version "17.0.1" 2021-10-19 LTS
OpenJDK Runtime Environment 21.9 (build 17.0.1+12-LTS)
OpenJDK 64-Bit Server VM 21.9 (build 17.0.1+12-LTS, mixed mode, sharing)
dnf list installed java-17-openjdk wget

实测输出:

Installed Packages
java-17-openjdk.x86_64             1:17.0.1.0.12-2.el8_5              @appstream
wget.x86_64                        1.19.5-10.el8                      @appstream

💡 java-17-openjdk-devel 额外提供 jps 等 JVM 诊断工具(位于 /usr/lib/jvm/java-17/bin/),本文用它验证 JVM 堆参数(见 4.13)。

4.3 安装 Tomcat 9(官方二进制包)

CentOS 8 的 AppStream 仓库中没有 Tomcat 包(RHEL 8 有、CentOS 8 上游仓库未收录),实测确认:

dnf search tomcat

实测输出:

Last metadata expiration check: 1:19:53 ago on Tue Oct 13 13:15:58 2026.
No matches found.

因此本文采用 Apache 官方二进制包安装。下载 Tomcat 9.0.123(官方 tomcat-9 下载目录当前最新版本)并校验:

cd /tmp
wget https://dlcdn.apache.org/tomcat/tomcat-9/v9.0.123/bin/apache-tomcat-9.0.123.tar.gz
wget https://dlcdn.apache.org/tomcat/tomcat-9/v9.0.123/bin/apache-tomcat-9.0.123.tar.gz.sha512
sha512sum apache-tomcat-9.0.123.tar.gz

实测输出:

64b1130e719399c0a409e6996081433b16af8d9c89266c7aaa9849af70a1815feca91e13896f5ccc41451dc5759716d1c84882682de955822c30509de102f290 *apache-tomcat-9.0.123.tar.gz

与 .sha512 文件内容一致即校验通过。解压到 /opt 并重命名为 /opt/tomcat(便于升级时整体替换):

tar xzf apache-tomcat-9.0.123.tar.gz -C /opt
mv /opt/apache-tomcat-9.0.123 /opt/tomcat

创建系统用户 tomcat 作为运行身份(不登录、家目录指向程序目录):

useradd -r -d /opt/tomcat -s /sbin/nologin tomcat
chown -R tomcat:tomcat /opt/tomcat
getent passwd tomcat

实测输出:

tomcat:x:998:996::/opt/tomcat:/sbin/nologin

确认 Tomcat 版本:

/opt/tomcat/bin/version.sh | grep -E "Server version|JVM Version"

实测输出:

NOTE: Picked up JDK_JAVA_OPTIONS:  --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.lang.invoke=ALL-UNNAMED --add-opens=java.base/java.lang.reflect=ALL-UNNAMED --add-opens=java.base/java.io=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.base/java.util.concurrent=ALL-UNNAMED --add-opens=java.rmi/sun.rmi.transport=ALL-UNNAMED
Server version: Apache Tomcat/9.0.123
JVM Version:    17.0.1+12-LTS

💡 首行 NOTE: Picked up JDK_JAVA_OPTIONS 是 CentOS 的 java-17-openjdk 包通过 systemd 环境生成器自动注入的模块开放参数,属正常现象。useradd -d /opt/tomcat 把 tomcat 用户家目录指向已存在的程序目录,JSPWiki 引擎首次初始化会在家目录下自动创建默认页面目录 jspwiki-files,目录可写则不会出现默认目录创建失败的问题(见 FAQ 问题 1)。

4.4 配置 JVM 堆内存(256–512MB)

创建 /opt/tomcat/bin/setenv.sh(Tomcat 启动脚本会自动加载该文件),限制堆初始 256MB、上限 512MB:

cat > /opt/tomcat/bin/setenv.sh <<'EOF'
#!/bin/sh
JAVA_OPTS="-Djava.awt.headless=true -Xms256m -Xmx512m"
EOF
chmod +x /opt/tomcat/bin/setenv.sh
cat /opt/tomcat/bin/setenv.sh

实测输出:

#!/bin/sh
JAVA_OPTS="-Djava.awt.headless=true -Xms256m -Xmx512m"

💡 setenv.sh 是官方 tar.gz 版 Tomcat 官方推荐的 JVM 参数入口:catalina.sh 启动时若检测到该文件存在就自动加载,无需改动任何自带脚本。修改后重启 tomcat 服务生效,验证方法见 4.13。

4.5 创建 JSPWiki 数据目录

创建页面存储与工作目录,并赋予 tomcat 用户属主:

mkdir -p /var/lib/jspwiki/pages /var/lib/jspwiki/work
chown -R tomcat:tomcat /var/lib/jspwiki
ls -ld /var/lib/jspwiki/pages /var/lib/jspwiki/work

实测输出:

drwxr-xr-x 2 tomcat tomcat 4096 Oct 13 14:39 /var/lib/jspwiki/pages
drwxr-xr-x 2 tomcat tomcat 4096 Oct 13 14:39 /var/lib/jspwiki/work

4.6 下载 JSPWiki 2.12.5 WAR 包并校验

cd /tmp
wget https://dlcdn.apache.org/jspwiki/2.12.5/binaries/webapp/JSPWiki.war
wget https://dlcdn.apache.org/jspwiki/2.12.5/binaries/webapp/JSPWiki.war.sha512
sha512sum JSPWiki.war

实测输出:

b9436587cca6a29c1e2fb56496d304f977e22c51f1e391bf83724b7ff106e149f55573cfba93fe2e03773f052d206f85ebf6e0cac7fabccce2ed29de13548d4f  JSPWiki.war

与官方 .sha512 文件中的哈希值一致即校验通过。确认文件大小:

ls -l /tmp/JSPWiki.war

实测输出:

-rw-r--r-- 1 root root 36752001 Aug 22 16:14 /tmp/JSPWiki.war

💡 两个项目的 .sha512 文件格式不同:JSPWiki 的是裸哈希值(无文件名),Tomcat 的是 哈希 *文件名(带星号二进制标记),比对时以哈希部分为准。

4.7 部署 WAR 包

cp /tmp/JSPWiki.war /opt/tomcat/webapps/JSPWiki.war
chown tomcat:tomcat /opt/tomcat/webapps/JSPWiki.war
ls -l /opt/tomcat/webapps/

实测输出:

total 35912
-rw-r--r--  1 tomcat tomcat 36752001 Oct 13 14:39 JSPWiki.war
drwxr-x---  3 tomcat tomcat     4096 Oct 13 14:39 ROOT
drwxr-x--- 16 tomcat tomcat     4096 Oct 13 14:39 docs
drwxr-x---  7 tomcat tomcat     4096 Oct 13 14:39 examples
drwxr-x---  6 tomcat tomcat     4096 Oct 13 14:39 host-manager
drwxr-x---  6 tomcat tomcat     4096 Oct 13 14:39 manager

⚠️ Tomcat 自带的 examples、host-manager、manager 是默认示例与管理应用,公网服务器建议删除或按 Tomcat 官方文档配置访问口令;本文为保持安装环境干净未做改动,仅作提醒。

4.8 编写 systemd 服务单元并启动

官方二进制包不带服务单元,手写 /etc/systemd/system/tomcat.service:

cat > /etc/systemd/system/tomcat.service <<'EOF'
[Unit]
Description=Apache Tomcat 9 Web Application Server
After=network.target

[Service]
Type=forking
User=tomcat
Group=tomcat
Environment=JAVA_HOME=/usr/lib/jvm/java-17
Environment=CATALINA_PID=/opt/tomcat/temp/tomcat.pid
PIDFile=/opt/tomcat/temp/tomcat.pid
ExecStart=/opt/tomcat/bin/startup.sh
ExecStop=/opt/tomcat/bin/shutdown.sh
Restart=on-failure

[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable tomcat
systemctl start tomcat

实测输出(enable 时创建开机自启软链):

Created symlink /etc/systemd/system/multi-user.target.wants/tomcat.service → /etc/systemd/system/tomcat.service.

确认服务状态:

systemctl is-active tomcat
systemctl is-enabled tomcat

实测输出:

active
enabled
systemctl status tomcat --no-pager | head -8

实测输出:

● tomcat.service - Apache Tomcat 9 Web Application Server
   Loaded: loaded (/etc/systemd/system/tomcat.service; enabled; vendor preset: disabled)
   Active: active (running) since Tue 2026-10-13 14:40:03 UTC; 16s ago
  Process: 387 ExecStart=/opt/tomcat/bin/startup.sh (code=exited, status=0/SUCCESS)
   Main PID: 395 (java)
    Tasks: 50 (limit: 30687)
   Memory: 338.7M

💡 单元中 Environment=JAVA_HOME=/usr/lib/jvm/java-17 指向 alternatives 软链接,后续升级小版本无需改动;Type=forking 配合 PIDFile 让 systemd 准确追踪 Tomcat 主进程;Restart=on-failure 保证异常退出后自动拉起。

4.9 放行防火墙端口 8080

CentOS 8 默认启用 firewalld。确认防火墙状态后放行 8080 端口(firewalld 未运行时先 systemctl start firewalld):

systemctl start firewalld
systemctl is-active firewalld
firewall-cmd --state
firewall-cmd --permanent --add-port=8080/tcp
firewall-cmd --reload
firewall-cmd --list-ports

实测输出:

active
running
success
success
8080/tcp

⚠️ --permanent 只写规则文件,必须紧跟 firewall-cmd --reload 才对运行时生效;漏掉 reload 会出现"命令返回 success 但端口仍不通"的现象。

4.10 打开初始化安装向导并完成配置

首次部署后用浏览器访问:

http://<服务器IP>:8080/JSPWiki/Install.jsp

向导表单共 3 个配置项,按下表填写(本文实测值):

表单项表单 name本文填写值说明
Application Namejspwiki.applicationNameMyWikiWiki 站点名称,页面标题会显示
Page storage directoryjspwiki.fileSystemProvider.pageDir/var/lib/jspwiki/pages页面(含附件)存储目录,即 4.5 创建的目录
Working directoryjspwiki.workDir/var/lib/jspwiki/work搜索索引、引用缓存等工作文件目录

点击 Configure! 提交后,向导页面会显示配置结果,实测关键回显如下:

Good news:
Your new properties have been saved to /opt/tomcat/work/Catalina/localhost/JSPWiki/jspwiki-custom.properties. Copy this file to a directory that is on the classpath of your servlet engine (e.g. the WEB-INF/classes directory of your web application), and delete or rename the old file.
Because no administrator account exists yet, JSPWiki created one for you, with a random password. You can change this password later, of course. The account's id is admin and the password is uRebcqXh. Please write this information down and keep it in a safe place. JSPWiki also created a wiki group called Admin that contains this user.

⚠️ 向导生成的 admin 密码是随机的(本文本次实测为 uRebcqXh),每次部署都不同,务必先记录再继续。

4.11 配置文件归位并重启

按向导提示把生成的配置文件复制到 Web 应用的 WEB-INF/classes/ 目录(JSPWiki 会从 classpath 读取 jspwiki-custom.properties):

cp /opt/tomcat/work/Catalina/localhost/JSPWiki/jspwiki-custom.properties \
   /opt/tomcat/webapps/JSPWiki/WEB-INF/classes/jspwiki-custom.properties
chown tomcat:tomcat /opt/tomcat/webapps/JSPWiki/WEB-INF/classes/jspwiki-custom.properties
cat /opt/tomcat/webapps/JSPWiki/WEB-INF/classes/jspwiki-custom.properties

实测输出(向导实际写入的内容):

#Tue Oct 13 14:40:37 UTC 2026
jspwiki.applicationName=MyWiki
jspwiki.workDir=/var/lib/jspwiki/work
jspwiki.fileSystemProvider.pageDir=/var/lib/jspwiki/pages
jspwiki.basicAttachmentProvider.storageDir=/var/lib/jspwiki/pages
jspwiki.pageProvider=VersioningFileProvider

⚠️ jspwiki.pageProvider=VersioningFileProvider 是向导默认写入的页面提供者,带版本历史(旧版本存于 pages/OLD/<页面名>/)。

⚠️ 向导同时会把 admin 账号写入 WEB-INF/userdatabase.xml(随机密码),把 Admin 组写入 WEB-INF/groupdatabase.xml。

重启 Tomcat 使配置生效:

systemctl restart tomcat

4.12 设置管理员密码

向导生成的 admin 密码是随机的(如上文实测为 uRebcqXh),登录后立即改为固定口令(本文统一使用 q1w2e3r4,生产环境请使用强密码):

  1. 访问 http://<服务器IP>:8080/JSPWiki/Login.jsp,输入账号 admin 与向导给出的随机密码登录。
  2. 访问 http://<服务器IP>:8080/JSPWiki/UserPreferences.jsp?tab=profile。
  3. 在 Profile 表单中填写:Login name 保持 admin,Current Password 填随机密码,New Password 与 Password verify 填 q1w2e3r4,补充 E-mail 后点击 Update your wiki profile.。

保存成功后用新密码退出重登即可确认生效。

4.13 功能验证

(1)首页可访问

curl -s -o /dev/null -w "%{http_code}\n" http://localhost:8080/JSPWiki/

实测输出:

200

(2)确认 JVM 堆限制已生效

/usr/lib/jvm/java-17/bin/jps -v | grep Bootstrap | grep -oE "\-Xms[0-9]+m|\-Xmx[0-9]+m"

实测输出:

-Xms256m
-Xmx512m

(3)确认配置文件已加载(日志出现 jspwiki.workDir is already set to 即说明覆盖文件生效):

tail -20 /opt/tomcat/logs/catalina.out | grep "already set to"

实测输出:

 [INFO ] 2026-10-13 14:41:01.423 [http-nio-8080-exec-1] o.a.w.u.PropertyReader - jspwiki.workDir is already set to: /var/lib/jspwiki/work

(4)创建页面:浏览器访问 http://<服务器IP>:8080/JSPWiki/Edit.jsp?page=InstallNotes,输入内容后点击 Save。保存成功后确认磁盘落盘:

find /var/lib/jspwiki/pages -type f | sort

实测输出:

/var/lib/jspwiki/pages/InstallNotes.txt
/var/lib/jspwiki/pages/OLD/InstallNotes/1.txt
/var/lib/jspwiki/pages/OLD/InstallNotes/page.properties

再次编辑该页并保存后,OLD/ 下会保留历史版本(1.txt 为第一版),page.properties 记录每版作者与变更说明:

cat /var/lib/jspwiki/pages/OLD/InstallNotes/page.properties

实测输出:

# JSPWiki page properties for InstallNotes. DO NOT MODIFY!
#Tue Oct 13 14:46:19 UTC 2026
2.author=Administrator
1.author=Administrator
1.changenote=create by admin
2.changenote=update by admin

(5)搜索验证

curl -s "http://localhost:8080/JSPWiki/Search.jsp?query=InstallNotes" | grep -c "InstallNotes"

实测输出:

7

搜索结果页能命中刚创建的 InstallNotes 页面,全文搜索正常。

五、部署方案 B:命令行自动化初始化(免浏览器)

方案 A 的向导步骤可用 curl 完全自动化,适合批量部署或无图形终端的环境。以下命令与方案 A 的向导完全等价(CSRF Token 从页面动态提取,随取随用):

(1)提交安装向导(用户名/密码等信息与 4.10 表格一致,admin 账号由此创建):

rm -f /tmp/w.jar
TOKEN=$(curl -s -c /tmp/w.jar http://localhost:8080/JSPWiki/Install.jsp | grep -oE "X-XSRF-TOKEN\" id=\"X-XSRF-TOKEN\" value=\"[a-f0-9-]+" | grep -oE "[a-f0-9-]{20,}" | head -1)
curl -s -b /tmp/w.jar -X POST http://localhost:8080/JSPWiki/Install.jsp \
  --data-urlencode "X-XSRF-TOKEN=$TOKEN" \
  --data-urlencode "jspwiki.applicationName=MyWiki" \
  --data-urlencode "jspwiki.fileSystemProvider.pageDir=/var/lib/jspwiki/pages" \
  --data-urlencode "jspwiki.workDir=/var/lib/jspwiki/work" \
  --data-urlencode "submit=Configure!" -o /tmp/wiz.html
grep -oE "account's id is admin and the password is [A-Za-z0-9]+" /tmp/wiz.html

实测输出(随机密码每次不同,务必记录):

account's id is admin and the password is uRebcqXh

(2)配置文件归位(同方案 A 4.11):

cp /opt/tomcat/work/Catalina/localhost/JSPWiki/jspwiki-custom.properties \
   /opt/tomcat/webapps/JSPWiki/WEB-INF/classes/jspwiki-custom.properties
chown tomcat:tomcat /opt/tomcat/webapps/JSPWiki/WEB-INF/classes/jspwiki-custom.properties
systemctl restart tomcat

(3)登录并修改 admin 密码为 q1w2e3r4(把命令中的 uRebcqXh 替换为上一步记录的随机密码):

rm -f /tmp/a.jar
TOKEN=$(curl -s -c /tmp/a.jar http://localhost:8080/JSPWiki/Login.jsp | grep -oE "X-XSRF-TOKEN\" id=\"X-XSRF-TOKEN\" value=\"[a-f0-9-]+" | grep -oE "[a-f0-9-]{20,}" | head -1)
curl -s -b /tmp/a.jar -c /tmp/a.jar -X POST "http://localhost:8080/JSPWiki/Login.jsp?redirect=Main" \
  --data-urlencode "X-XSRF-TOKEN=$TOKEN" \
  --data-urlencode "j_username=admin" \
  --data-urlencode "j_password=uRebcqXh" \
  --data-urlencode "redirect=Main" \
  --data-urlencode "submitlogin=Login" -o /dev/null -w "login: %{http_code}\n"

实测输出:

login: 302
curl -s -b /tmp/a.jar "http://localhost:8080/JSPWiki/UserPreferences.jsp?tab=profile" -o /tmp/prefs.html
TOKEN=$(grep -A3 'id="editProfile"' /tmp/prefs.html | grep -oE "X-XSRF-TOKEN\" id=\"X-XSRF-TOKEN\" value=\"[a-f0-9-]+" | grep -oE "[a-f0-9-]{20,}" | head -1)
curl -s -b /tmp/a.jar -X POST "http://localhost:8080/JSPWiki/UserPreferences.jsp?tab=profile" \
  --data-urlencode "redirect=" \
  --data-urlencode "X-XSRF-TOKEN=$TOKEN" \
  --data-urlencode "loginname=admin" \
  --data-urlencode "password0=uRebcqXh" \
  --data-urlencode "password=q1w2e3r4" \
  --data-urlencode "password2=q1w2e3r4" \
  --data-urlencode "fullname=Administrator" \
  --data-urlencode "email=admin@example.org" \
  --data-urlencode "action=saveProfile" -o /dev/null -w "saveProfile: %{http_code}\n"

实测输出:

saveProfile: 302

⚠️ 表单字段 loginname、password0(当前密码)必须携带,缺项会被服务端拒绝并提示 Login name cannot be blank。提交后可用 grep -o "<user[^>]*>" /opt/tomcat/webapps/JSPWiki/WEB-INF/userdatabase.xml 查看 lastModified 是否更新来确认保存成功。

六、方案对比与选择建议

维度方案 A(浏览器向导)方案 B(curl 自动化)
版本来源官方 WAR(dlcdn.apache.org)官方 WAR(dlcdn.apache.org)
是否需联网需(下载 WAR)需(下载 WAR)
初始化方式浏览器填写 3 项表单curl 提交同一表单
systemd 来源手写 tomcat.service 单元同左
优点直观、官方流程可脚本化、适合批量/无浏览器环境
缺点不易自动化需处理 CSRF Token 提取

选择建议:单台/首次部署用方案 A;批量部署、CI 初始化或只能 SSH 的环境用方案 B。两者最终配置完全一致。

七、systemd 开机自启配置

本文 4.8 已手写单元 /etc/systemd/system/tomcat.service 并执行 systemctl enable tomcat(开机自启软链已创建)。与本方案相关的三个要点:

(1)JVM 参数入口:单元通过 /opt/tomcat/bin/startup.sh 启动,Tomcat 的 catalina.sh 会自动加载 /opt/tomcat/bin/setenv.sh 中的 JAVA_OPTS(本文已在 4.4 设置 -Xms256m -Xmx512m)。

(2)运行身份:单元声明 User=tomcat、Group=tomcat,无需 su 或 sudo 包一层;PIDFile=/opt/tomcat/temp/tomcat.pid 与单元内 Environment=CATALINA_PID 对应,保证 systemctl stop tomcat 能准确停掉主进程。

(3)自启确认:

systemctl is-enabled tomcat

实测输出:

enabled

八、配置说明

(1)配置文件体系:JSPWiki 2.12.5 不再使用单一大而全的 jspwiki.properties,而是"内置默认值(jar 内 /ini/jspwiki.properties,164 个键)+ 覆盖文件 jspwiki-custom.properties"两层结构。覆盖文件的位置按优先级:

优先级来源说明
1JVM 系统属性 jspwiki.custom.config=<绝对路径>指向任意绝对路径的覆盖文件
2classpath 下的 /jspwiki-custom.properties即 WEB-INF/classes/jspwiki-custom.properties(本文 4.11 位置)
3环境变量 / 系统属性中 jspwiki 开头的键(_ 转为 .)如环境变量 JSPWIKI_ENCODING=UTF-8 等价于 jspwiki.encoding=UTF-8

完整的参数分类详解见《Apache JSPWiki 2.12.5 配置参数详解》。

(2)调整监听端口:编辑 /opt/tomcat/conf/server.xml 中的 HTTP 连接器(默认 8080):

    <Connector port="8080" protocol="HTTP/1.1"

修改后执行 firewall-cmd --permanent --add-port=<新端口>/tcp 放行新端口(并 --permanent --remove-port=8080/tcp 移除旧端口),再 systemctl restart tomcat 生效。

(3)JVM 堆参数:位于 /opt/tomcat/bin/setenv.sh(见 4.4)。调整后重启 tomcat 服务,用 /usr/lib/jvm/java-17/bin/jps -v | grep Bootstrap 确认实际生效值(实测回显见 4.13),不要只看配置文件改动。

(4)日志位置:JSPWiki 运行日志默认随 Tomcat 控制台输出,即 /opt/tomcat/logs/catalina.out;独立日志文件 jspwiki.log 默认不落盘(日志器声明的 ${sys:java.io.tmpdir}/jspwiki.log 路径需要额外配置才会真正启用),开启方法见《Apache JSPWiki 2.12.5 常用 CLI 命令与工具详解》"日志排查"一节。

(5)数据目录迁移:如需将页面目录从 /var/lib/jspwiki/pages 迁走,修改 WEB-INF/classes/jspwiki-custom.properties 中的 jspwiki.fileSystemProvider.pageDir,把旧目录内容整体 cp -a 到新路径并 chown -R tomcat:tomcat,重启服务即可。

九、注意事项

  1. 升级到同一版本线的更新版(如 2.12.x 下一版)时,下载新 WAR 覆盖 /opt/tomcat/webapps/JSPWiki.war 并重启即可;/var/lib/jspwiki(页面)与 WEB-INF/classes/jspwiki-custom.properties(配置)、WEB-INF/userdatabase.xml(用户)均保留。重大跨版本升级(2.12 → 3.0)涉及 jakarta 命名空间与更换 Servlet 服务器,需另行评估。
  2. WEB-INF/userdatabase.xml 与 groupdatabase.xml 是用户/组数据库(XMLUserDatabase 默认位置在 war 解压目录内),备份时必须一并纳入。
  3. 官方二进制包的 Tomcat 9 保留了 shutdown 端口(/opt/tomcat/conf/server.xml 中 <Server port="8005" shutdown="SHUTDOWN">),shutdown.sh 可以停服;但统一通过 systemd 管理,停服一律使用 systemctl stop tomcat(实测 stop 后 is-active 返回 inactive,start 后恢复 active 且站点 200)。
  4. 直接编辑 pages/ 下的 .txt 文件即可修改页面内容(立即生效,JSPWiki 实时读盘),但注意保持 UTF-8 编码;OLD/ 下的历史版本不要手工改动。
  5. 升级 Tomcat 小版本时,保留 setenv.sh、conf/server.xml 与 webapps/JSPWiki.war,解压新版后按 4.3 的方式替换 /opt/tomcat 目录内容再重启。
  6. 生产环境建议:管理员密码改强口令、jspwiki.baseURL 显式设置为对外访问地址、firewalld 用 rich rule 限制 8080 来源网段或前置 Nginx 反代加 HTTPS。

十、常见问题(FAQ)

Q1:首次访问 http://<IP>:8080/JSPWiki/ 返回 404,/opt/tomcat/logs/catalina.out 报 Failed to create page directory /home/tomcat/jspwiki-files?

A:JSPWiki 2.12.5 内置默认页面目录是 ${user.home}/jspwiki-files。若 tomcat 用户创建时家目录不存在或不可写(例如 useradd 后未把家目录指向已存在目录),引擎初始化会失败、整个 Web 应用不可用。本文 4.3 将家目录设为 /opt/tomcat(目录已存在且 tomcat 属主,首次启动后 jspwiki-files 自动创建),规避了该问题。若因其他原因已中招,修复:

usermod -d /opt/tomcat tomcat
chown -R tomcat:tomcat /opt/tomcat
systemctl restart tomcat

Q2:dnf 安装时报 Waiting for process with pid N to finish 后长时间无响应?

A:上一次 dnf 进程被强制中断(Ctrl+C、kill 或终端断开)后残留(甚至变成僵尸进程),新 dnf 检测到进程锁被占用就一直等待。本文实测中曾出现 dnf 挂起 20 分钟的现场:ps aux | grep dnf 可见一个处于 Z (defunct) 状态的旧 dnf 与多个排队的新 dnf。处理:

ps aux | grep dnf | grep -v grep
kill -9 <残留的旧dnf进程PID>

若旧进程已是僵尸态(kill 无效),重启服务器后僵尸进程由 init 回收,dnf 锁随之释放。

Q3:浏览器编辑页面点 Save 后跳到 SessionExpired,自动化提交保存报 302 到 Wiki.jsp?page=SessionExpired?

A:保存校验(SpamFilter.checkHash)要求提交三类字段缺一不可:① X-XSRF-TOKEN;② encodingcheck(固定值 ぁ,UTF-8 编码检查字段);③ 动态反垃圾哈希字段——字段名随机(形如 cvobgk,约每 24 小时轮换),值形如 1792407481946。用浏览器正常操作不会遇到;做自动化时必须从当次 GET 的编辑页 HTML 中提取全部字段再提交:

grep -oE "<input type='hidden' name='[a-z]+' value='[0-9]+' />" /tmp/edit.html

实测输出(示例):

<input type='hidden' name='cvobgk' value='1792407481946' />

三字段齐全的 POST 才会返回 Location: /JSPWiki/Wiki.jsp?page=<页面名> 并正常落盘。

Q4:向导提交后页面提示属性文件已保存,重启后配置没生效?

A:向导把 jspwiki-custom.properties 写到工作目录(如 /opt/tomcat/work/Catalina/localhost/JSPWiki/),该路径不在 classpath 中,重启后不会被读取。必须按 4.11 把文件复制到 /opt/tomcat/webapps/JSPWiki/WEB-INF/classes/ 下。确认方法:重启后查看 /opt/tomcat/logs/catalina.out,出现 jspwiki.workDir is already set to: /var/lib/jspwiki/work 即说明覆盖文件已加载(实测回显见 4.13)。

Q5:admin 随机密码丢了怎么办?

A:删除 WEB-INF/userdatabase.xml 中的 <user ... loginName="admin" ... /> 条目并重启 Tomcat,再访问 Install.jsp 重新提交向导即可重建 admin(会再次生成随机密码)。注意 WEB-INF/groupdatabase.xml 中 Admin 组成员引用的是全名 Administrator,重建后自动恢复关联。

Q6:访问 http://<IP>:8080/JSPWiki/<页面名> 这种短 URL 返回 404?

A:官方 WAR 默认不启用短 URL 构造器,页面请用完整路径访问:http://<IP>:8080/JSPWiki/Wiki.jsp?page=<页面名>(实测 Wiki.jsp?page=InstallNotes 返回 200 且内容正常)。如需短 URL,在 jspwiki-custom.properties 中配置 jspwiki.shortURLConstructor 后重启。

Q7:内存不足,Tomcat 频繁 Full GC?

A:本方案堆已限制在 256–512MB。用 jps -v 确认实际生效值(见 4.13),如需调整,改 /opt/tomcat/bin/setenv.sh 的 JAVA_OPTS 后重启;同时可用 systemctl status tomcat 观察 Memory: 一行的实际占用(实测约 338.7M)。

十一、卸载方式

systemctl stop tomcat
systemctl disable tomcat
rm -f /etc/systemd/system/tomcat.service
systemctl daemon-reload
firewall-cmd --permanent --remove-port=8080/tcp
firewall-cmd --reload
userdel tomcat
rm -rf /opt/tomcat /var/lib/jspwiki
rm -f /tmp/JSPWiki.war /tmp/JSPWiki.war.sha512
rm -f /tmp/apache-tomcat-9.0.123.tar.gz /tmp/apache-tomcat-9.0.123.tar.gz.sha512

如需一并卸载 JDK:

dnf remove -y java-17-openjdk java-17-openjdk-devel

💡 firewalld 是系统级防火墙组件,保留不卸载;如需恢复 dnf 源为系统自带配置,执行 rm -f /etc/yum.repos.d/CentOS-Base.repo 后把 /etc/yum.repos.d/backup/ 下的文件移回原位(注意 CentOS 8 EOL 后原生源已不可用,仅在更换其他镜像时操作)。

十二、参考链接