Node.js中Express监听80端口触发EACCES错误无法捕获如何处理
捕获失败原因
app.listen() 属于异步I/O操作,端口绑定的错误会在后续事件循环阶段抛出,而你编写的同步try/catch块只能捕获当前执行栈内的同步错误,自然无法捕获到异步抛出的EACCES异常。
正确处理方式
方案1:监听服务的error事件(最常用)
app.listen会返回一个Node.js的http.Server实例,我们可以直接监听这个实例的error事件捕获端口绑定相关错误:
const express = require("express"); const app = express(); var meetings = []; app.use("/static", express.static("public/")) app.use("/index.html?", function(request, response, next) { response.redirect("/"); }) app.get("/", function(request, response) { response.sendFile(__dirname + "/pages/index.html"); }) const server = app.listen(80); server.on('error', (err) => { if (err.code === 'EACCES') { console.log("Can't run on port 80. Please, run me as a sudo!"); process.exit(1); } // 其他错误类型可在这里补充处理逻辑 });
方案2:封装为Promise配合async/await捕获
如果偏好try/catch的写法,可以把监听逻辑封装为Promise,配合异步函数捕获错误:
const express = require("express"); const app = express(); var meetings = []; app.use("/static", express.static("public/")) app.use("/index.html?", function(request, response, next) { response.redirect("/"); }) app.get("/", function(request, response) { response.sendFile(__dirname + "/pages/index.html"); }) // 封装监听逻辑为Promise function startServer(port) { return new Promise((resolve, reject) => { const server = app.listen(port); server.on('error', reject); server.on('listening', () => resolve(server)); }); } // 异步启动服务 async function init() { try { await startServer(80); console.log("服务启动成功"); } catch (err) { if (err.code === 'EACCES') { console.log("Can't run on port 80. Please, run me as a sudo!"); } process.exit(1); } } init();
额外说明
Linux、macOS等类Unix系统中,1024以下的端口属于特权端口,默认只有root权限才能绑定。直接给Node服务root权限存在安全风险,生产环境更推荐你:
- 把Node服务监听1024以上的端口(比如3000)
- 用Nginx做反向代理,将80端口的请求转发到Node服务的监听端口
内容的提问来源于stack exchange,提问作者Vad Sim
相关产品推荐
相关产品推荐

