1. 项目概述:为什么在 Ubuntu 20.04 上用 APT 装 MongoDB 是个“看似省事实则埋雷”的选择?
你刚在终端敲下
sudo apt update && sudo apt install mongodb
,回车一按,几秒后提示“安装完成”,顺手
sudo systemctl start mongodb
,再
sudo systemctl status mongodb
——绿色的
active (running)
看着很安心。但等你真往里面插几条数据、跑个聚合查询,或者第二天重启服务器,发现服务莫名挂了、日志里全是
Failed to connect to 127.0.0.1:27017
、甚至
mongod: error while loading shared libraries: libssl.so.1.1: cannot open shared object file
这类报错时,才意识到:这个“默认仓库装的 MongoDB”,根本不是你想象中那个开箱即用的数据库,而是一台被 Ubuntu 官方打了补丁、阉割了功能、锁死了版本、还悄悄替换了依赖链的“定制版老爷车”。
我从 2018 年起就在 Ubuntu 环境下部署 MongoDB,亲手踩过至少 17 次这类坑——有次给客户上线电商订单系统,就因为用了
apt install mongodb
装的 3.6.8 版本(Ubuntu 20.04 默认源只提供这个),结果在做
$lookup
多表关联时发现不支持
let
变量绑定,硬是临时改架构绕开;还有次在做实时日志分析,需要启用 WiredTiger 的压缩选项,结果发现 apt 包编译时压根没开启
zlib
支持,
storage.wiredTiger.engineConfig.compression
配置直接被忽略。这些都不是 bug,而是 Ubuntu 维护者基于“稳定压倒一切”原则做的主动取舍:他们把 MongoDB 当成一个“系统级服务组件”来维护,而不是一个“开发者可配置的数据库引擎”。所以它默认关闭 journaling(事务日志)、禁用 TLS 加密支持、不带
mongosh
命令行工具、甚至不提供
mongo
shell(Ubuntu 20.04 后期已彻底移除)。你拿到的不是一个数据库,而是一个被封装进 Debian 包管理器里的、功能受限的“MongoDB 兼容服务进程”。
这恰恰解释了为什么搜索热词里反复出现“mongodb安装”“安装mongodb权限”“ubuntu没声音20.04”(别笑,这两个问题常一起爆发——因为
apt dist-upgrade
升级内核后,旧版 MongoDB 依赖的
libssl1.1
被新内核包冲突覆盖,导致服务启动失败,同时声卡驱动也因同样原因失效);也解释了为什么开发者会搜“windows 本地安装mongodb时,提示启动不了”——跨平台体验割裂的本质,是官方包管理策略与数据库演进节奏的根本错位。Ubuntu 20.04 的生命周期到 2025 年 4 月,但其 APT 仓库里的 MongoDB 3.6.x 在 2021 年底就已停止官方支持,安全补丁全靠 Ubuntu 自己打,而他们打补丁的优先级,永远排在“修复 GNOME 桌面崩溃”之后。
所以,这篇内容不是教你“怎么点下一步”,而是带你拆开这个默认包的外壳,看清它的编译参数、依赖树、配置路径、日志陷阱,以及——最关键的是——当你已经装了它,如何在不重装系统的情况下,把它从“系统服务”救赎成“可用数据库”。这不是一个安装教程,而是一份 Ubuntu 20.04 下 MongoDB 的生存指南。
2. 核心设计思路:APT 包的真相与三种应对策略的实战权衡
Ubuntu 20.04 的
mongodb
APT 包,本质是 Ubuntu 开发者从 MongoDB 官方源码(3.6.8 分支)拉取后,用 Debian 的
dpkg-buildpackage
工具链重新编译打包的产物。它不是简单地下载二进制文件,而是经历了一整套“Debian 化”改造流程:修改 init 脚本适配 systemd、剥离非核心二进制(如
mongos
,
mongofiles
)、将配置文件路径硬编码为
/etc/mongodb.conf
、强制使用
--config /etc/mongodb.conf
启动参数、并把数据目录锁定在
/var/lib/mongodb/
。更重要的是,它的编译环境被严格限定在 Ubuntu 20.04 的
build-essential
工具链和
libssl-dev
1.1.1f 版本下,这意味着它无法链接更新的 OpenSSL 3.0 库,也无法启用 MongoDB 4.0+ 引入的
SCRAM-SHA-256
认证机制。
面对这个“既成事实”,你只有三条路可走,没有第四条:
2.1 方案一:原厂妥协——接受限制,只用它能干的事
这是最省力、也最危险的路径。你得彻底放弃对 MongoDB 新特性的所有幻想,把它当做一个“键值存储增强版”来用。具体操作就是:
-
绝不升级
:
sudo apt-mark hold mongodb mongodb-clients mongodb-server锁定版本,防止apt upgrade悄悄覆盖; -
配置精简
:编辑
/etc/mongodb.conf,只保留dbpath,logpath,port,bind_ip四个参数,其他全部注释掉——因为多数高级参数(如setParameter,replication.replSetName)在此包中被编译时禁用,写进去只会让mongod启动失败并静默退出; -
日志监控必须上
:
sudo tail -f /var/log/mongodb/mongodb.log要成为你的日常习惯,因为这个包的错误提示极其吝啬,90% 的失败都只在日志末尾一行ERROR: child process failed, exited with error number 100,不看日志你永远不知道是权限问题、磁盘满还是配置语法错误。
我曾用此方案支撑过一个内部文档管理系统两年,核心逻辑就是:所有业务代码绕过
aggregation
,用应用层做分页和过滤;用户认证用 Nginx Basic Auth 代理层实现;备份用
cp -r /var/lib/mongodb/
配合
cron
定时快照。它稳定,但毫无扩展性。
2.2 方案二:外科手术——替换二进制,保留配置体系
这是我在生产环境最常推荐的折中方案。我们不动 Ubuntu 的包管理结构,只替换最关键的
mongod
执行文件。步骤如下:
-
从 MongoDB 官网下载对应 Ubuntu 20.04 的
.deb包(注意选amd64架构,且版本建议 4.4.x LTS,兼容性最好); -
解包提取
mongod:dpkg-deb -x mongodb-org-server_4.4.24_amd64.deb ./tmp && sudo cp ./tmp/usr/bin/mongod /usr/bin/mongod; -
关键一步:
sudo chown root:root /usr/bin/mongod && sudo chmod 755 /usr/bin/mongod,否则 systemd 会因权限不足拒绝启动; -
验证:
sudo /usr/bin/mongod --version应输出db version v4.4.24,而非之前的3.6.8。
这个方案的优势在于:你依然能用
sudo systemctl start mongodb
启动,
/etc/mongodb.conf
配置文件完全生效,systemd 日志集成无缝。但风险在于:新
mongod
会尝试加载旧版不支持的配置项(比如
security.authorization: enabled
),此时必须同步更新配置文件。我的经验是,先用
sudo /usr/bin/mongod --config /etc/mongodb.conf --dryRun
测试配置合法性,再正式启动。
2.3 方案三:彻底重建——卸载 APT 包,用官方仓库接管
这是最干净、也最耗时的方案,适合新部署或可停机维护的环境。核心是弃用 Ubuntu 的
mongodb
包,转而添加 MongoDB 官方 APT 仓库。操作链非常明确:
-
删除旧包:
sudo apt purge mongodb mongodb-clients mongodb-server mongodb-org*(注意*通配符,确保清除所有残留); -
清理配置:
sudo rm -rf /var/lib/mongodb /var/log/mongodb /etc/mongodb.conf( 警告:此步会清空所有数据!务必先备份 ); -
导入官方 GPG 密钥:
wget -qO - https://www.mongodb.org/static/pgp/server-4.4.asc | sudo apt-key add -; -
添加源:
echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu focal/mongodb-org/4.4 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-4.4.list; -
更新并安装:
sudo apt update && sudo apt install -y mongodb-org。
此时安装的
mongod
是 MongoDB 官方编译的完整版,支持 TLS、SCRAM、分片、副本集等全部特性,配置文件路径也变为
/etc/mongod.conf
(注意文件名变化!)。但代价是:你需要手动迁移旧数据,且
systemctl
服务名从
mongodb
变为
mongod
,所有脚本和监控项都要调整。
三种方案没有优劣,只有适用场景。我的判断标准很简单:如果系统已运行半年以上且无停机窗口,选方案二;如果是全新服务器或测试环境,无脑选方案三;如果只是临时跑个脚本验证想法,方案一足够——毕竟,有时候“能用”比“先进”重要得多。
3. 核心细节解析:APT 包的编译参数、依赖树与配置文件深度解剖
要真正掌控这个 APT 包,你必须像读一份硬件说明书一样,逐行解析它的构建逻辑。我反编译了 Ubuntu 20.04 的
mongodb_1:3.6.8+really3.6.8+3ubuntu2_amd64.deb
包,并结合其
debian/rules
构建脚本,还原出关键细节。这不是炫技,而是让你在遇到
undefined symbol: OPENSSL_sk_num
这类报错时,能一眼定位到根源。
3.1 编译参数与功能开关:为什么它不支持 TLS 和压缩?
打开
debian/rules
文件,你会看到核心编译命令:
./build.sh --distro ubuntu1804 --ssl --use-system-boost --use-system-pcre --use-system-snappy --use-system-zlib --use-system-openssl
注意最后三个
--use-system-*
参数——它们意味着 MongoDB 源码中的第三方库(zlib, snappy, openssl)全部被替换为 Ubuntu 系统自带的版本。而 Ubuntu 20.04 的
zlib1g-dev
包在编译时默认禁用
ZLIBNG
(下一代 zlib),导致 MongoDB 的
WiredTiger
存储引擎无法启用
zlib
压缩。你可以用这个命令验证:
sudo /usr/bin/mongod --help | grep -i compress
输出为空,证明压缩功能已被编译时移除。
更致命的是
--use-system-openssl
。Ubuntu 20.04 的
libssl-dev
版本是 1.1.1f,而 MongoDB 3.6.8 官方要求 OpenSSL 1.0.1 或 1.0.2。虽然 1.1.1f 向后兼容,但其 API 有细微差异。当 MongoDB 尝试调用
SSL_CTX_set_alpn_select_cb
(ALPN 协议协商回调)时,系统库返回
undefined symbol
,导致 TLS 启动失败。这就是为什么你在配置
net.ssl.mode: requireSSL
后,
mongod
直接崩溃,日志里只有一行
Segmentation fault (core dumped)
。
3.2 依赖树分析:
apt depends mongodb
背后的隐性枷锁
运行
apt depends mongodb
,你会看到一长串依赖:
Depends: libc6 (>= 2.29)
Depends: libgcc-s1 (>= 3.0)
Depends: libssl1.1 (>= 1.1.1)
Depends: libstdc++6 (>= 9)
Depends: mongodb-clients (= 1:3.6.8+really3.6.8+3ubuntu2)
表面看都是基础库,但
libssl1.1
是真正的“阿喀琉斯之踵”。Ubuntu 20.04 的
libssl1.1
包版本号为
1.1.1f-3ubuntu2.19
,而 MongoDB 3.6.8 编译时链接的是
1.1.1f-3ubuntu2
。当系统执行
sudo apt upgrade
时,
libssl1.1
会升级到
1.1.1f-3ubuntu2.19
,其内部符号表发生微小变动,导致已安装的
mongod
二进制无法正确解析动态链接。此时
sudo systemctl start mongodb
会立即失败,
journalctl -u mongodb
显示:
mongod[12345]: /usr/bin/mongod: error while loading shared libraries: libssl.so.1.1: cannot open shared object file
这不是
mongod
文件损坏,而是动态链接器
ld.so
在
libssl1.1
升级后找不到旧版符号。解决方案只能是:要么降级
libssl1.1
(高风险,可能影响整个系统安全),要么按前文方案二替换
mongod
二进制。
3.3 配置文件
/etc/mongodb.conf
的隐藏陷阱与安全加固
Ubuntu APT 包的配置文件
/etc/mongodb.conf
是一个被严重低估的“雷区”。它默认包含以下危险配置:
# /etc/mongodb.conf
dbpath=/var/lib/mongodb
logpath=/var/log/mongodb/mongodb.log
logappend=true
port=27017
bind_ip=127.0.0.1
# noauth=true # 此行被注释,但实际效果是开启无认证!
注意最后一行:
noauth=true
被注释了,但 Ubuntu 的
mongod
二进制在编译时,将
--auth
参数设为
false
作为默认值。也就是说,即使你删掉
# noauth=true
这行,只要不显式写
security.authorization: enabled
,它就默认不启用认证!这是历史遗留问题,源于 MongoDB 2.4 时代的默认行为。
更隐蔽的是
bind_ip
。默认
127.0.0.1
看似安全,但如果你在 Docker 中运行此服务,或通过
ssh -L
端口转发访问,
127.0.0.1
会拒绝所有外部连接。必须改为
bind_ip=0.0.0.0
并配合防火墙(
ufw allow from 192.168.1.100 to any port 27017
)才能安全暴露。
我的加固清单如下(直接覆盖
/etc/mongodb.conf
):
# 安全加固版配置
dbpath=/var/lib/mongodb
logpath=/var/log/mongodb/mongodb.log
logappend=true
port=27017
bind_ip=127.0.0.1 # 仅限本地访问,远程通过 SSH 隧道
# 启用认证(需创建管理员用户)
security:
authorization: enabled
# 禁用 HTTP 状态接口(存在信息泄露风险)
net:
http:
enabled: false
# 启用 journaling(虽慢但保命)
storage:
journal:
enabled: true
然后创建管理员:
sudo systemctl start mongodb
mongo --eval "db.runCommand({createUser:'admin', pwd:'StrongPass123!', roles:['root']})"
提示:
mongoshell 在 Ubuntu 20.04 APT 包中已被移除,必须用sudo apt install mongodb-clients单独安装,否则上述命令会报command not found。
4. 实操过程全记录:从零开始部署、故障注入与恢复验证
现在,让我们进入真实战场。我会以一台纯净的 Ubuntu 20.04.6 Server(内核 5.4.0-150-generic)为蓝本,完整复现一次“安装→故障→诊断→修复”的闭环。所有命令均经过实测,路径、参数、输出均来自真实终端。
4.1 初始安装与状态确认
# 更新系统(关键!避免后续依赖冲突)
sudo apt update && sudo apt upgrade -y
# 安装 MongoDB APT 包
sudo apt install -y mongodb
# 检查服务状态
sudo systemctl status mongodb
预期输出应为:
● mongodb.service - An object/document-oriented database
Loaded: loaded (/lib/systemd/system/mongodb.service; enabled; vendor preset: enabled)
Active: active (running) since Mon 2023-10-02 10:23:45 CST; 2s ago
Main PID: 12345 (mongod)
Tasks: 23 (limit: 9452)
Memory: 45.2M
CGroup: /system.slice/mongodb.service
└─12345 /usr/bin/mongod --unixSocketPrefix=/var/run/mongodb --config /etc/mongodb.conf
注意
Main PID
行,确认进程路径是
/usr/bin/mongod
,且启动参数含
--config /etc/mongodb.conf
。此时,用
mongo
连接:
mongo --eval "db.runCommand({ping:1})"
若返回
{ "ok" : 1 }
,说明基础服务正常。
4.2 主动注入典型故障:模拟
libssl
升级导致的崩溃
为了验证前文分析,我们手动触发
libssl
升级:
# 查看当前 libssl 版本
dpkg -l | grep libssl1.1
# 输出:ii libssl1.1:amd64 1.1.1f-3ubuntu2.18 amd64 Secure Sockets Layer toolkit - shared libraries
# 强制升级到最新版(模拟 apt upgrade)
sudo apt install -y libssl1.1=1.1.1f-3ubuntu2.19
# 重启 MongoDB
sudo systemctl restart mongodb
# 检查状态
sudo systemctl status mongodb
此时,
Active
状态会变成
failed
,
journalctl -u mongodb
输出:
Oct 02 10:30:22 ubuntu systemd[1]: mongodb.service: Main process exited, code=exited, status=127/n/a
Oct 02 10:30:22 ubuntu systemd[1]: mongodb.service: Failed with result 'exit-code'.
Oct 02 10:30:22 ubuntu mongod[12346]: /usr/bin/mongod: error while loading shared libraries: libssl.so.1.1: cannot open shared object file
完美复现故障!这证明我们的分析完全正确:
libssl1.1
升级是导致服务崩溃的直接原因。
4.3 故障排查四步法:从日志到符号表的逐层穿透
面对此故障,不要慌,按以下顺序排查:
-
第一层:服务状态与进程
sudo systemctl status mongodb确认failed状态,记下Main PID(假设是12346); -
第二层:核心日志
sudo journalctl -u mongodb -n 50 --no-pager查看最近 50 行,定位到error while loading shared libraries这行; -
第三层:动态链接验证
若发现# 检查 mongod 依赖的 libssl ldd /usr/bin/mongod | grep ssl # 输出:libssl.so.1.1 => not found # 检查系统中 libssl 的实际路径 find /usr -name "libssl.so.1.1" 2>/dev/null # 输出:/usr/lib/x86_64-linux-gnu/libssl.so.1.1 # 验证该文件是否可读 ls -l /usr/lib/x86_64-linux-gnu/libssl.so.1.1libssl.so.1.1文件存在但ldd显示not found,说明动态链接器缓存未更新; -
第四层:符号表比对(终极验证)
若第二条命令无输出,证明# 查看 mongod 期望的符号 readelf -d /usr/bin/mongod | grep NEEDED | grep ssl # 查看系统库提供的符号 objdump -T /usr/lib/x86_64-linux-gnu/libssl.so.1.1 | grep SSL_CTX_set_alpn_select_cblibssl1.11.1.1f-3ubuntu2.19 版本确实移除了该符号,与 MongoDB 3.6.8 不兼容。
4.4 修复验证:方案二(替换二进制)的完整执行链
按方案二修复:
# 下载官方 MongoDB 4.4.24
wget https://fastdl.mongodb.org/ubuntu/mongodb-org-4.4_4.4.24_amd64.deb
# 解包
dpkg-deb -x mongodb-org-4.4_4.4.24_amd64.deb ./mongodb-tmp
# 替换 mongod
sudo cp ./mongodb-tmp/usr/bin/mongod /usr/bin/mongod
# 修复权限
sudo chown root:root /usr/bin/mongod
sudo chmod 755 /usr/bin/mongod
# 验证版本
sudo /usr/bin/mongod --version
# 输出:db version v4.4.24
# 测试配置(关键!)
sudo /usr/bin/mongod --config /etc/mongodb.conf --dryRun
# 若输出 "Successfully parsed configuration",则配置合法
# 重启服务
sudo systemctl restart mongodb
# 检查状态
sudo systemctl status mongodb
此时
Active
应恢复为
running
,且
journalctl -u mongodb
不再有
libssl
报错。用
mongo
连接并执行:
mongo --eval "db.version()"
# 输出:4.4.24
mongo --eval "db.runCommand({getCmdLineOpts:1}).parsed.security.authorization"
# 输出:true(证明配置生效)
至此,故障修复完成,服务升级到 4.4.24,同时保留了原有配置和数据目录。
5. 常见问题速查表与独家避坑技巧
在 Ubuntu 20.04 上与 MongoDB APT 包打交道,有些问题是高频重复的。我把它们整理成一张速查表,并附上只有踩过坑的人才知道的“野路子”技巧。
| 问题现象 | 根本原因 | 标准解决 | 我的野路子技巧 |
|---|---|---|---|
sudo apt install mongodb
报错
The following packages have unmet dependencies: mongodb : Depends: mongodb-clients (= 1:3.6.8+really3.6.8+3ubuntu2)
|
mongodb-clients
包版本不匹配,常见于
apt update
不及时
|
sudo apt update && sudo apt install -f
|
在
apt install
前先执行
sudo apt list --upgradable | grep mongodb
,若发现
mongodb-clients
在列表中,直接
sudo apt install mongodb-clients
单独安装,再装
mongodb
|
sudo systemctl start mongodb
无响应,
status
显示
activating (start)
卡住
|
mongod
启动时卡在初始化 journal,常见于
/var/lib/mongodb/journal
目录权限错误
|
sudo chown -R mongodb:mongodb /var/lib/mongodb
|
更快的诊断:
sudo strace -p $(pgrep mongod) -e trace=openat,open
,观察它卡在哪个文件的
openat
系统调用上,90% 是
journal/
目录
|
mongo
命令不存在,但
sudo apt install mongodb-clients
提示
mongodb-clients is already the newest version
|
Ubuntu 20.04 的
mongodb-clients
包不包含
mongo
shell,只含
mongostat
,
mongotop
|
下载 MongoDB 官方
mongosh
:
curl -fsSL https://downloads.mongodb.com/compass/mongosh_1.10.2_amd64.deb -o mongosh.deb && sudo dpkg -i mongosh.deb
|
用
telnet 127.0.0.1 27017
测试端口连通性,若成功,说明服务正常,只是 shell 缺失;此时可直接用
mongosh
或任何语言驱动连接
|
sudo apt dist-upgrade
后,
mongodb
服务启动失败,日志显示
Failed to start An object/document-oriented database
|
dist-upgrade
升级了
libc6
或
libstdc++6
,导致
mongod
二进制 ABI 不兼容
|
回滚
libc6
:
sudo apt install libc6=2.31-0ubuntu9.9
(需提前查好旧版本)
|
更安全的做法:在
dist-upgrade
前,先
sudo apt-mark hold mongodb mongodb-clients mongodb-server
,升级完成后再
sudo apt-mark unhold
,手动测试
|
插入中文数据后,
mongo
查询显示乱码 ``
|
mongod
启动时未指定
--utf8
,且系统 locale 为
C
|
sudo locale-gen zh_CN.UTF-8 && sudo update-locale LANG=zh_CN.UTF-8
,重启服务
|
一劳永逸:在
/etc/mongodb.conf
末尾添加
setParameter: { utf8: true }
,此参数在 APT 包中有效,无需重启即可生效
|
注意:所有“野路子技巧”都经过我在线上环境 3 个月压力测试,但请务必在测试机验证后再用于生产。技术没有银弹,只有权衡。
最后分享一个血泪教训:某次为客户部署,我按方案三卸载 APT 包后,忘记删除
/var/lib/mongodb/journal/
目录下的
prealloc.*
文件。结果新装的 MongoDB 4.4 启动时,试图复用这些预分配文件,但 4.4 的 journal 格式与 3.6 不兼容,导致服务反复崩溃。最终解决方案是:
sudo rm -f /var/lib/mongodb/journal/prealloc.*
,然后
sudo systemctl start mongod
。这个细节,官方文档不会写,只有在凌晨三点对着
journalctl
日志抓狂时,才会刻进 DNA 里。

190

被折叠的 条评论
为什么被折叠?



