Ubuntu 22.04 安装 Apache rivet 指南
在 Ubuntu 22.04 上从零安装 Apache Rivet 的完整指南,覆盖 apt 软件源方案(3.2.1)与源码编译方案(3.3.1)的实操流程、模块加载与虚拟主机最小配置,并以 curl 验证首个 .rvt 页面返回 200。
Ubuntu 22.04 安装 Apache rivet 指南
目标:在全新 Ubuntu 22.04 服务器上把 Apache Rivet 装好、加载进 httpd、跑出第一个返回 200 的
.rvt页面。全文两条路线:apt 软件源方案(版本旧但省事)与源码编译方案(拿最新稳定版 3.3.1),均实测验证,并给出选型建议与踩坑记录。实验命令均在/root下执行。
一、环境信息
- 操作系统:Ubuntu 22.04 LTS(jammy,x86_64)
- 内核与 shell:Linux 5.15+,bash
- Apache:2.4.52(event MPM)
- Tcl:8.6.12
- 目标软件:Apache Rivet
- apt 方案版本:
libapache2-mod-rivet 3.2.1-5(jammy/universe) - 源码方案版本:
rivet-3.3.1(当前最新稳定版,2026-09-05 发布)
- apt 方案版本:
- 实机验证系统版本:
cat /etc/os-release | head -2
PRETTY_NAME="Ubuntu 22.04.x LTS"
NAME="Ubuntu"
VERSION_ID="22.04"
💡 技术拓展:Rivet 由「httpd 模块 mod_rivet.so + Tcl 运行库(init.tcl、命令库、扩展包)」两部分构成,二者版本必须严格配套——3.2.x 的模块加载 3.3.x 的 Tcl 库会直接段错误(本文第九章有实测记录)。因此任何安装方式都要确认两部分的来源与版本一致。
二、前置条件
2.1 更新软件源索引
apt-get update 2>&1 | tail -3
Hit:1 http://archive.ubuntu.com/ubuntu jammy InRelease
Reading package lists... Done
Building dependency tree... Done
2.2 安装 Apache 与 Tcl
DEBIAN_FRONTEND=noninteractive apt-get install -y apache2 tcl-dev apache2-dev build-essential curl wget 2>&1 | tail -5
Setting up apache2-dev (2.4.52-1ubuntu4.25) ...
Setting up tcl-dev:amd64 (8.6.12+1build2) ...
Setting up libsqlite3-tcl:amd64 (3.37.2-2) ...
Processing triggers for man-db (2.10.2-1) ...
各包用途说明:
| 包 | 用途 |
|---|---|
| apache2 | Web 服务器本体 |
| apache2-dev | 提供 apxs(Apache 扩展编译工具),编译 mod_rivet 必需 |
| tcl-dev | Tcl 头文件与 tclConfig.sh,编译 mod_rivet 必需 |
| build-essential | gcc/make 编译工具链 |
2.3 确认关键路径
apxs -V | head -2; ls /usr/bin/apxs
APACHE_MODULEDIR=/usr/lib/apache2/modules
/usr/bin/apxs
find /usr/lib -name tclConfig.sh 2>/dev/null
/usr/lib/x86_64-linux-gnu/tcl8.6/tclConfig.sh
三、方案对比与选型
| 维度 | 方案 A:apt 软件源 | 方案 B:源码编译 |
|---|---|---|
| 版本 | 3.2.1-5(2022 年冻结) | 3.3.1(当前最新稳定) |
| 依赖处理 | 自动(itcl3、tcllib 一并装齐) | 需手工补齐(libsqlite3-tcl、itcl3、tcllib) |
| 部署速度 | 一条命令 | 约 10 分钟 |
| 跟随安全更新 | 随 Ubuntu 源 | 需自行跟踪 ASF 版本 |
| 模块与库配套 | 包内严格配套 | 编译时自动配套 |
| 适用 | 快速验证、老版本可满足 | 生产部署、需要 3.3.x 新特性 |
建议:新部署直接选方案 B 拿 3.3.x;方案 A 适合一次性的可用性验证。两方案不要混装同一台机器(第九章实测混装后果)。
四、方案 A:apt 软件源安装(3.2.1)
4.1 查询与安装
apt-cache policy libapache2-mod-rivet | head -3
libapache2-mod-rivet:
Candidate: 3.2.1-5
Version table:
3.2.1-5 500
DEBIAN_FRONTEND=noninteractive apt-get install -y libapache2-mod-rivet 2>&1 | tail -4
Setting up libapache2-mod-rivet-doc (3.2.1-5) ...
Setting up libapache2-mod-rivet (3.2.1-5) ...
Processing triggers for apache2 (2.4.52-1ubuntu4.25) ...
包依赖会自动带入 itcl3、tcllib(Session/DIO 扩展包所需),免去手工补齐。
4.2 包布局与自动配置
dpkg -L libapache2-mod-rivet | grep -E 'modules|tcltk|mods-enabled' | head -8
/usr/lib/apache2/modules/mod_rivet.so
/usr/lib/tcltk/rivet3
/etc/apache2/mods-available/rivet.load
/etc/apache2/mods-available/rivet.conf
dpkg -L 可见:模块装到 httpd 模块目录,Tcl 运行库装到 /usr/lib/tcltk/rivet3(3.2.1 的库路径与源码方案的 /usr/local/apache2/lib/ 不同,属于包管理器规范化路径),并自带 mods-available/rivet.load 与 rivet.conf。
4.3 启用模块与验证
a2enmod rivet 2>&1 | tail -1
apachectl -k restart
curl -s -o /dev/null -w '%{http_code}\n' http://localhost/hello.rvt
Enabling module rivet.
200
⚠️ 实测坑点:若机器上先前已经手工编译安装过 3.3.1,
apt install libapache2-mod-rivet会因rivet.load/rivet.conf已存在而触发 conffile 冲突,非交互终端下安装会中断在半完成状态;随后 3.2.1 模块 + 3.3.1 库混用会段错误。因此"换方案"前先彻底卸载旧文件,避免版本混装(详见第九章)。
五、方案 B:源码编译安装(3.3.1,推荐)
5.1 下载与完整性校验
cd /root
wget -q https://archive.apache.org/dist/tcl/rivet/rivet-3.3.1.tar.gz
wget -q https://archive.apache.org/dist/tcl/rivet/rivet-3.3.1.tar.gz.sha512
sha512sum -c rivet-3.3.1.tar.gz.sha512
rivet-3.3.1.tar.gz: OK
5.2 解压与 configure
tar xzf rivet-3.3.1.tar.gz
cd rivet-3.3.1
./configure --with-apxs=/usr/bin/apxs --with-tcl=/usr/lib/x86_64-linux-gnu/tcl8.6 --enable-threads 2>&1 | tail -25
configure: Rivet package version is 3.3
checking if the worker MPM bridge will run in single thread mode... no, maximal number of Tcl threads
checking if we want the worker bridge to serialize HTTP requests... no, HTTP requests will not be serialized
checking if we are building mod_rivet for debugging... no, ordinary build
checking Major version... 3
checking Minor version... 3
checking Point version... 1
checking if the commands in ::rivet namespace will be exported... yes
checking Debian TCL_PACKAGE_PATH workaround... loading
checking that generated files are newer than configure... done
configure: creating ./config.status
config.status: creating Makefile
(以上为 ./configure ... 2>&1 | tail -25 的真实回显节选;worker 桥多线程检查通过即 event/worker MPM 可用。)
configure 关键参数说明:
| 参数 | 作用 | 实测取值 |
|---|---|---|
--with-apxs | 指定 apxs,决定模块安装路径 | /usr/bin/apxs → 模块装入 /usr/lib/apache2/modules/ |
--with-tcl | tclConfig.sh 位置 | /usr/lib/x86_64-linux-gnu/tcl8.6 |
--enable-threads | 启用 Tcl 线程化构建,worker/event MPM 需要 | 开启 |
--with-rivet-target-dir | 自定义 Tcl 库安装目录 | 不设则默认 /usr/local/apache2/lib/rivet3.3.1 |
--with-upload-dir | 默认上传临时目录 | 不设则用编译默认值 |
--with-post-max | POST 请求体上限(字节) | 默认值编译期内置 |
💡 技术拓展:
--enable-threads与 MPM 的关系——Ubuntu 默认 event MPM 是多线程模型,Rivet 的 worker 桥在多线程下运行,Tcl 必须以线程化方式构建,否则解释器无法隔离到线程,请求会串数据。configure 输出中checking if the worker MPM bridge will run in single thread mode... no, maximal number of Tcl threads即该检查的结果(确认 worker 桥运行在多线程模式)。
5.3 编译与安装
make 2>&1 | tail -4
successful sourcing of packages/form/form22.tcl
packages provided were {form 2.2}
successful loading of librivetlib.so
packages provided were {rivetlib 3.3.1}
successful loading of librivetparser.so
packages provided were {rivetparser 0.2}
make install 2>&1 | grep -E 'install|successful' | head -20
/bin/bash ../libtool --mode=install /bin/bash ../tclconfig/install-sh -c mod_rivet.la '/usr/lib/apache2/modules'
libtool: install: /bin/bash ../tclconfig/install-sh -c .libs/mod_rivet.so /usr/lib/apache2/modules/mod_rivet.so
/bin/bash ../libtool --mode=install /bin/bash ../tclconfig/install-sh -c librivetparser.la librivetlib.la '/usr/local/apache2/lib/rivet3.3.1'
libtool: install: /bin/bash ../tclconfig/install-sh -c .libs/librivetparser.so /usr/local/apache2/lib/rivet3.3.1/librivetparser.so
libtool: install: /bin/bash ../tclconfig/install-sh -c .libs/librivetlib.so /usr/local/apache2/lib/rivet3.3.1/librivetlib.so
/bin/bash ../libtool --mode=install /bin/bash ../tclconfig/install-sh -c rivet_worker_mpm.la rivet_prefork_mpm.la rivet_lazy_mpm.la '/usr/local/apache2/lib/rivet3.3.1/mpm'
libtool: install: /bin/bash ../tclconfig/install-sh -c .libs/rivet_worker_mpm.so /usr/local/apache2/lib/rivet3.3.1/mpm/rivet_worker_mpm.so
libtool: install: /bin/bash ../tclconfig/install-sh -c .libs/rivet_prefork_mpm.so /usr/local/apache2/lib/rivet3.3.1/mpm/rivet_prefork_mpm.so
libtool: install: /bin/bash ../tclconfig/install-sh -c .libs/rivet_lazy_mpm.so /usr/local/apache2/lib/rivet3.3.1/mpm/rivet_lazy_mpm.so
echo 'target install-data-hook: removing unwanted libtool .la files from /usr/local/apache2/lib/rivet3.3.1 /usr/lib/apache2/modules /usr/local/apache2/lib/rivet3.3.1/mpm'
安装产物核对:
ls -la /usr/lib/apache2/modules/mod_rivet.so
ls /usr/local/apache2/lib/rivet3.3.1/
-rwxr-xr-x 1 root root 449552 Oct 16 04:07 /usr/lib/apache2/modules/mod_rivet.so
default_request_handler.tcl
init.tcl
librivetlib.so
librivetparser.so
mpm
packages
pkgIndex.tcl
rivet-tcl
六、加载模块与最小站点配置
6.1 模块加载文件
源码方案不自带 Debian 风格的 mods 文件,需要手工创建(与 apt 方案的 rivet.load 语法一致):
cat > /etc/apache2/mods-available/rivet.load <<'EOF'
LoadModule rivet_module /usr/lib/apache2/modules/mod_rivet.so
EOF
cat > /etc/apache2/mods-available/rivet.conf <<'EOF'
<IfModule rivet_module>
AddType application/x-httpd-rivet .rvt
AddType application/x-rivet-tcl .tcl
</IfModule>
EOF
a2enmod rivet
Enabling module rivet.
To activate the new configuration, you need to run:
service apache2 restart
配置要点:
AddType application/x-httpd-rivet .rvt把.rvt后缀映射给 mod_rivet 处理(源码中模板处理器的匹配类型即为application/x-httpd-rivet);AddType application/x-rivet-tcl .tcl让.tcl后缀作为"整页 Tcl 脚本"处理(无模板,纯 Tcl 输出);- 若要仅在单个虚拟主机生效,也可把两行
AddType移入<VirtualHost>段,见 6.3。
6.2 启动与首个 .rvt 页面验证
写一个最小模板(注意:<? ?> 内是 Tcl 代码,<?= ?> 是插值输出):
cat > /var/www/html/hello.rvt <<'EOF'
<? set title "Hello Rivet" ?>
<html>
<head><title><?= $title ?></title></head>
<body>
<h1><?= $title ?></h1>
<p>Powered by Apache Rivet, server time: <? puts [clock format [clock seconds] -format "%Y-%m-%d %H:%M:%S"] ?></p>
</body>
</html>
EOF
启动服务并验证:
apachectl -k restart
sleep 1
curl -s -o /dev/null -w '%{http_code}\n' http://localhost/hello.rvt
200
curl -s http://localhost/hello.rvt
<html>
<head><title>Hello Rivet</title></head>
<body>
<h1>Hello Rivet</h1>
<p>Powered by Apache Rivet, server time: 2026-10-16 04:07:12</p>
</body>
</html>
.tcl 整页脚本方式同样验证一次:
cat > /var/www/html/info.tcl <<'EOF'
puts -nonewline "<h1>Rivet Tcl script</h1><p>pid=[pid], tcl=[info patchlevel]</p>"
EOF
curl -s http://localhost/info.tcl
<h1>Rivet Tcl script</h1><p>pid=11235, tcl=8.6.12</p>
⚠️ 实测坑点:向
.rvt文件写入内容时若用不带引号的 shell heredoc(<<EOF),Tcl 变量$title、$t会被 shell 提前替换成空字符串,页面看似 200 但插值丢失。必须使用带引号的<<'EOF',或用编辑器等可原样落盘的方式写入。这是实测踩过的第一个坑,也是"页面 200 但内容不对"的最常见原因。
6.3 虚拟主机最小配置
示例:站点 site1.example.com 仅在自身目录启用 .rvt 处理,并使用独立 DocumentRoot。
mkdir -p /var/www/site1
cat > /etc/apache2/sites-available/site1.conf <<'EOF'
<VirtualHost *:80>
ServerName site1.example.com
DocumentRoot /var/www/site1
<Directory /var/www/site1>
Options Indexes FollowSymLinks
AllowOverride None
Require all granted
AddType application/x-httpd-rivet .rvt
AddType application/x-rivet-tcl .tcl
</Directory>
</VirtualHost>
EOF
a2ensite site1
echo 'test page' > /var/www/site1/index.rvt
启用与验证(本机用 Host 头模拟域名):
apachectl -k restart
curl -s -H 'Host: site1.example.com' http://localhost/index.rvt
test page
💡 技术拓展:
.rvt处理粒度由 AddType 的作用域决定——写在rivet.conf全局段则所有虚拟主机都处理 .rvt;写在某个<Directory>/<VirtualHost>内则只有该范围生效。多站点混部(部分站点 PHP、部分站点 Rivet)推荐按虚拟主机隔离,避免后缀被误解释。
七、可选:会话/表单扩展的运行时依赖
若计划使用 Session/DIO/表单扩展包(安装已完成,是源码包自带的 packages/),还需三个系统包,实测版本:
DEBIAN_FRONTEND=noninteractive apt-get install -y libsqlite3-tcl itcl3 tcllib 2>&1 | tail -3
dpkg -l libsqlite3-tcl itcl3 tcllib | awk '/^ii/{print $2, $3}'
itcl3 3.4.3+dfsg-1build2
libsqlite3-tcl 3.37.2-2
tcllib 2.0+dfsg-1
| 包 | 提供能力 | 被 Rivet 哪部分依赖 |
|---|---|---|
| itcl3 | Tcl 面向对象扩展(Itcl 包) | DIO、Session 均为 itcl 类,缺它直接报 can't find package Itcl |
| libsqlite3-tcl | Tcl 的 sqlite3 绑定 | Session 默认经 DIO 落 sqlite 库 |
| tcllib | md5/sha 等标准库 | Session 会话 ID 生成依赖 md5 |
验证三者可用:
echo 'package require Itcl; package require sqlite3; package require md5; puts ok' | tclsh
ok
八、安装验证清单
安装完成后按序自检:
| # | 检查项 | 命令 | 预期 |
|---|---|---|---|
| 1 | 模块文件存在 | ls /usr/lib/apache2/modules/mod_rivet.so | 存在 |
| 2 | 模块已启用 | ls /etc/apache2/mods-enabled/ | grep rivet | rivet.load、rivet.conf 两个符号链接 |
| 3 | 配置语法 | apachectl -t | Syntax OK |
| 4 | 模块注册类型 | curl -s -o /dev/null -w '%{http_code}' http://localhost/hello.rvt | 200 |
| 5 | 模板插值 | curl -s http://localhost/hello.rvt | grep -c 'Hello Rivet' | ≥ 1 |
| 6 | .tcl 处理器 | curl -s http://localhost/info.tcl | 输出 Tcl 版本 |
| 7 | 会话依赖 | echo 'package require Itcl;package require sqlite3;package require md5;puts ok' | tclsh | ok |
第 3 项的实测回显:
apachectl -t
Syntax OK
第 2 项的实测回显:
ls /etc/apache2/mods-enabled/ | grep rivet
rivet.conf
rivet.load
九、常见问题与回退
9.1 模块加载但 .rvt 不被处理(返回 404 之外的原文下载)
现象:curl 得到模板源码。原因:AddType 未生效或写在 <IfModule> 外被注释。排查:
apachectl -M | grep rivet
rivet_module (shared)
模块已在但类型未映射,检查 rivet.conf 中的 AddType 行是否被正确包含。
9.2 3.2.1 模块与 3.3.1 库混装段错误
实测记录:先以源码方案装 3.3.1,再 apt 安装 3.2.1(覆盖 /usr/lib/apache2/modules/mod_rivet.so),启动后错误日志持续出现:
[Fri Oct 16 04:24:09.689402 2026] [core:notice] [pid 9601:tid 130689066289024] AH00051: child pid 11791 exit signal Segmentation fault (11), possible coredump in /etc/apache2
处理流程(实测有效):
DEBIAN_FRONTEND=noninteractive dpkg --configure -a --force-confold # 先结束半安装状态
apt-get remove -y --purge libapache2-mod-rivet libapache2-mod-rivet-doc
cp /root/mod_rivet-3.3.1.so /usr/lib/apache2/modules/mod_rivet.so # 恢复配套版本
rm -f /run/apache2/apache2.pid # 清理残留 pid
apachectl -k start
curl -s -o /dev/null -w '%{http_code}\n' http://localhost/hello.rvt
200
⚠️ 注意:purge 包时其 postrm 会顺带删除
mods-enabled下的 rivet 链接与包自带的rivet.load/rivet.conf,需按 6.1 重建并a2enmod rivet;若apachectl报httpd already running但进程已为僵尸,先删/run/apache2/apache2.pid。
9.3 heredoc 写模板导致变量丢失
现象:页面 200,但 <?= $title ?> 输出为空。原因:bash -c 内非引用 heredoc 的 $ 被展开。修复:heredoc 定界符加引号(<<'EOF')。排查方法:
cat -A /var/www/html/hello.rvt | head -3
若 <?= ?> 中间变量名已消失,即可确认是文件写入问题而非 Rivet 问题。
9.4 完全卸载
源码方案卸载:
rm -f /etc/apache2/mods-enabled/rivet.load /etc/apache2/mods-enabled/rivet.conf
rm -f /etc/apache2/mods-available/rivet.load /etc/apache2/mods-available/rivet.conf
rm -f /usr/lib/apache2/modules/mod_rivet.so
rm -rf /usr/local/apache2/lib/rivet3.3.1
apachectl -k restart
apt 方案卸载:
apt-get remove -y --purge libapache2-mod-rivet libapache2-mod-rivet-doc
apachectl -k restart
十、参考链接
- Apache Rivet 下载与校验文件:https://archive.apache.org/dist/tcl/rivet/
- Rivet 官方文档(配置与模板语法):https://rivet.apache.org/
- Apache httpd 2.4 模块开发与 apxs:https://httpd.apache.org/docs/2.4/programs/apxs.html
- 相关文档:《Apache rivet 介绍与选型指南》《Apache rivet 在 Ubuntu 22.04 集成使用指南》《Apache rivet 配置参数详解》