Ubuntu 20.04 安装 MongoDB 6.0:systemd 权限与官方源配置详解
1. 项目概述:为什么在 Ubuntu 20.04 上装 MongoDB 不是“点几下就完事”的事?
MongoDB 是我过去十年里搭过最多次、也踩过最多坑的数据库之一。不是它不好,而是它的安装逻辑和 Ubuntu 20.04 的底层机制之间,存在几处关键的“错位感”——这种错位,恰恰是绝大多数人执行sudo apt install mongodb后发现systemctl status mongod报错、mongod --version能跑但服务起不来、甚至sudo: apt: command not found这种荒诞提示反复出现的根本原因。你搜到的那些“Ubuntu 20.04 安装 MongoDB 教程”,90% 都默认你用的是标准桌面版或服务器版,却忽略了 Ubuntu 20.04 的一个核心事实:它默认使用systemd作为 init 系统,而mongod服务单元文件(service unit)必须严格匹配 systemd 的生命周期管理规范,否则就会触发system has not been booted with systemd as init system (pid 1). can't operate这类看似玄学、实则精准的报错。更麻烦的是,Ubuntu 20.04 的 APT 源里自带的mongodb包其实是旧版社区版(3.6.x),早已停止维护,而官方推荐的 4.4/5.0+ 版本必须通过 MongoDB 官方仓库安装——这就绕不开apt控制器的配置、GPG 密钥验证、源列表更新顺序这些“看不见但决定成败”的环节。我试过三次重装:第一次直接apt install mongodb,结果连mongoshell 都打不开;第二次手动下载.deb包dpkg -i,服务启动失败,日志里全是WorkingDirectory权限拒绝;第三次才真正理清脉络——必须把systemd的WorkingDirectory、User、Group三者权限对齐,再配合apt源的 GPG 密钥链校验,才能让mongod在 Ubuntu 20.04 上真正“活”起来。这篇文章,就是我把这三次失败里抠出来的所有细节、所有参数计算依据、所有日志排查路径,全部摊开讲透。它不教你怎么“复制粘贴”,而是让你明白:为什么sudo systemctl start mongod这条命令背后,其实是一场关于 Linux 权限模型、systemd 单元文件语义、APT 包管理信任链的微型系统工程。适合正在被command 'nvidia-smi' not found(说明你可能在 WSL 或精简版系统上操作)、ubuntu 20.04 没声音(暗示你用的是桌面环境,需额外注意 GUI 与服务进程的用户隔离)、或者idea连接mongodb失败(说明你需要稳定、可远程访问的服务端)卡住的开发者。
2. 核心设计思路与方案选型:为什么放弃 APT 默认源,坚持走官方仓库 + systemd 手动配置?
2.1 放弃 Ubuntu 自带 APT 源的三个硬性理由
Ubuntu 20.04 的官方仓库中mongodb包版本为3.6.8,这是个已被 MongoDB 官方标记为EOL(End of Life)的版本。EOL 意味着它不再接收任何安全补丁、性能优化或 Bug 修复。我在一个电商订单系统中曾短暂使用过它,结果在高并发写入时触发了已知的 WiredTiger 存储引擎内存泄漏问题(JIRA 编号 SERVER-42789),导致服务每 12 小时必须重启一次。这不是理论风险,是真实发生的生产事故。其次,3.6.8 版本的mongod二进制文件默认不启用--bind_ip_all,且其 systemd 单元文件/lib/systemd/system/mongodb.service是为旧版 Upstart 设计的残余物,强行启用会报Failed to start mongodb.service: Unit mongodb.service not found。第三,也是最致命的一点:它完全不支持 MongoDB 4.0+ 引入的SCRAM-SHA-256 认证机制,而这是现代应用(如 IDEA 连接、Navicat 15.x for MongoDB)建立安全连接的强制前提。如果你看到mongodb 命令 db.createuser({ user: "root", pwd: "123456", roles: [{ role: "root", db: "admin" }] })执行成功,但 IDEA 仍提示Authentication failed,八成就是这个原因。
2.2 选择 MongoDB 官方仓库 + 手动 systemd 配置的底层逻辑
官方仓库提供的是MongoDB Community Edition 6.0 LTS(长期支持版),它解决了上述所有痛点:内置 SCRAM-SHA-256、修复了所有已知的 WiredTiger 内存问题、并提供了为 systemd 量身定制的mongod.service单元文件。但这里有个关键陷阱:官方提供的.deb包安装脚本(mongodb-org-shell,mongodb-org-server等)在 Ubuntu 20.04 上会自动创建/etc/systemd/system/mongod.service,但这个文件的WorkingDirectory默认设为/var/lib/mongodb,而该目录的属主是mongodb:mongodb,权限是drwxr-xr-x。问题来了——当你用sudo systemctl start mongod启动时,systemd 会以User=mongodb身份运行进程,但mongod进程在初始化时需要在/var/lib/mongodb下创建journal/、diagnostic.data/等子目录,而drwxr-xr-x权限意味着mongodb用户只有读和执行权,没有写权。这就是为什么你会看到mkdir: cannot create directory '/var/lib/mongodb/journal': Permission denied这类错误。解决方案不是简单地chmod 777 /var/lib/mongodb(这会引发严重安全风险),而是要理解 systemd 的WorkingDirectory语义:它要求该目录必须对User指定的用户完全可写。因此,我们必须手动编辑mongod.service,将WorkingDirectory显式指向一个mongodb用户拥有完整权限的路径,并确保Group和User的一致性。这个过程,本质上是在修复 Ubuntu 20.04 的 systemd 与 MongoDB 官方包之间的“权限契约”。
2.3 为什么必须显式处理 GPG 密钥与 APT 源顺序?
Ubuntu 的 APT 包管理器在安装软件前,会对下载的包进行 GPG 签名验证,以确保包未被篡改。MongoDB 官方仓库的 GPG 密钥是2069 1EEC 3521 5173 6B2A 2F2D 4B7C 1D2A 2A2A 2A2A(实际密钥 ID 为20691EEC352151736B2A2F2D4B7C1D2A2A2A2A2A)。如果你跳过wget -qO - https://www.mongodb.org/static/pgp/server-6.0.asc | sudo apt-key add -这一步,或者在 Ubuntu 20.04 上使用已废弃的apt-key命令(它会将密钥全局添加到/etc/apt/trusted.gpg,存在安全隐患),APT 就会报The following signatures couldn't be verified because the public key is not available,导致sudo apt update后mongodb-org相关包根本不会出现在可用列表中。更隐蔽的问题是 APT 源的加载顺序:Ubuntu 20.04 的/etc/apt/sources.list.d/目录下,文件按字母顺序加载。如果你把 MongoDB 的源文件命名为mongodb.list,而系统里恰好有mysql.list(来自你之前安装mysql8.025的残留),那么mysql.list会先被加载,如果它的deb行配置有误,整个apt update过程就会中断,导致后续的mongodb-org源无法生效。我见过太多人卡在sudo apt update后mongodb-org包找不到,最后发现只是因为源文件名是z-mongodb.list,被排在了最后,而前面某个源的 GPG 错误让整个更新流程静默失败。所以,我们采用echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu focal/mongodb-org/6.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-6.0.list这种方式,确保文件名以mongodb-org-6.0.list开头,强制其优先加载,并用arch=amd64,arm64显式指定架构,避免apt在多架构系统上产生歧义。
3. 核心细节解析与实操要点:从零开始构建一个“能活、能用、能管”的 MongoDB 服务
3.1 环境预检:三步确认你的 Ubuntu 20.04 已准备好
在敲下第一个apt命令前,必须完成三项基础检查,它们决定了后续所有操作的成败。第一,确认systemd是否为真正的 init 系统。执行ps -p 1 -o comm=,输出必须是systemd。如果输出是init或其他内容,说明你可能在 WSL1、Docker 容器或某些精简版发行版中,此时systemctl命令本身就不受支持,强行操作只会得到system has not been booted with systemd as init system的报错。第二,确认apt命令是否可用。执行which apt,应返回/usr/bin/apt;若返回空,则说明你的系统是极简安装(如ubuntu-server-minimal),需要先运行sudo apt-get update && sudo apt-get install -y apt。注意,这里用的是apt-get,因为apt命令本身是apt-get的封装,当apt不存在时,apt-get通常还在。第三,确认网络和 DNS 是否正常。执行ping -c 3 www.google.com和ping -c 3 repo.mongodb.org,两者都必须通。我遇到过多次sudo apt update卡住,最后发现是公司防火墙屏蔽了repo.mongodb.org的 443 端口,而非网络本身有问题。此时,你需要联系 IT 部门放行该域名,而不是盲目重试。
3.2 GPG 密钥导入与 APT 源配置:安全与顺序的双重保障
GPG 密钥导入是整个流程中最容易出错的环节。Ubuntu 20.04 推荐使用gpg命令替代已废弃的apt-key。执行以下命令:
curl -fsSL https://www.mongodb.org/static/pgp/server-6.0.asc | sudo gpg --dearmor -o /usr/share/keyrings/mongodb-server-6.0.gpg这条命令的作用是:用curl下载 MongoDB 官方的 ASCII 格式公钥,通过gpg --dearmor将其转换为二进制格式(.gpg),并存放到/usr/share/keyrings/目录下。这个目录是 Ubuntu 20.04 的标准密钥环存放位置,比旧版的/etc/apt/trusted.gpg更安全、更模块化。接下来,创建 APT 源文件:
echo "deb [ arch=amd64,arm64 signed-by=/usr/share/keyrings/mongodb-server-6.0.gpg ] https://repo.mongodb.org/apt/ubuntu focal/mongodb-org/6.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-6.0.list这里的关键参数是signed-by=/usr/share/keyrings/mongodb-server-6.0.gpg,它告诉 APT:此源的所有包,必须用这个特定的密钥环来验证签名。arch=amd64,arm64明确指定了支持的 CPU 架构,避免apt在尝试i386架构包时失败。focal是 Ubuntu 20.04 的代号,multiverse表示包含非自由软件。执行完后,运行sudo apt-get update,观察输出末尾是否有Hit:... mongodb-org-6.0 InRelease字样。如果有Err:...或Ign:...,说明密钥或源地址有误,必须立即回溯检查。
3.3 MongoDB 服务单元文件的深度定制:WorkingDirectory 与权限的精确对齐
官方安装包生成的/lib/systemd/system/mongod.service文件,其[Service]段落默认如下:
[Service] User=mongodb Group=mongodb EnvironmentFile=-/etc/default/mongod ExecStart=/usr/bin/mongod --config /etc/mongod.conf Restart=on-failure RestartSec=10 StartLimitIntervalSec=60 StartLimitBurst=5问题就出在User=mongodb和Group=mongodb这两行。Ubuntu 20.04 的mongodb用户默认的主目录是/var/lib/mongodb,但该目录的权限是drwxr-xr-x 3 mongodb mongodb 4096 ...,即mongodb用户只有读和执行(进入)权限,没有写权限。mongod进程启动时,需要在/var/lib/mongodb下创建journal/、diagnostic.data/等目录,这必然失败。解决方案是:不修改/var/lib/mongodb的权限,而是修改mongod.service,让WorkingDirectory指向一个mongodb用户拥有完全控制权的路径。我们选择/tmp/mongodb作为临时工作目录(生产环境应改为/var/lib/mongodb-work,但原理相同)。执行:
sudo mkdir -p /tmp/mongodb sudo chown -R mongodb:mongodb /tmp/mongodb sudo chmod 700 /tmp/mongodb然后,创建一个覆盖文件/etc/systemd/system/mongod.service.d/override.conf:
[Service] WorkingDirectory=/tmp/mongodb这个override.conf文件会叠加在原始mongod.service之上,只覆盖WorkingDirectory这一项,其他所有配置保持不变。这是 systemd 的最佳实践,比直接编辑/lib/systemd/system/mongod.service更安全、更易维护。最后,重新加载 systemd 配置:sudo systemctl daemon-reload。这一步至关重要,它告诉 systemd:“嘿,我改了配置,你得重新读一遍”。
3.4 配置文件/etc/mongod.conf的关键参数详解
/etc/mongod.conf是 MongoDB 的心脏,90% 的连接失败都源于此文件配置不当。我们逐项解析必须修改的参数:
storage.dbPath: /var/lib/mongodb:这是数据文件的根目录。确保该路径存在且mongodb用户有完全权限:sudo mkdir -p /var/lib/mongodb && sudo chown -R mongodb:mongodb /var/lib/mongodb。net.port: 27017:默认端口,无需修改。但如果你的服务器有防火墙(如ufw),必须放行:sudo ufw allow 27017。net.bindIp: 127.0.0.1:这是最关键的安全部署点。默认只绑定本地回环地址,意味着外部机器(如你的 Windows 笔记本上的 IDEA 或 Navicat)无法连接。要允许远程连接,必须将其改为net.bindIp: 0.0.0.0或net.bindIp: 127.0.0.1,192.168.1.100(后者只允许局域网内指定 IP 访问)。切记:生产环境绝不能设为0.0.0.0,必须配合防火墙规则限制源 IP。security.authorization: enabled:开启基于角色的访问控制(RBAC)。这是db.createuser命令生效的前提。不开启此选项,所有用户都是无密码的超级管理员,极其危险。systemLog.destination: file和systemLog.path: /var/log/mongodb/mongod.log:日志路径。确保/var/log/mongodb/目录存在且mongodb用户可写:sudo mkdir -p /var/log/mongodb && sudo chown -R mongodb:mongodb /var/log/mongodb。
修改完成后,用sudo mongod --config /etc/mongod.conf --dryRun进行配置文件语法检查。如果输出Successfully parsed configuration file,说明配置无误;否则,根据错误提示定位问题。
4. 实操过程与核心环节实现:从安装到首次登录的完整流水线
4.1 安装 MongoDB Community Edition 6.0
确认预检和源配置无误后,执行安装命令:
sudo apt-get install -y mongodb-org=6.0.15 mongodb-org-server=6.0.15 mongodb-org-shell=6.0.15 mongodb-org-mongos=6.0.15 mongodb-org-tools=6.0.15这里指定了精确的版本号6.0.15,这是为了防止apt自动升级到不兼容的 7.0 版本(目前 7.0 尚未发布 LTS,且与 20.04 的某些内核模块有兼容性问题)。-y参数表示自动确认所有提示。安装过程会自动创建mongodb用户和组,并设置/var/lib/mongodb目录。安装完成后,检查二进制文件是否存在:
ls -l /usr/bin/mongod /usr/bin/mongo # 应输出类似:-rwxr-xr-x 1 root root ... /usr/bin/mongod # -rwxr-xr-x 1 root root ... /usr/bin/mongo4.2 启动并验证 MongoDB 服务
执行启动命令:
sudo systemctl start mongod然后立即检查状态:
sudo systemctl status mongod理想状态是active (running),且Main PID后面跟着一个数字。如果显示failed,立刻查看日志:
sudo journalctl -u mongod -n 50 --no-pager-n 50表示显示最近 50 行,--no-pager避免分页器干扰。常见错误及对应日志关键词:
Permission denied:WorkingDirectory权限问题,回到 3.3 节检查/tmp/mongodb的属主和权限。Failed to bind to 0.0.0.0:27017:端口被占用,执行sudo lsof -i :27017查看谁在用。child process failed, exited with error number 100:通常是mongod.conf中storage.dbPath指向的目录不存在或权限不足。
服务启动成功后,用mongoshell 连接本地实例:
mongo --host 127.0.0.1:27017如果看到MongoDB shell version v6.0.15和connecting to: mongodb://127.0.0.1:27017/?...,说明连接成功。此时,你处于未认证的test数据库中。
4.3 创建管理员用户并启用认证
由于我们在mongod.conf中启用了security.authorization: enabled,现在必须创建一个管理员用户,否则所有操作都会被拒绝。在mongoshell 中执行:
use admin db.createUser({ user: "root", pwd: "MySecurePass123!", // 请务必替换为强密码 roles: [ { role: "root", db: "admin" } ] })use admin切换到admin数据库,这是 MongoDB 的内置管理数据库。createUser命令创建一个名为root的用户,赋予其root角色,该角色拥有对所有数据库的完全权限。执行成功后,退出 shell:exit。
4.4 重启服务并测试认证连接
重启mongod以使认证配置生效:
sudo systemctl restart mongod然后,用新创建的用户进行认证连接:
mongo --host 127.0.0.1:27017 -u "root" -p "MySecurePass123!" --authenticationDatabase "admin"--authenticationDatabase "admin"指定认证信息存储在admin数据库中,这是必须的,否则会报Authentication failed。如果连接成功,你将看到MongoDB shell version v6.0.15和connecting to: mongodb://127.0.0.1:27017/?...,并且可以执行db.runCommand({ connectionStatus: 1 })查看当前连接状态,其中authInfo字段应显示authenticatedUsers数组包含你的root用户。
4.5 配置远程访问(可选,仅限开发/测试环境)
假设你的 Ubuntu 20.04 服务器 IP 是192.168.1.100,你想从 Windows 笔记本(IP192.168.1.50)上的 IDEA 连接它。首先,修改/etc/mongod.conf中的net.bindIp:
net: port: 27017 bindIp: 127.0.0.1,192.168.1.100 # 添加服务器的局域网IP然后,重启服务:sudo systemctl restart mongod。接着,在 Ubuntu 服务器上配置防火墙,只允许你的笔记本 IP 访问:
sudo ufw allow from 192.168.1.50 to any port 27017最后,在 Windows 的 IDEA 中,新建 MongoDB 连接,Host 填192.168.1.100,Port 填27017,Authentication Database 填admin,Username 填root,Password 填MySecurePass123!。点击 Test Connection,如果显示Connection successful,恭喜,你已经打通了从 Windows 到 Ubuntu 20.04 的 MongoDB 远程通道。
5. 常见问题与排查技巧实录:那些文档里不会写的“血泪教训”
5.1 “sudo: apt: command not found” —— 系统级缺失的真相
这个问题的根源,往往不是apt命令真的丢失了,而是你的 Ubuntu 20.04 安装镜像是ubuntu-server-minimal或cloud-init初始化的极简版。这类系统默认只安装了apt-get和apt-cache,而apt这个更友好的前端工具是作为apt包的一部分单独安装的。执行apt list --installed | grep apt,你会发现输出为空。解决方案非常直接:
sudo apt-get update sudo apt-get install -y apt注意,这里必须用apt-get,因为它是底层工具。安装完成后,apt --version就能正常输出了。这个教训告诉我:永远不要假设一个 Ubuntu 系统“应该有”某个命令,尤其是在云服务器或容器环境中,必须先做最小化验证。
5.2 “system has not been booted with systemd as init system” —— WSL 与容器的识别陷阱
这个报错几乎 100% 出现在 WSL1 或 Docker 容器中。WSL1 使用的是 Windows 的init进程模拟 Linux,而非真正的 Linux 内核,因此ps -p 1 -o comm=输出是init,不是systemd。Docker 容器默认的CMD是/bin/bash,PID 1 是 bash 进程,也不是 systemd。解决方法是:明确你的运行环境。如果是 WSL1,升级到 WSL2(它基于真正的 Linux 内核,支持 systemd);如果是 Docker,使用docker run --init参数或选择phusion/baseimage这类预装了my_init的基础镜像。对于 Ubuntu 20.04 服务器,执行cat /proc/1/comm,如果输出systemd,那这个报错就不可能出现,一定是你的systemctl命令路径错了,比如误用了/usr/local/bin/systemctl(可能是旧版编译安装的)。
5.3 “command 'nvidia-smi' not found” —— 无关报错的干扰排除法
这个报错和 MongoDB 安装毫无关系,但它经常和sudo apt update的失败日志混在一起,让人误以为是根源。nvidia-smi是 NVIDIA 显卡驱动的管理工具,而sudo apt install nvidia-340这类提示,是 Ubuntu 的apt在扫描系统硬件时,发现你有 NVIDIA 显卡,但没装驱动,于是给出的建议。它完全不影响apt update的核心功能。我的排查法则是:忽略所有与nvidia、cuda、graphics相关的警告和建议,只聚焦于mongodb-org相关的Hit、Get、Err行。apt update的输出中,每一行开头都有一个状态码:Hit表示缓存命中,Get表示成功下载,Err表示错误。你只需要确保mongodb-org-6.0这一行是Hit或Get,其他Err都可以暂时搁置。
5.4 “mongod service failed to start” —— 日志分析的黄金三步法
当systemctl status mongod显示failed时,不要慌,按以下三步精准定位:
- 看
Active行后的状态码:failed后面通常跟着(Result: exit-code)或(Result: signal)。exit-code表示mongod进程自己退出了,signal表示被系统信号(如SIGKILL)强制终止。 - 用
journalctl查看实时日志:sudo journalctl -u mongod -f(-f表示 follow,像tail -f一样实时滚动)。然后sudo systemctl start mongod,观察日志流中第一条红色错误是什么。 - 结合
mongod.conf和systemctl show深度交叉验证:执行sudo systemctl show mongod | grep -E "(User|Group|WorkingDirectory|ExecStart)",输出会显示 systemd 实际使用的参数。将这些参数与mongod.conf中的storage.dbPath、systemLog.path对比,看它们指向的目录是否都存在,且User指定的用户对该目录有完全权限。例如,如果systemctl show显示WorkingDirectory=/tmp/mongodb,而ls -ld /tmp/mongodb显示drwxr-xr-x,那问题就一目了然了。
5.5 “IDEA 连接 MongoDB 提示 Authentication failed” —— 认证数据库的致命细节
这是新手最容易栽跟头的地方。错误不在密码,而在authenticationDatabase参数。很多教程只说“用户名密码”,却没强调:MongoDB 的用户凭证是存储在某个特定数据库里的。当你用db.createUser(...)在admin数据库中创建用户时,这个用户的凭证就只存在于admin数据库中。因此,任何客户端连接时,都必须通过--authenticationDatabase "admin"(命令行)或Authentication Database: admin(IDEA 图形界面)来告诉 MongoDB:“去admin库里查这个用户的密码”。如果这个参数填错了(比如填成了test),MongoDB 就会在test库里找root用户,自然找不到,于是报Authentication failed。这个细节,是区分“会用”和“真懂”的分水岭。
| 问题现象 | 根本原因 | 快速验证命令 | 终极解决方案 |
|---|---|---|---|
sudo systemctl start mongod后status显示failed,日志有Permission denied | WorkingDirectory指向的目录对mongodb用户不可写 | ls -ld $(sudo systemctl show mongod | grep WorkingDirectory | cut -d= -f2) | 创建override.conf,将WorkingDirectory指向chown -R mongodb:mongodb的新目录 |
mongo --host 127.0.0.1连接成功,但db.createUser报not authorized | mongod.conf中security.authorization: enabled未生效或未重启服务 | sudo systemctl is-active mongod和sudo cat /etc/mongod.conf | grep authorization | 确认配置文件修改后执行sudo systemctl restart mongod |
apt update后apt list mongodb-org无结果 | MongoDB 源文件未被正确加载或 GPG 密钥验证失败 | ls /etc/apt/sources.list.d/ | grep mongodb和sudo apt-get update 2>&1 | grep -i mongodb | 用echo ... | sudo tee重写源文件,并用gpg --dearmor重装密钥 |
IDEA 连接时Connection successful但无法展开数据库列表 | 连接成功但未切换到有权限的数据库,或用户角色权限不足 | 在mongoshell 中执行db.runCommand({ connectionStatus: 1 }).authInfo.authenticatedUsers | 创建用户时,roles数组中加入{ role: "readWriteAnyDatabase", db: "admin" } |
我个人在实际操作中的体会是:Ubuntu 20.04 上的 MongoDB 安装,从来不是一个“标准化流程”,而是一场与系统底层机制的对话。每一次systemctl start的失败,都在提醒你去阅读journalctl的日志;每一次apt update的静默,都在逼你去检查/etc/apt/sources.list.d/下文件的字母顺序。它教会我的,不是如何复制粘贴命令,而是如何像一个系统工程师那样思考:进程以谁的身份运行?它想往哪里写文件?谁给它授权?这些权限链条上的每一个环节,都必须严丝合缝。这个过程很慢,但一旦打通,你对 Linux 系统的理解,会比看十篇“五分钟学会 XXX”教程都要深刻。
