首页 > 解决方案 > ubuntu 上的 pm2 和 systemd 无法正确守护节点应用程序

问题描述

伙计们。我正在 Ubuntu 服务器上实现一个节点应用程序。该应用程序使用 CAS 服务器来获取票证。如下代码:

module.exports = function (req, res, next) {
    if (!req.session) {         // failed to create session
        return res.status(500).end();
    }
    if (req.session.uid) {      // user has logged
        return next();
    }
    if (!req.query || !req.query.ticket) {  
        // if a none-logged request has no query, it should be thought as 
        // the first request of the user, so it would be redirect to CAS 
        // server for authentication
        return redirectToCas(req, res);
    }
    var { ticket } = req.query;
    if (!ticket.startsWith('ST-')) {
        // This system self don't use query string. If a none-logged request
        // carries a none-CAS-standard query, it will be treated as illegal
        // and redirect to unauthorized page.
        return redirectTo401(res);  // unknown ticket
    }
    let originalUrl = LOCAL_SERVICE + url.parse(req.originalUrl).pathname;
    let path = `${CAS_SERVER}/serviceValidate?service=${originalUrl}&ticket=${ticket}`;
    (async () => {
        try {
            console.log(`${times++} original url:${originalUrl}`);

            let echo = await getResponseText(path);     // get xml response from CAS server
            let result = await parseXmlEcho(echo);      // set successful flag and fetch uid 
            if (result.success) {       // successfully pass the verification of CAS
                var hasPerm = await testPermission(result.uid);
                if (hasPerm) {          // test if user has permission in this system
                    req.session.uid = result.uid;
                    res.redirect(originalUrl);
                } else {
                    redirectTo401(res);
                }
            } else {
                //res.status(401).end('authorized');
                redirectTo401(res);
            }
        }
        catch (err) {
            console.error(err);
            //res.status(401).end('没有授权!');      // unauthorized
            redirectTo401(res);
        }
    })();
}

以上代码属于auth.js。app.js 的主要入口端口是这样的:

// provide public resources
app.use(favicon(path.join(__dirname, 'public', 'some.ico')))
    .use('/public', express.static('public'));

// check session
app.use(session({
    name: 'certain-name',
    secret,
    store: new MssqlStore(storeConfig),
    resave: false,
    saveUninitialized: false,
    cookie: {
        path: '/',
        httpOnly: false
    }
}));

// authenticate
app.use('*', auth)              // authenticate
    .post('/end', api.end);     // logout
    .... serve index.html and other resource here 

现在我已经在我的 Ubuntu 服务器上实现了代码。当我使用“node app.js”在 Putty 终端中启动应用程序时,一切正常。但是当我使用 PM2 或 systemd 启动它时(我在 Chris Lea 的博客的指导下配置它 ),应用程序崩溃并且浏览器回显“Cannot GET /index.html”。查看日志(systemctl status myappname)后,系统但报告 index.html 已被提供。通过直接在终端中敲入“节点应用程序”和使用 systemd 或 PM2 启动它来生成过程有什么区别?生成 Nodejs+CAS 是否需要一些进一步的配置?

标签: node.jssystemdpm2

解决方案


在插入一束日志语句后,我已经弄清楚了应用程序的详细流程步骤。该问题是由于指定了错误的静态资源路径引起的。我的应用程序中有两行引用了 express 静态中间件。一个是在认证之前,另一个是在认证之后。

use('/public', express.static('public')) // serve two tiny images and noperm.html
...authenticate
use('/',express.static('client/build')) // serve homepage

这两个语句都将资源路径与当前目录捆绑在一起。当我使用 putty 连接到 Ubuntu 时,我不知不觉总是进入包含应用程序的路径,然后使用 node.js 启动应用程序。因为当前路径是应用程序的根目录,所以 current-path+'public' 和 current-path+'client/build' 都可以计算出正确的资源路径,并且应用程序运行愉快。但是当我使用 PM2 或 systemd 启动应用程序时,基本目录更改(我尚未验证但只是猜测)到 PM2 或 systemd 的根路径,因此所有静态资源都无法再正确发现并且应用程序运行失败的。在我修改了代码以计算静态资源路径后,path.join 方法问题消失了。所以从 PM2 和 Node 启动应用程序之间确实有一些不同,至少默认路径是。


推荐阅读