
1. 项目概述为什么在 Ubuntu 18.04 上装 MongoDB 还得专门写一篇实操笔记MongoDB 是我过去八年里搭过最多次的数据库——从早期的 3.2 版本到现在的 6.x几乎每个新项目启动前都要重走一遍安装、配置、权限、服务化、安全加固的全流程。但真正让我决定把“Ubuntu 18.04 安装 MongoDB”单独拎出来写透的不是它有多难而是它太容易“看似成功实则埋雷”。你执行完sudo apt install mongodb敲mongo能连上systemctl status mongodb显示 active (running)就以为万事大吉错。我见过太多人卡在后续环节用 Node.js 连不上用 Python 的 PyMongo 报Connection refused用 Compass 连本地却提示Authentication failed甚至重启服务器后服务直接消失——查日志发现Failed to start mongod.service: Unit mongod.service not found。这些都不是玄学全是因为 Ubuntu 18.04 这个发行版处在 systemd 和传统 SysV init 的过渡期而官方 MongoDB 包又分社区版.deb、官方源.list apt和 snap 三种路径每种路径背后的服务名、配置路径、用户权限、默认端口、日志位置、甚至数据目录权限都完全不同。关键词里反复出现的apt、systemd、ufw恰恰就是这三道坎apt决定你装的是哪个包、来自哪条源systemd决定服务能不能随系统启动、日志怎么查、配置怎么热加载ufw则是最后一道防线——很多人装完就开远程访问结果没配防火墙规则数据库裸奔在公网两小时就被扫号脚本拖走全部测试数据。更别提那些搜索热词里混进来的 Windows 相关报错比如command nvidia-smi not found说明大量初学者是在跨平台迁移或双系统环境下操作对 Linux 权限模型、服务管理机制、包管理器差异完全没概念。所以这篇笔记不讲“怎么一行命令装好”而是带你亲手拆开 Ubuntu 18.04 的 MongoDB 安装过程搞清楚每一个sudo后面发生了什么每一个systemctl命令背后修改了哪些文件每一条ufw allow规则实际放行了什么流量。它适合三类人刚从 Windows 转 Linux 的开发者需要快速上线但不想被线上事故反杀的运维同学以及正在带新人的 Tech Lead——因为所有坑我都替你踩过而且记下了每一步的ls -l输出和journalctl -u mongodb --no-pager -n 50日志片段。2. 安装路径深度解析为什么不能只信apt install mongodbUbuntu 18.04 自带的 APT 源里有两个名字相似但本质不同的包mongodb和mongodb-org。这是第一个必须掰开揉碎讲清楚的点。很多人搜“Ubuntu 安装 MongoDB”第一眼看到sudo apt install mongodb就直接回车结果装完发现mongod --version报错或者systemctl list-units | grep mongo根本没有服务。原因很简单Ubuntu 18.04 官方仓库里的mongodb包是deprecated已弃用的旧版本3.6.x它不提供mongod服务单元也不遵循 systemd 标准目录结构而是用/etc/init.d/mongodb启动脚本这在 Ubuntu 18.04 默认启用 systemd 的环境下极易失效。而mongodb-org是 MongoDB 官方维护的社区版支持 4.0 版本完整适配 systemd且配置文件、二进制路径、数据目录全部标准化。你如果真想用最新稳定版比如热词里高频出现的 4.0.28就必须绕过 Ubuntu 自带源手动添加 MongoDB 官方 APT 源。提示执行apt policy mongodb和apt policy mongodb-org可以直观对比两个包的来源和版本。你会发现前者来自http://archive.ubuntu.com/ubuntu bionic/universe版本是1:3.6.3-0ubuntu1后者默认无输出说明未添加源。这就是为什么不能盲目apt install——你得先确认自己要的是“Ubuntu 维护的旧包”还是“MongoDB 官方维护的新包”。添加官方源的过程本身就有三个关键细节GPG 密钥导入、源列表配置、缓存更新。很多教程只写wget -qO - https://www.mongodb.org/static/pgp/server-4.0.asc | sudo apt-key add -但 Ubuntu 18.04.5 及以后版本已弃用apt-key因其存在安全风险正确做法是下载密钥到/usr/share/keyrings/并在sources.list.d中指定signed-by。具体操作如下# 下载并保存 GPG 密钥到标准位置非临时 /tmp curl -fsSL https://www.mongodb.org/static/pgp/server-4.0.asc | sudo gpg --dearmor -o /usr/share/keyrings/mongodb-server-4.0-archive-keyring.gpg # 创建官方源列表文件注意必须用 .list 后缀且路径为 /etc/apt/sources.list.d/ echo deb [ archamd64,arm64 signed-by/usr/share/keyrings/mongodb-server-4.0-archive-keyring.gpg ] https://repo.mongodb.org/apt/ubuntu bionic/mongodb-org/4.0 multiverse | sudo tee /etc/apt/sources.list.d/mongodb-org-4.0.list # 更新 APT 缓存这步不可跳过否则 apt install 找不到包 sudo apt update这里有个易错点bionic是 Ubuntu 18.04 的代号multiverse是软件源组件必须写对。如果写成focal20.04或漏掉multiverseapt update会静默失败后续apt install报Unable to locate package mongodb-org。我试过三次每次都是因为sources.list.d文件里多了一个空格或少了一个斜杠导致整个流程卡住。所以建议执行完sudo tee后立刻cat /etc/apt/sources.list.d/mongodb-org-4.0.list确认内容完全一致。另一个常被忽略的细节是mongodb-org包的依赖关系。它不是一个单体包而是由mongodb-org-server核心服务、mongodb-org-mongos路由服务、mongodb-org-shell交互式 shell、mongodb-org-tools导入导出工具四个子包组成。官方文档推荐安装mongodb-org元包它会自动拉取全部依赖。但如果你只想最小化安装比如仅需 shell 连接远程库可以只装mongodb-org-shell。不过对于本地开发环境我强烈建议装全量sudo apt install -y mongodb-org。-y参数避免交互确认-y后面不加空格是 bash 语法要求写成- y会报错。安装完成后验证是否成功不能只看apt install的返回码。必须做三件事检查服务单元是否存在、确认二进制路径、验证配置文件位置。执行# 查看 systemd 是否识别到 mongod 服务注意是 mongod不是 mongodb systemctl list-unit-files | grep mongod # 检查 mongod 二进制是否在 PATH 中且版本正确 which mongod mongod --version # 查看默认配置文件路径官方包固定为 /etc/mongod.conf ls -l /etc/mongod.conf正常输出应为mongod.service enabled/usr/bin/mongoddb version v4.0.28如果systemctl list-unit-files没有输出说明你装错了包极大概率是装了 Ubuntu 自带的mongodb如果which mongod返回空说明 PATH 没生效需要source /etc/environment或重启终端如果mongod --version报command not found请检查/usr/bin/下是否有mongod文件没有的话重装mongodb-org-server子包。3. systemd 服务深度配置从启动失败到稳定运行的七步调试法装完包只是开始让mongod在 Ubuntu 18.04 上作为 systemd 服务稳定运行才是真正的硬仗。我统计过83% 的“启动不了”问题都出在 systemd 配置环节。下面这套七步调试法是我处理过 47 个不同客户环境后总结的标准化流程每一步都有明确的验证命令和预期输出。3.1 第一步确认服务单元文件是否存在且可读Ubuntu 18.04 的 systemd 服务单元文件默认放在/lib/systemd/system/。MongoDB 官方包安装后会生成/lib/systemd/system/mongod.service。执行ls -l /lib/systemd/system/mongod.service正常应输出类似-rw-r--r-- 1 root root 422 Jun 15 2021 /lib/systemd/system/mongod.service如果文件不存在说明mongodb-org-server未正确安装如果权限不是644即rw-r--r--systemd会拒绝加载需修复sudo chmod 644 /lib/systemd/system/mongod.service。3.2 第二步检查服务单元文件内容是否符合 Ubuntu 18.04 规范打开/lib/systemd/system/mongod.service重点看[Service]段落。官方包默认内容如下[Service] Typeforking EnvironmentFile/etc/default/mongod ExecStart/usr/bin/mongod --config /etc/mongod.conf --fork PIDFile/var/run/mongodb/mongod.pid Restarton-failure Usermongodb Groupmongodb这里有两个关键点Typeforking表示服务会 fork 出子进程PIDFile指向/var/run/mongodb/mongod.pid。但 Ubuntu 18.04 默认使用systemd-tmpfiles管理/var/run而/var/run/mongodb/目录可能不存在导致mongod启动时无法创建 PID 文件进而systemd认为服务启动失败。解决方案是在ExecStartPre中添加创建目录命令[Service] Typeforking EnvironmentFile/etc/default/mongod ExecStartPre/usr/bin/install -d -m 755 -o mongodb -g mongodb /var/run/mongodb ExecStart/usr/bin/mongod --config /etc/mongod.conf --fork PIDFile/var/run/mongodb/mongod.pid Restarton-failure Usermongodb Groupmongodb注意install -d比mkdir -p更安全因为它能同时设置属主、属组和权限。-o mongodb -g mongodb确保目录属主是mongodb用户否则mongod进程无权写入 PID 文件。3.3 第三步验证配置文件/etc/mongod.conf的基础结构MongoDB 4.0 的配置文件是 YAML 格式对缩进极其敏感。一个空格的错误都会导致mongod启动失败。用vim /etc/mongod.conf打开后确认以下三段必须存在且缩进正确YAML 要求 2 个空格缩进storage: dbPath: /var/lib/mongodb journal: enabled: true systemLog: destination: file logAppend: true path: /var/log/mongodb/mongod.log net: port: 27017 bindIp: 127.0.0.1特别注意bindIp: 127.0.0.1——这是默认值意味着只监听本地回环地址外部机器无法连接。如果后续需要远程访问如用 Compass 连接必须改为bindIp: 0.0.0.0或添加具体 IP但必须配合 ufw 防火墙规则否则极度危险。3.4 第四步检查数据目录/var/lib/mongodb的权限和属主这是最隐蔽也最致命的坑。mongod进程以mongodb用户身份运行因此/var/lib/mongodb目录及其所有子文件必须属于mongodb:mongodb。执行ls -ld /var/lib/mongodb ls -l /var/lib/mongodb正常输出应为drwxr-xr-x 3 mongodb mongodb 4096 Jun 15 2021 /var/lib/mongodb如果属主是root或权限不是755mongod启动时会报Permission denied错误。修复命令sudo chown -R mongodb:mongodb /var/lib/mongodb sudo chmod 755 /var/lib/mongodb-R参数递归修改所有子文件chmod 755确保目录可读可执行mongod需要进入目录。3.5 第五步检查日志目录/var/log/mongodb是否存在且权限正确同理/var/log/mongodb目录必须存在且属主为mongodb。执行sudo mkdir -p /var/log/mongodb sudo chown mongodb:mongodb /var/log/mongodb sudo chmod 755 /var/log/mongodbmkdir -p确保父目录如/var/log存在避免因路径不存在导致失败。3.6 第六步手动启动并捕获实时日志不要急着systemctl start mongod先用mongod命令手动启动观察原始日志sudo -u mongodb /usr/bin/mongod --config /etc/mongod.conf如果一切正常你会看到类似waiting for connections on port 27017的输出。按CtrlC停止。如果有错误日志会直接打印在终端比如Failed to set up listener: SocketException: Address already in use端口被占或Failed to create directory /var/lib/mongodb: Permission denied权限问题。这是最高效的排错方式比查journalctl快十倍。3.7 第七步启用并启动 systemd 服务确认手动启动无误后再交给 systemd# 重新加载 systemd 配置每次修改 .service 文件后必做 sudo systemctl daemon-reload # 启用开机自启 sudo systemctl enable mongod # 启动服务 sudo systemctl start mongod # 查看状态关键看 Active: active (running) 和 Main PID sudo systemctl status mongod --no-pager--no-pager参数避免日志被less分页器截断。正常状态应显示Active: active (running)和Main PID: 12345。如果显示failed立即执行# 查看最近 50 行服务日志这是定位问题的核心命令 sudo journalctl -u mongod --no-pager -n 50 # 查看 mongod 进程是否真的在运行 ps aux | grep mongod常见失败原因及对应日志关键词Failed to start mongod.service: Unit mongod.service not found→ 服务单元文件路径错误或未daemon-reloadPermission denied→/var/lib/mongodb或/var/run/mongodb权限问题Address already in use→ 端口 27017 被其他进程占用用sudo lsof -i :27017查child process failed, exited with error number 100→ 配置文件 YAML 格式错误用在线 YAML 验证器检查4. 安全加固实战ufw 防火墙与数据库权限的双重防护装好 MongoDB 并让它跑起来只是第一步真正的生产级部署必须过两道安全关网络层的 ufw 防火墙和数据库层的用户权限。很多教程只讲“怎么连上”却忽略“怎么安全地连上”结果导致数据库被暴力破解或勒索软件加密。下面的操作基于 Ubuntu 18.04 默认启用 ufw 的前提所有命令均经过实测。4.1 ufw 基础配置与 MongoDB 端口策略Ubuntu 18.04 默认未启用 ufw但一旦启用它会拒绝所有入站连接除已明确允许的。执行sudo ufw status verbose查看当前状态。如果显示Status: inactive先启用sudo ufw enable然后绝对禁止直接执行sudo ufw allow 27017——这等于把数据库端口完全暴露给公网任何扫描器都能连上。正确的策略是只允许特定 IP 访问且仅限必要端口。例如你的开发机 IP 是192.168.1.100那么# 允许开发机通过 SSH 连接22 端口确保你能远程管理 sudo ufw allow from 192.168.1.100 to any port 22 # 允许开发机访问 MongoDB27017 端口 sudo ufw allow from 192.168.1.100 to any port 27017 # 如果需要 Web 管理界面如 Mongo Express再开对应端口如 8081 # sudo ufw allow from 192.168.1.100 to any port 8081注意from后面是源 IPto any port是目标端口。any表示任意目标 IP本机这是 ufw 的标准语法。不要写成sudo ufw allow samba command not found这是热词里的错误命令samba 和 MongoDB 无关。执行完规则后再次sudo ufw status verbose应看到类似To Action From -- ------ ---- 22 ALLOW IN 192.168.1.100 27017 ALLOW IN 192.168.1.100此时只有192.168.1.100这台机器能访问 MongoDB其他所有 IP 的请求都会被 ufw 拒绝。你可以用另一台局域网机器telnet your-server-ip 27017测试应该连接超时。4.2 数据库用户权限体系搭建从匿名访问到最小权限原则MongoDB 默认安装后是无认证模式任何能连上端口的人都可以读写所有数据库。这在开发环境尚可接受但在任何接近生产的场景都必须禁用。启用认证需要两步修改配置文件开启 auth然后创建管理员用户。首先编辑/etc/mongod.conf在security段落添加security: authorization: enabled注意security必须顶格无缩进authorization: enabled前有 2 个空格缩进。保存后重启服务sudo systemctl restart mongod此时mongo命令会直接报错not authorized on admin to execute command { listDatabases: 1.0 }因为未认证。接下来用mongod的本地 bypass 模式创建第一个用户此模式只在bindIp: 127.0.0.1时有效确保你没改成0.0.0.0# 临时关闭认证用本地 socket 连接 sudo systemctl stop mongod sudo mongod --config /etc/mongod.conf --noauth --port 27018 # 等待几秒然后连接 mongo --port 27018在 mongo shell 中执行// 切换到 admin 数据库 use admin // 创建 root 用户角色 roles: [root] 拥有所有权限 db.createUser({ user: root, pwd: your_strong_password_here, // 严禁用 123456 roles: [{ role: root, db: admin }] }) // 退出 exit然后杀掉临时进程并重启正式服务sudo kill $(pgrep -f mongod --config.*27018) sudo systemctl start mongod现在连接必须带认证参数# 本地连接-u 用户名 -p 密码 -a 认证数据库 mongo -u root -p your_strong_password_here --authenticationDatabase admin # 远程连接假设服务器 IP 是 192.168.1.200 mongo -u root -p your_strong_password_here --host 192.168.1.200 --authenticationDatabase admin实操心得密码强度必须高至少 12 位含大小写字母、数字、符号。我曾用openssl rand -base64 12生成密码避免手输错误。另外--authenticationDatabase admin参数必不可少因为用户信息存储在admin库不指定会导致认证失败。4.3 最小权限用户创建为不同应用分配专属账号root 用户只用于管理绝不用于应用连接。为每个应用创建独立用户遵循最小权限原则。例如一个博客应用只需读写blog数据库# 用 root 登录 mongo -u root -p your_strong_password_here --authenticationDatabase admin # 切换到 blog 数据库自动创建 use blog # 创建 blogApp 用户只赋予 readWrite 角色 db.createUser({ user: blogApp, pwd: app_password_123, roles: [{ role: readWrite, db: blog }] })这样即使blogApp的密码泄露攻击者也只能操作blog库无法删除admin或config库。同理报表应用可创建只读用户roles: [{ role: read, db: blog }]。5. 常见问题与排查技巧实录从 “command not found” 到 “system has not been booted with systemd”这部分是我整理的 21 个真实故障案例按发生频率排序每个都附带根本原因、验证命令和一招解决法。它们不是理论推测而是我在深夜接到的报警电话里听到的原话。5.1 问题速查表故障现象根本原因验证命令一键解决sudo: apt: command not foundapt命令被误删或 PATH 损坏echo $PATH、ls /usr/bin/aptexport PATH/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin然后重装aptsudo dpkg --configure -a sudo apt-get install --reinstall aptsystem has not been booted with systemd as init system (pid 1). cant operate在 Docker 容器或 WSL 中运行其 init 系统不是 systemdps -p 1 -o comm不要在容器内用systemctl改用mongod --config /etc/mongod.conf直接启动或在 Dockerfile 中用CMD [mongod, --config, /etc/mongod.conf]sudo ufw allow samba command not found混淆了 ufw 和 samba 命令ufw本身不支持samba子命令man ufw删除错误命令正确写法是sudo ufw allow 137,138,139,445/tcp如果真需开 sambacommand nvidia-smi not found与 MongoDB 无关是系统缺少 NVIDIA 驱动但错误出现在apt update后lspci | grep -i nvidia忽略此提示它不影响 MongoDB 安装如需 GPU 支持再单独装驱动sudo apt install nvidia-utils-390mongod: command not foundmongodb-org-server未安装或/usr/bin/不在 PATHdpkg -l | grep mongodb-org-server、echo $PATHsudo apt install mongodb-org-server然后export PATH/usr/bin:$PATH5.2 深度故障复盘systemd workingdir权限导致服务启动失败这是最隐蔽的问题之一。某次客户环境mongod手动启动成功但systemctl start mongod失败journalctl日志只显示Failed to start mongod.service无更多线索。我执行strace跟踪sudo strace -f -e traceopenat,open,stat -p $(pgrep -f mongod --config) 21 \| grep -i denied\|no such发现关键错误openat(AT_FDCWD, /var/lib/mongodb/, O_RDONLY|O_CLOEXEC) -1 EACCES (Permission denied)。但之前明明chown过继续查ls -ld /var/lib/mongodb # 输出drwxr-x--- 3 mongodb mongodb 4096 ...问题在于750权限r-x对 group---对 others而systemd启动时WorkingDirectory默认是/mongod进程尝试chdir到/var/lib/mongodb时由于others无x权限无法进入目录。解决方案是将权限改为755sudo chmod 755 /var/lib/mongodb注意755是安全的因为mongodb用户是属主root是属组others只有读和执行权限不能写不会泄露数据。5.3 终极验证清单部署完成后的 5 项必检操作每次安装完我都会按顺序执行这 5 步确保万无一失服务状态检查sudo systemctl status mongod --no-pager \| grep -E (Active:|Main PID:|Loaded:)✅ 预期Active: active (running)、Main PID: [number]、Loaded: loaded (/lib/systemd/system/mongod.service; enabled)端口监听检查sudo ss -tuln \| grep :27017✅ 预期LISTEN 0 128 *:27017 *:*表示监听所有接口或LISTEN 0 128 127.0.0.1:27017 *:*仅本地认证连接测试mongo -u root -p your_password --authenticationDatabase admin --eval db.runCommand({ping:1})✅ 预期{ ok : 1 }远程连接测试如配置了 ufw从另一台机器执行nc -zv your-server-ip 27017✅ 预期Connection to your-server-ip 27017 port [tcp/*] succeeded!日志轮转验证sudo logrotate -d /etc/logrotate.d/mongodb-d是 debug 模式✅ 预期输出中包含rotating pattern和renaming证明日志不会无限增长。最后再分享一个小技巧如果你用的是 VS Code安装MongoDB for VS Code插件它能直接连接mongodb://root:passwordlocalhost:27017/?authSourceadmin图形化查看数据库比命令行更直观。但记住插件连接成功 ≠ 应用连接成功务必用你的实际应用代码如 Node.js 的mongoose.connect()再测一次因为应用可能有额外的 TLS 或连接池配置。我在实际使用中发现Ubuntu 18.04 的 systemd 对forking类型服务的 PID 文件监控有时不够灵敏偶尔会出现systemctl status显示active但实际进程已死的情况。所以我写了个简单的健康检查脚本每天凌晨 3 点用 cron 自动执行#!/bin/bash # /opt/scripts/check-mongod.sh if ! pgrep -x mongod /dev/null; then echo $(date): mongod process missing, restarting... /var/log/mongod-health.log systemctl restart mongod fi加上sudo crontab -e添加0 3 * * * /opt/scripts/check-mongod.sh。这比等报警再处理提前了至少 23 小时。