标签归档:nodejs

pm2部署遇到process.cwd报错的解决方法

最近在pm2.log中看见如下错误导致无法启动服务:

path.js:1144
          cwd = process.cwd();
                        ^

Error: ENOENT: no such file or directory, uv_cwd
    at Error (native)
    at Object.resolve (path.js:1144:25)
    at Function.Module._resolveLookupPaths (module.js:361:17)
    at Function.Module._resolveFilename (module.js:431:31)
    at Function.Module._load (module.js:388:25)
    at Module.require (module.js:468:17)
    at require (internal/module.js:20:19)
    at Object. (/usr/lib/node_modules/pm2/lib/ProcessContainer.js:12:15)
    at Module._compile (module.js:541:32)
    at Object.Module._extensions..js (module.js:550:10)

于是google之,在https://github.com/Unitech/pm2/issues/2057找到方法解决,记录如下:

首先导致这个错误是因为pm2最早启动的目录被删除了(删除后重建同名目录也是无用的)。

什么叫最早启动的目录呢?就是在命令行下第一次执行pm2时所在的目录,比如新装系统,在 /home/deploy 下第一次执行 pm2命令,那么 /home/deploy 就是最早启动的目录。再比如杀掉pm2进程后,再次在某个目录下执行了pm2命令,那这个目录也是最早启动的目录。

理解了最早启动的目录,那么当pm2启动后,把该目录删除过一次,则再次用pm2去启动node服务时就会报以上错误。

pm2 issues-2057中也有人指出了验证方法,如下:

  1. 先找到pm2的进程pid:
    ps ax | grep PM2
    
  2. 然后查询该进程执行时所在的目录(用上一步得到的pid替换下面命令的PM2_PID)
    ls -l /proc/PM2_PID/cwd
    
  3. 最后根据结果,如下的(deleted)标注,就说明该目录被删除过。
    $ ls -l /proc/24016/cwd
    lrwxrwxrwx 1 root root 0 Feb 4 17:04 /proc/24016/cwd -> /home/nodejs/deploy(deleted)
    

验证原因后,解决方法就是重新在另外一个安全一些的目录重启pm2进程。

先用pm2 kill命令杀掉pm2进程,然后 cd ~ 到home目录,执行 pm2 -v 命令,这样就在一个相对安全的目录启动了pm2。最后再去部署node服务就可以了。

express请求流中的错误捕捉处理

nodejs中的错误处理还是比较麻烦的,尤其遇到异步回调之类,多层嵌套,简单的try…catch无法处理。

目前在用expressjs,拿此举例说说怎样实践。
第一种,从一介布衣那儿看到的方法,可行:

const domain = require('domain');
app.use((req, res, next) => {
  const reqDomain = domain.create();
  // next抛出的异常在这里被捕获,触发此事件
  reqDomain.on('error', e => {
    // ... 这里统一处理错误,比如渲染或跳转到404,500页面
  });

  return reqDomain.run(next);
});

通过在route定义之前添加如上的中间件,可以捕捉到大部分的错误。

第二种,上面说到是大部分的错误,因为我碰到了一个没成功捕捉到的,就是使用swig模板渲染时的变量报错。

// 设置模板引擎
app.engine('swig', swig.renderFile);
app.set('view engine', 'swig');
app.set('views', `${__dirname}/views`);
app.set('viewExt', '.swig');
// 在某处渲染输出: 
res.render('template/filepath');
// 如果在filepath.swig文件中有变量报错,则第一种方法不能成功捕捉

这时在stackoverflow找到一个方法,

// 依然按第一种方法写错误捕捉
// 然后在route之后再写个中间件

// 最后的错误处理,比如发生在res.render中的错误
// 由于已经设置了响应,因此只能发送状态码,或跳转
// next不能去除,否则无法获取到错误
app.use((err, req, res, next) => {
  // res.sendStatus(500);
  log.error(err);
  // res.redirect(301, '/'); // 跳转到首页
  next();
});

ok,经过验证,上述方法已经能够处理目前所有遇到的问题。

第三种,为什么会有这一种方法呢,纯属个人思维发散,由于是express内部处理了模板引擎,导致res.render方法不能正常抛出错误被外围捕捉,那么我直接用swig方法渲染文件,并把渲染后的结果通过res.send方法响应是不是可以呢?

// 之前是这样渲染的
res.render('template/filepath');
// 改为
res.send(swig.renderFile('/...这里应该是物理绝对路径.../template/filepath.swig'));

经过上面改造,发现只用第一种方法也可以正常捕捉到错误,说明推论正确。

之所以在第二种还能解决的情况下还在寻找其他方案,是因为第二种的最终错误处理只能响应状态码,而不能再渲染页面了。终究不够完美,方法不够优雅。

像第三种方式,完全可以不必设置express的模板引擎了,用res.send + 模板自身的渲染方法即可,封装为一个方法,方便调用。

nodejs用fs.renameSync报错cross-device link not permitted

平台是windows,linux下也会有这种错误。具体是在调用

fs.renameSync(oldfile, newfile);时候,报以下错误:

fs.js:340
  return binding.rename(pathModule._makeLong(oldPath),
                 ^
Error: EXDEV, cross-device link not permitted 'C:\Users\cssor.com\AppData\Local\T
emp\5dead17eab63b1909b2e2664bdc1810c'
    at Object.renameSync (fs.js:340:18)

通过google以后理解了所谓的cross-device是什么意思了,原来是从C盘重命名文件并保存到F盘就会导致这种错误,所以,貌似只能同一个盘符操作。。。

最新版nodejs在windows系统下提供安装包

今天去nodejs下载,发现官网提供的不再是免安装的nodejs.exe了,而是nodejs.msi。安装后,在cmd下node和npm命令都有了,越来越方便了。

npm如下:

C:\Users\cssor>npm

Usage: npm  where  is one of: add-user, adduser, apihelp, author, bin, bugs, c, cache, completion, config, deprecate, docs, edit, explore, faq, find, get, help, help-search, home, i, info, init, install, la, link, list, ll, ln, login, ls, outdated, owner, pack, prefix, prune, publish, r, rb, rebuild, remove, restart, rm, root, run-script, s, se, search, set, show, shrinkwrap, star, start, stop, submodule, tag, test, un, uninstall, unlink, unpublish, unstar, up, update, version, view, whoami npm  -h quick help on  npm -l display full usage info npm faq commonly asked questions npm help  search for help on  npm help npm involved overview Specify configs in the ini-formatted file: C:\Users\ThinkPad\.npmrc or on the command line via: npm  --key value Config info can be viewed via: npm help config npm@1.1.21 C:\Program Files\nodejs\node_modules\npm

Node.js使用的场景

工欲善其事必先利其器, 利其器前也要选好这个“器”。Nodejs好像很好,但是也不是什么场景都好用,以下可以做些参考。

来源于:http://cnodejs.org/topic/4f97d5b8407edba2146030dd

原文地址在这里:http://nodeguide.com/convincingtheboss.html 英文版,题目的意思是说服老板的指南,文章中就Node.js应用场景这一重要话题说了一些看法,我摘取其中比较重要的段落,翻译在这里:

Continue reading Node.js使用的场景

Express.js中文入门指引手册

来源于:http://www.csser.com/board/4f77e6f996ca600f78000936

Express 是基于 Node.js,高性能、一流的web开发框架。

本手册由一回于 2011-4-24 首次翻译,如今已经过去接近一年,express 最新的版本已经与当时翻译有些脱节,为了方便内容更新,将使用 csser 开发的贴板功能进行维护,也方便大家针对细节进行讨论,并请指出翻译不当之处。

express 的安装

$ npm install express

或者

$ npm install -g express

创建服务器

要创建 express.HTTPServer 的实例,只需简单的调用 createServer() 方法即可。通过 HTTPServer 实例 app 我们可以定义基于 HTTP 动作(HTTP verbs)的路由(routes),本例中为 app.get()

var app = require('express').createServer();

app.get('/', function(req, res){
  res.send('hello world from csser.com!');
});

app.listen(3000);

Continue reading Express.js中文入门指引手册

NodeJS入门

来源于: http://www.nodebeginner.org/index-zh-cn.html

关于

本书致力于教会你如何用Node.js来开发应用,过程中会传授你所有所需的“高级”JavaScript知识。本书绝不是一本“Hello World”的教程。

状态

你正在阅读的已经是本书的最终版。因此,只有当进行错误更正以及针对新版本Node.js的改动进行对应的修正时,才会进行更新。

本书中的代码案例都在Node.js 0.6.11版本中测试过,可以正确工作。

读者对象

本书最适合与我有相似技术背景的读者: 至少对一门诸如Ruby、Python、PHP或者Java这样面向对象的语言有一定的经验;对JavaScript处于初学阶段,并且完全是一个Node.js的新手。

这里指的适合对其他编程语言有一定经验的开发者,意思是说,本书不会对诸如数据类型、变量、控制结构等等之类非常基础的概念作介绍。要读懂本书,这些基础的概念我都默认你已经会了。

然而,本书还是会对JavaScript中的函数和对象作详细介绍,因为它们与其他同类编程语言中的函数和对象有很大的不同。

本书结构

读完本书之后,你将完成一个完整的web应用,该应用允许用户浏览页面以及上传文件。

当然了,应用本身并没有什么了不起的,相比为了实现该功能书写的代码本身,我们更关注的是如何创建一个框架来对我们应用的不同模块进行干净地剥离。 是不是很玄乎?稍后你就明白了。

本书先从介绍在Node.js环境中进行JavaScript开发和在浏览器环境中进行JavaScript开发的差异开始。

紧接着,会带领大家完成一个最传统的“Hello World”应用,这也是最基础的Node.js应用。

最后,会和大家讨论如何设计一个“真正”完整的应用,剖析要完成该应用需要实现的不同模块,并一步一步介绍如何来实现这些模块。

可以确保的是,在这过程中,大家会学到JavaScript中一些高级的概念、如何使用它们以及为什么使用这些概念就可以实现而其他编程语言中同类的概念就无法实现。

该应用所有的源代码都可以通过
本书Github代码仓库.

Continue reading NodeJS入门