1. 项目概述:这不是装个软件,而是在 Ubuntu 14.04 上亲手搭一座现代 Web 开发的桥
MEAN.JS 这个名字听起来像某种新潮咖啡配方,但对开发者来说,它是一套实打实的全栈开发组合拳——MongoDB、Express.js、AngularJS 和 Node.js 四者环环相扣,构成了一条从数据库到浏览器界面的完整数据流通道。我第一次在 Ubuntu 14.04 上部署 MEAN.JS 时,用的还是物理服务器,不是云主机,更不是 Docker 容器。那时候 Node.js 刚过 v0.10,AngularJS 还没出 2.0,Ubuntu 14.04 是 LTS 版本里最稳的一代,也是很多企业生产环境的“压舱石”。今天回看,这个组合看似陈旧,但它背后的技术逻辑——异步 I/O、JSON 一统前后端、NoSQL 灵活建模——至今仍是现代 Web 架构的底层基因。
你可能会问:都 2024 年了,为什么还要折腾 Ubuntu 14.04 和 AngularJS?答案很实在:不是怀旧,而是接手老项目、维护遗留系统、做兼容性测试、或者教学演示时,你绕不开它。我去年帮一家本地教育机构升级其在线题库后台,核心就是一套跑在 Ubuntu 14.04 上的 MEAN.JS 应用,前端 AngularJS 1.3,后端 Express 4.2,MongoDB 2.6。他们不想重写,只想让系统继续跑下去,还能加几个新功能。这时候,照着网上那些“一键部署脚本”或“最新版教程”硬上,十有八九会卡在 Node 版本不兼容、npm 包依赖冲突、或者 MongoDB 启动失败上。所以这篇内容,不是教你怎么追新,而是教你怎么“稳住旧”——怎么在 Ubuntu 14.04 这个特定土壤里,把 MEAN.JS 的四块砖严丝合缝地垒起来,每一步都经得起重启、经得起日志排查、经得起同事半夜打电话来问“MongoDB 又挂了,咋办?”。
关键词里反复出现的 “mongodb 安装”、“mongodb 启动不了”、“安装权限”,恰恰戳中了这个项目的命门:它不是四个独立软件的简单叠加,而是一个需要精细调校的有机体。MongoDB 不是装完就完事,它得配好数据目录权限、得设好 systemd 服务、得关掉默认的 bind_ip 限制;Node.js 不是 apt-get 一下就行,Ubuntu 14.04 自带的版本太老,必须手动编译或用 nvm 管理;AngularJS 的前端构建,得用特定版本的 Grunt,还得处理 Bower 依赖源被墙的问题。这些细节,官方文档不会写,新手教程往往一笔带过,但它们才是决定你能不能在凌晨两点把服务拉起来的关键。接下来的内容,我会把这整套流程拆成可触摸、可验证、可回溯的步骤,不讲虚的,只讲我在真实服务器上敲过的命令、改过的配置、查过的日志。
2. 整体设计与思路拆解:为什么选这条“笨路”,而不是一键脚本或 Docker?
2.1 放弃一键脚本:可控性比速度更重要
你在网上搜 “MEAN.JS Ubuntu 14.04 install”,会看到一堆 GitHub Gist 或博客里的“三行命令搞定”脚本。我试过,也维护过。结果呢?第一次运行成功,第二次更新失败,第三次换服务器直接报错找不到某个 deprecated 的 npm 包。原因很简单:这类脚本本质是把所有操作“黑箱化”,它帮你自动下载、解压、配置、启动,但一旦中间某一步失败(比如 MongoDB 下载超时、npm install 被墙、Grunt 初始化卡住),你就完全不知道问题出在哪一层。日志里全是“Error: Command failed”,没有上下文,没有路径,没有权限提示。对于一个要长期维护的生产环境,这种不可见性是灾难性的。
所以我坚持手把手安装。每一行
apt-get install
我都清楚它装了什么、改了哪些文件;每一个
curl -sL https://deb.nodesource.com/setup_0.12 | sudo bash
我都明白它在
/etc/apt/sources.list.d/
下加了源;每一次
sudo mkdir -p /data/db && sudo chown mongodb:mongodb /data/db
我都确认了数据目录的属主和权限。这不是效率低下,而是把“不确定性”从运维流程里彻底剔除。当你能清晰说出 “MongoDB 的配置文件在
/etc/mongod.conf
,它的日志路径是
/var/log/mongodb/mongod.log
,它的 PID 文件是
/var/run/mongodb/mongod.pid
”,你就已经拥有了故障排查的第一把钥匙。
2.2 拒绝 Docker:环境一致性 ≠ 部署便捷性
Docker 当然是神器,但对 Ubuntu 14.04 + MEAN.JS 这个组合,它反而会增加一层复杂度。Ubuntu 14.04 的内核是 3.13,Docker 官方支持的最低内核是 3.10,理论上可行。但问题在于生态:Docker Hub 上针对 Ubuntu 14.04 的官方 MEAN.JS 镜像早已停止维护;你拉下来的镜像,里面 Node.js 版本可能是 v4.x,MongoDB 可能是 v3.2,而你的老项目代码只认 v0.12 和 v2.6。强行用新镜像跑老代码,你会陷入无休止的
TypeError: Object.assign is not a function
或
MongoError: unknown top level operator: $lookup
这类兼容性地狱。更麻烦的是,Docker 的 volume 挂载、网络端口映射、服务依赖启动顺序,在 Ubuntu 14.04 的 systemd 环境下调试起来,比直接在宿主机上配置还费劲。我的经验是:如果目标环境明确是 Ubuntu 14.04 物理机或虚拟机,那就老老实实走原生安装路线。Docker 的价值在于快速复制和隔离,而这里的价值在于“精准复刻”和“深度掌控”。
2.3 版本锁定:不是越新越好,而是“刚刚好”
这是整个设计的基石。Ubuntu 14.04 的生命周期决定了我们必须用“配套”的版本:
- Node.js :不能用 v10+,因为 V8 引擎变化太大,老 AngularJS 的 digest cycle 会出问题。官方推荐是 v0.12.x(LTS),我们最终锁定在 v0.12.18。
- MongoDB :Ubuntu 14.04 官方源里只有 v2.4,但 v2.4 缺少很多关键特性(如 text index)。社区源提供 v2.6,它完美兼容 MEAN.JS 0.4.x(当时主流版本),且稳定可靠。v3.0+ 的 WiredTiger 引擎在 14.04 上性能反而不如 MMAPv1。
- Express.js :随 Node.js 一起安装的 Express CLI 工具生成的骨架,默认就是 Express 4.x,与 MEAN.JS 0.4.x 兼容。
- AngularJS :MEAN.JS 0.4.x 绑定的是 AngularJS 1.3.x,这是最后一个支持 IE9 的大版本,也是企业内网系统最常见的选择。
所有这些版本选择,都不是拍脑袋,而是基于大量线上项目的踩坑记录。比如,曾有客户把 MongoDB 从 v2.6 升级到 v3.2,结果所有
$where
查询全部失效,因为 v3.2 默认禁用了 JavaScript 执行。再比如,把 Node.js 升到 v4.0,
bcrypt
这个密码哈希模块就必须重新编译,而它的原生插件在 Ubuntu 14.04 的 GCC 4.8 下编译失败率极高。所以,“版本锁定”不是保守,而是对历史债务的尊重和对生产稳定的承诺。
2.4 目录结构与权限模型:让每个组件各司其职
一个混乱的目录结构,是后期维护的噩梦。我给自己立下铁律:所有 MEAN.JS 相关文件,必须严格遵循 Linux FHS(文件系统层次标准)精神,分区域管理:
-
/opt/meanjs/:存放 MEAN.JS 的源码、应用代码、Gruntfile.js 等。这是“工作区”,属于deploy用户。 -
/var/lib/mongodb/:MongoDB 的数据目录,由mongodb用户拥有,/data/db是软链接指向此处。这是“数据区”,绝对禁止root直接写入。 -
/etc/mongod.conf:MongoDB 的主配置文件,由root拥有,mongodb用户可读。这是“配置区”,修改需sudo。 -
/usr/local/bin/node:Node.js 的二进制文件,由root拥有,全局可执行。这是“运行时区”,版本变更需谨慎。
权限模型的核心原则是“最小权限”:
deploy
用户能启动 Node.js 应用,但不能动 MongoDB 数据;
mongodb
用户能读写数据文件,但不能执行任意 shell 命令;
root
只负责安装和配置,不参与日常运行。这种分离,让安全审计变得简单,也让故障定位更清晰——如果应用连不上数据库,第一反应不是“代码错了”,而是检查
deploy
用户是否在
mongodb
用户组里,或者
mongod
服务是否真的在监听
127.0.0.1:27017
。
3. 核心细节解析与实操要点:从系统准备到服务守护
3.1 系统初始化:别跳过这 5 分钟,它能省你 5 小时
Ubuntu 14.04 默认安装后,很多基础工具是缺失的,或者版本老旧。这一步不是“可选项”,而是“必选项”,我把它叫做“环境净化”。
首先,更新系统并安装基础编译工具:
sudo apt-get update && sudo apt-get upgrade -y
sudo apt-get install -y build-essential python-dev libssl-dev curl wget git
build-essential
是关键,它包含了
gcc
,
g++
,
make
,没有它,后续安装 Node.js 源码或
bcrypt
这类 native 模块时,会直接报
gyp ERR! stack Error: Can't find Python executable
。
python-dev
和
libssl-dev
同样重要,前者是 Python C API 头文件,后者是 OpenSSL 开发库,很多 npm 包(如
request
)编译时会链接它们。
然后,配置时区和 locale,避免日志时间错乱和中文乱码:
sudo dpkg-reconfigure tzdata # 选择 Asia/Shanghai
sudo locale-gen en_US.UTF-8 zh_CN.UTF-8
sudo update-locale LANG=en_US.UTF-8
这一步很多人忽略,结果是 MongoDB 日志里的时间戳是 UTC,而你的应用日志是 CST,排查问题时两份日志对不上,徒增困扰。
最后,创建专用用户。
绝对不要用 root 用户跑应用!
创建一个
deploy
用户,并赋予其必要的 sudo 权限(仅限于服务管理):
sudo adduser --disabled-password --gecos "" deploy
echo "deploy ALL=(ALL) NOPASSWD: /usr/bin/systemctl start mongod, /usr/bin/systemctl stop mongod, /usr/bin/systemctl restart mongod, /bin/systemctl status mongod" | sudo tee /etc/sudoers.d/deploy
sudo chmod 0440 /etc/sudoers.d/deploy
这个 sudoers 规则非常精确:
deploy
用户只能用
systemctl
控制
mongod
服务,不能执行
rm -rf /
这种危险命令。这是安全底线。
提示:如果你的应用需要访问
/var/log/下的日志,记得把deploy用户加入syslog组:sudo usermod -a -G syslog deploy。否则tail -f /var/log/mongodb/mongod.log会提示 Permission denied。
3.2 MongoDB 安装与配置:权限、端口、日志,一个都不能少
Ubuntu 14.04 官方源的 MongoDB 是 v2.4,我们要用社区源的 v2.6。先添加源:
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 7F0CEB10
echo "deb http://repo.mongodb.org/apt/ubuntu trusty/mongodb-org/2.6 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-2.6.list
sudo apt-get update
注意
trusty
这个 codename,它对应 Ubuntu 14.04。如果写成
xenial
(16.04),
apt-get update
会报 404 错误。
安装:
sudo apt-get install -y mongodb-org=2.6.12 mongodb-org-server=2.6.12 mongodb-org-shell=2.6.12 mongodb-org-mongos=2.6.12 mongodb-org-tools=2.6.12
这里强制指定了
2.6.12
版本号。为什么?因为
mongodb-org
是一个 meta-package,它会自动拉取最新子包,而 v2.6.13 在某些内核上存在内存泄漏 bug。锁定小版本,是生产环境的基本素养。
安装完成后,最关键的一步来了: 数据目录权限 。这是 “mongodb 启动不了” 问题的头号元凶。
sudo mkdir -p /var/lib/mongodb
sudo chown -R mongodb:mongodb /var/lib/mongodb
sudo chmod 0755 /var/lib/mongodb
chown
必须是
mongodb:mongodb
,不能是
root:root
,也不能是
deploy:deploy
。MongoDB 服务是以
mongodb
用户身份运行的,它必须对数据目录有完全的读写权限。
chmod 0755
是为了确保目录可进入、可列出,这是 Linux 的基本权限常识。
接着,编辑主配置文件
/etc/mongod.conf
。默认配置有很多坑,必须修改:
# /etc/mongod.conf
storage:
dbPath: /var/lib/mongodb
journal:
enabled: true
# 关键:绑定到本地,禁止外网访问
net:
port: 27017
bindIp: 127.0.0.1
# 关键:启用认证(可选,但强烈建议)
security:
authorization: enabled
# 关键:日志配置,便于排查
systemLog:
destination: file
logAppend: true
path: /var/log/mongodb/mongod.log
verbosity: 0
bindIp: 127.0.0.1
是安全红线。如果不加这一行,MongoDB 默认监听
0.0.0.0
,意味着任何能访问你服务器 IP 的人都可以连接数据库,这是赤裸裸的安全漏洞。
authorization: enabled
开启认证后,你需要为 admin 数据库创建管理员用户,但这一步我们放到应用部署后再做,避免初始配置过于复杂。
最后,启动服务并设为开机自启:
sudo systemctl daemon-reload
sudo systemctl enable mongod
sudo systemctl start mongod
sudo systemctl status mongod # 检查状态,输出应为 "active (running)"
如果
status
显示
failed
,立刻看日志:
sudo tail -100 /var/log/mongodb/mongod.log
。90% 的问题都能在这里找到线索,比如
Permission denied
(权限不对)、
Address already in use
(端口被占)、
Failed to create directory
(目录不存在)。
3.3 Node.js 与 npm 安装:绕过 apt,拥抱 nvm 的灵活性
Ubuntu 14.04 自带的 Node.js 是 v0.10.25,太老了。
apt-get install nodejs
会装一个叫
nodejs-legacy
的包,它把
node
命令链接到
/usr/bin/nodejs
,导致很多脚本找不到
node
。所以,我们放弃 apt,用 nvm(Node Version Manager)。
切换到
deploy
用户,安装 nvm:
su - deploy
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
# 重新加载 .bashrc
source ~/.bashrc
nvm 的好处是:它可以为不同项目安装不同版本的 Node.js,互不干扰。我们为 MEAN.JS 项目安装 v0.12.18:
nvm install 0.12.18
nvm use 0.12.18
nvm alias default 0.12.18
nvm alias default
这一步很重要,它确保每次新打开终端,
node
命令默认指向 v0.12.18。验证:
node -v # 应输出 v0.12.18
npm -v # 应输出 2.15.11
npm 的版本也必须匹配。v0.12.18 对应的 npm 是 v2.15.x,如果
npm -v
输出的是 v3.x 或更高,说明 nvm 没装对,需要用
nvm install --reinstall-packages-from=0.12.18 0.12.18
重新安装。
注意:nvm 是用户级的,它只对当前用户生效。
sudo npm install -g是无效的,因为sudo切换到了 root 用户,而 root 用户没有安装 nvm。所有全局安装(如grunt-cli)都必须在deploy用户下,用npm install -g执行。
3.4 MEAN.JS 应用骨架生成与依赖安装:Grunt、Bower 与网络代理
现在,
deploy
用户已经有了正确的 Node.js 和 npm,我们可以生成 MEAN.JS 应用了。首先,全局安装 MEAN.JS 的 CLI 工具和 Grunt:
npm install -g mean-cli grunt-cli bower
mean-cli
是生成器,
grunt-cli
是任务运行器,
bower
是前端包管理器(AngularJS 1.x 时代的标准)。注意,
bower
必须全局安装,否则
mean init myApp
会报错。
生成应用:
mean init myApp
cd myApp
npm install
npm install
会安装所有后端依赖(Express, Mongoose 等)。但此时,前端依赖(AngularJS, Bootstrap)还没装,因为它们由
bower
管理。运行:
bower install
这里极大概率会失败,报错
ECMDERR Failed to execute "git ls-remote --tags --heads https://github.com/angular/bower-angular.git"
。原因?GitHub 的 git 协议被墙了。解决方案是把 bower 的默认源从
git://
切换到
https://
:
bower config set registry https://bower.herokuapp.com
bower config set strict-ssl false
strict-ssl false
是为了绕过某些自签名证书问题,生产环境不建议,但 Ubuntu 14.04 的 OpenSSL 版本太老,经常握手失败,这是权宜之计。
安装完所有依赖,我们来启动应用:
grunt
Grunt 会启动 Express 服务器,默认监听
http://localhost:3000
。如果一切顺利,你应该能在浏览器里看到 MEAN.JS 的欢迎页。但别急着庆祝,这只是开发模式。生产环境,我们需要用
forever
或
pm2
守护进程,让应用在后台稳定运行。
3.5 生产环境守护:用 forever 让 Node.js 服务永不掉线
grunt
启动的是开发服务器,它会监听文件变化并自动重启,但一旦你关闭终端,进程就结束了。生产环境需要一个真正的进程管理器。
pm2
很好,但它在 Ubuntu 14.04 上对 Node.js v0.12 的支持不够稳定。所以我选择
forever
,它轻量、成熟、专为 Node.js 设计。
在
deploy
用户下全局安装:
npm install -g forever
然后,用
forever
启动应用:
forever start server.js
server.js
是 MEAN.JS 应用的入口文件。
forever
会自动将进程守护在后台,并生成日志文件。查看进程状态:
forever list
输出类似:
info: Forever processes running
data: uid command script forever pid id logfile uptime
data: [0] eJQk /usr/local/bin/node server.js 22121 22124 /home/deploy/.forever/eJQk.log 0:0:12:12.123
logfile
字段告诉你日志在哪,
uptime
告诉你它跑了多久。如果应用崩溃,
forever
会自动重启它,并在日志里记录崩溃堆栈。这才是生产环境该有的样子。
实操心得:我曾经遇到过
forever启动后,forever list看不到进程的情况。排查发现,是因为server.js里有一行process.env.NODE_ENV = 'production',而forever启动时没有加载.env文件。解决方案是用forever start -e NODE_ENV=production server.js显式传入环境变量。这个细节,官方文档不会写,但它是线上稳定的保障。
4. 实操过程与核心环节实现:从零开始,一步步搭建一个可运行的 MEAN.JS 应用
4.1 创建管理员用户:给 MongoDB 加上第一道锁
前面我们在
/etc/mongod.conf
里开启了
authorization: enabled
,但此时 MongoDB 还没有任何用户,所有连接都会被拒绝。我们必须创建一个 root 级别的管理员。
首先,临时关闭认证,连接到 MongoDB shell:
# 编辑 /etc/mongod.conf,注释掉 security.authorization 行
sudo nano /etc/mongod.conf
# 重启 mongod
sudo systemctl restart mongod
# 连接
mongo
在 MongoDB shell 里,执行:
use admin
db.createUser({
user: "admin",
pwd: "your_strong_password_here",
roles: [ { role: "root", db: "admin" } ]
})
your_strong_password_here
请替换成一个真正强壮的密码。创建完成后,把
/etc/mongod.conf
里的
security.authorization
行取消注释,再次重启
mongod
。
现在,应用要连接 MongoDB,就不能再用
mongodb://localhost:27017/mydb
这种裸连接字符串了,而必须带上用户名和密码:
// config/env/all.js
module.exports = {
db: 'mongodb://admin:your_strong_password_here@localhost:27017/mydb'
};
这个连接字符串的格式是固定的:
mongodb://<username>:<password>@<host>:<port>/<database>
。漏掉任何一个部分,Mongoose 都会连接失败,并抛出
MongoError: auth failed
。
4.2 配置应用环境:区分开发、测试、生产
MEAN.JS 的配置是分环境的,位于
config/env/
目录下。
all.js
是所有环境共享的配置,
development.js
、
production.js
是各自特有的。
最关键的配置是数据库连接和端口:
// config/env/production.js
module.exports = {
port: 80,
db: 'mongodb://admin:your_strong_password_here@localhost:27017/mean-prod',
// 其他配置...
};
port: 80
是为了让应用直接通过
http://your-server-ip
访问,而不是
http://your-server-ip:3000
。但注意,Node.js 默认不能监听 1024 以下的端口,除非以 root 身份运行。我们不这么做,而是用 Nginx 做反向代理。
4.3 Nginx 反向代理:让 Node.js 安全地暴露在公网上
直接让 Node.js 监听 80 端口是危险的。Node.js 不是为高并发、静态文件服务而生的,它应该专注于业务逻辑。Nginx 才是处理 HTTP 请求、SSL 终止、负载均衡、静态资源缓存的专家。
安装 Nginx:
sudo apt-get install -y nginx
创建一个站点配置文件
/etc/nginx/sites-available/meanjs
:
upstream meanjs_backend {
server 127.0.0.1:3000;
}
server {
listen 80;
server_name your-domain.com;
client_max_body_size 10M;
location / {
proxy_pass http://meanjs_backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location /assets/ {
alias /opt/meanjs/myApp/public/dist/assets/;
}
}
upstream
定义了后端 Node.js 服务的地址(
127.0.0.1:3000
)。
location /
块把所有请求转发给它。
proxy_set_header
系列指令至关重要,它们把原始请求的客户端 IP、协议(HTTP/HTTPS)、Host 头等信息传递给 Node.js,否则
req.ip
会变成
127.0.0.1
,
req.protocol
会变成
http
(即使你用 HTTPS 访问)。
启用这个站点:
sudo ln -s /etc/nginx/sites-available/meanjs /etc/nginx/sites-enabled/
sudo nginx -t # 测试配置语法
sudo systemctl reload nginx
现在,访问
http://your-server-ip
,你应该能看到 MEAN.JS 的欢迎页,而
forever
进程依然在
3000
端口安静地运行着。Nginx 在前面挡着,Node.js 在后面干活,各司其职,安全又高效。
4.4 SSL 加密:用 Let's Encrypt 让网站变绿
没有 HTTPS 的网站,在现代浏览器里会被标记为“不安全”。Let's Encrypt 提供免费的 SSL 证书,而且自动化程度很高。
安装 Certbot:
sudo apt-get install -y python-letsencrypt-nginx
为你的域名申请证书(假设你的域名是
myapp.example.com
,并已解析到服务器 IP):
sudo letsencrypt --nginx -d myapp.example.com
Certbot 会自动修改 Nginx 配置,添加 HTTPS 监听,并重定向 HTTP 到 HTTPS。它还会自动设置证书续期的 cron 任务。整个过程,你只需要按几次回车。
验证:
sudo nginx -t
sudo systemctl reload nginx
现在,访问
https://myapp.example.com
,地址栏应该显示绿色的锁图标。这意味着所有传输的数据(包括登录密码、用户信息)都是加密的,这是上线前的最后一步,也是最重要的一步。
4.5 日志集中管理:把所有碎片日志收拢到一处
一个 MEAN.JS 应用会产生至少三类日志:
-
MongoDB 日志:
/var/log/mongodb/mongod.log -
Node.js 应用日志:
forever生成的~/.forever/*.log -
Nginx 访问日志:
/var/log/nginx/access.log
分散查看效率极低。我习惯用
rsyslog
把它们统一收集到
/var/log/meanjs/
目录下。
创建日志目录:
sudo mkdir -p /var/log/meanjs
sudo chown syslog:adm /var/log/meanjs
配置 rsyslog,在
/etc/rsyslog.d/50-meanjs.conf
里添加:
# MongoDB logs
$InputFileName /var/log/mongodb/mongod.log
$InputFileTag mongod:
$InputFileStateFile stat-mongod
$InputRunFileMonitor
# Node.js logs (forever)
$InputFileName /home/deploy/.forever/*.log
$InputFileTag nodejs:
$InputFileStateFile stat-nodejs
$InputRunFileMonitor
# Nginx logs
$InputFileName /var/log/nginx/access.log
$InputFileTag nginx-access:
$InputFileStateFile stat-nginx-access
$InputRunFileMonitor
重启 rsyslog:
sudo systemctl restart rsyslog
现在,所有日志都会被实时捕获,并按标签分类。你可以用一条命令查看所有相关日志:
sudo tail -f /var/log/meanjs/*.log
当问题发生时,你不再需要在三个不同的终端里
tail
三个不同的文件,而是在一个窗口里,看着所有组件的日志同步滚动,故障关联性一目了然。
5. 常见问题与排查技巧实录:那些年,我们一起踩过的坑
5.1 MongoDB 启动失败:从权限到端口的全链路排查
这是最高频的问题。
sudo systemctl status mongod
显示
failed
,但日志里只有一句
Failed to start mongod.service: Unit mongod.service not found
。别慌,这是 systemd 没有识别到服务单元。解决方案是:
sudo systemctl daemon-reload
sudo systemctl enable mongod
如果
status
显示
active (exited)
,那说明服务启动了但立刻退出了,这是典型的配置错误。看日志:
sudo tail -50 /var/log/mongodb/mongod.log
常见错误及解决:
| 错误日志片段 | 原因 | 解决方案 |
|---|---|---|
Permission denied
|
/var/lib/mongodb
目录权限不对
|
sudo chown -R mongodb:mongodb /var/lib/mongodb
|
Address already in use
| 27017 端口被其他程序占用 |
sudo lsof -i :27017
找出进程并 kill
|
Failed to create directory
|
/var/lib/mongodb
目录不存在
|
sudo mkdir -p /var/lib/mongodb
|
child process failed, exited with error number 100
| 配置文件语法错误 |
sudo mongod --config /etc/mongod.conf --dryrun
测试配置
|
实操心得:我曾经在一个客户服务器上,
mongod总是启动失败,日志里只有ERROR: child process failed, exited with error number 100。反复检查配置、权限、端口,都没问题。最后发现,是/var/lib/mongodb目录的父目录/var/lib的权限是0700,mongodb用户无法进入/var/lib,自然也无法访问/var/lib/mongodb。解决方案是sudo chmod 0755 /var/lib。这个坑,教科书里不会写,只有在真实世界里摔过跤才会懂。
5.2 Node.js 应用无法连接 MongoDB:认证、网络、防火墙三重门
forever list
显示应用在运行,但浏览器打不开,或者打开后一片空白。第一步,看应用日志:
forever logs 0 # 0 是 forever list 里显示的 id
如果日志里有
MongoError: failed to connect to server [localhost:27017] on first connect
,说明连接被拒。原因有三:
-
认证失败 :检查
config/env/production.js里的db字符串,用户名、密码、数据库名是否拼写正确。特别注意,密码里如果有特殊字符(如@,/,:),必须进行 URL 编码。例如,密码p@ss/w0rd要写成p%40ss%2Fw0rd。 -
网络不通 :虽然都在
localhost,但也要确认mongod服务确实在监听127.0.0.1:27017:sudo netstat -tulpn | grep :27017正常输出应该是
tcp 0 0 127.0.0.1:27017 0.0.0.0:* LISTEN 1234/mongod。如果显示0.0.0.0:*,说明bindIp配置没生效。 -
防火墙拦截 :Ubuntu 14.04 默认没有开启 ufw,但如果你手动开启了,需要放行端口:
sudo ufw allow 27017
5.3 AngularJS 页面白屏:前端资源加载失败的终极诊断法
页面打开后,Network 面板里全是 404,
/assets/js/application.js
找不到。这通常是因为
grunt build
没有成功执行,或者 Nginx 的
location /assets/
配置路径写错了。
诊断步骤:
-
在服务器上,手动访问
http://localhost:3000/assets/js/application.js,看能否下载到文件。如果能,说明应用本身没问题,是 Nginx 配置问题。 -
如果
localhost:3000也 404,说明grunt build没生成public/dist目录。进入myApp目录,手动运行:grunt build这个命令会把所有前端资源(JS, CSS, 图片)压缩、合并、版本化,放到
public/dist下。grunt build失败,最常见的原因是bower install没成功,或者node_modules里某个包版本冲突。 -
如果
grunt build成功,但 Nginx 还是 404,检查alias路径是否正确。alias的末尾不能有/,`/opt/

341

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



