Node.js
Node.js 笔记
Node.js 中文文档
http://nodejs.cn/api/
问题
JavaScript heap out of memory
hexo g 生成博客时报错:
<--- Last few GCs --->
[9778:0x3dbc8c0] 255427 ms: Mark-sweep 905.0 (932.2) -> 897.8 (932.2) MB, 112.6 / 0.0 ms (average mu = 0.348, current mu = 0.317) allocation failure scavenge might not succeed
[9778:0x3dbc8c0] 255578 ms: Mark-sweep 904.9 (932.2) -> 900.6 (932.9) MB, 116.3 / 0.0 ms (average mu = 0.293, current mu = 0.230) allocation failure scavenge might not succeed
<--- JS stacktrace --->
==== JS stack trace =========================================
0: ExitFrame [pc: 0x1374fd9]
Security context: 0x11594c7808a1 <JSObject>
1: /* anonymous */ [0xbdb517567e1] [/home/centos/git/hexo/node_modules/htmlparser2/lib/Parser.js:~181] [pc=0x221e201d5f5c](this=0x066bc2c80699 <Parser map = 0x28c71fabe141>)
2: /* anonymous */ [0xbdb51756051] [/home/centos/git/hexo/node_modules/htmlparser2/lib/Tokenizer.js:~702] [pc=0x221e1ff1903c](this=0x066bc2c80759 <Tokenizer map = 0x28c71fabe0f1>)
...
FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory
Writing Node.js report to file: report.20210622.113552.9778.0.001.json
Node.js report completed
1: 0x9da7c0 node::Abort() [hexo]
2: 0x9db976 node::OnFatalError(char const*, char const*) [hexo]
原因:
内存不足
解决:
export NODE_OPTIONS="--max-old-space-size=2048"
child_process
child_process
模块提供了衍生子进程的能力
child_process(子进程)
http://nodejs.cn/api/child_process.html
exec()创建子进程执行shell命令
child_process.exec(command[, options][, callback])
创建一个shell,然后在shell里执行命令。执行完成后,将 (error, stdout, stderr) 作为参数传入回调方法
如果提供了 callback,则调用时传入参数 (error, stdout, stderr)。
当成功时,则 error 将会为 null。 当出错时,则 error 将会是 Error 的实例。
error.code 属性将会是子进程的退出码, error.signal 将会被设为终止进程的信号。 除 0 以外的任何退出码都被视为出错。
传给回调的 stdout 和 stderr 参数将会包含子进程的 stdout 和 stderr 输出。 默认情况下,Node.js 会将输出解码为 UTF-8 并将字符串传给回调。
execFile()执行shell脚本
child_process.execFile(file[, args][, options][, callback])
child_process.execFile() 函数类似于 child_process.exec(),但默认情况下不会衍生 shell。
相反,指定的可执行文件 file 会作为新进程直接地衍生,使其比 child_process.exec() 稍微更高效。
由于没有衍生 shell,因此不支持 I/O 重定向和文件通配等行为。
从node源码来看,exec()、execFile()最大的差别,就在于是否创建了shell。(execFile()内部,options.shell === false),那么,可以手动设置shell。
所以下面两种方式是等价的
var child_process = require('child_process');
var execFile = child_process.execFile;
var exec = child_process.exec;
exec('ls -al .', function(error, stdout, stderr){
if(error){
throw error;
}
console.log(stdout);
});
execFile('ls -al .', {shell: '/bin/bash'}, function(error, stdout, stderr){
if(error){
throw error;
}
console.log(stdout);
});
Error: spawn shell.sh EACCES
原因:没有执行 shell 脚本的执行权限
解决:
给启动 node 进程的用户该脚本的可执行权限即可
Error: spawn /home/centos/git/hexo/nodejs/doker_deploy.sh EACCES
at Process.ChildProcess._handle.onexit (internal/child_process.js:264:19)
at onErrorNT (internal/child_process.js:456:16)
at processTicksAndRejections (internal/process/task_queues.js:80:21) {
errno: 'EACCES',
code: 'EACCES',
syscall: 'spawn /home/centos/git/hexo/nodejs/doker_deploy.sh',
path: '/home/centos/git/hexo/nodejs/doker_deploy.sh',
spawnargs: [],
cmd: '/home/centos/git/hexo/nodejs/doker_deploy.sh'
}
nodejs启动web服务器
child_process(子进程)
http://nodejs.cn/api/child_process.html
Node.js 提供了 http 模块,http 模块主要用于搭建 HTTP 服务端和客户端,使用 HTTP 服务器或客户端功能必须调用 http 模块,代码如下:
var http = require('http');
新建一个 webapp.js 文件
//引入http模块
var http = require("http");
//设置主机名
var hostName = '127.0.0.1';
//设置端口
var port = 8080;
//创建服务
var server = http.createServer(function(req, res) {
res.setHeader('Content-Type','text/plain');
res.end("hello nodejs");
});
server.listen(port, hostName, function(){
console.log(`服务器运行在http://${hostName}:${port}`);
});
后台运行nohup node webapp.js &
nodejs搭建web服务器就是这么简单!
https://blog.csdn.net/ZACH_ZHOU/article/details/72779762
nodejs启动web服务做webhooks
新建一个 webhooks.js 文件,内容如下:
// nodejs启动一个http服务监听1121端口响应webhook
var http = require('http')
var exec = require('child_process').exec
http.createServer(function (request, response) {
// 解决中文乱码问题
response.writeHead(200, {'Content-Type': 'text/plain; charset=utf-8'});
response.write(request.url + " ");
// 该路径与git中配置的WebHooks中的路径部分需要完全匹配
// 博客html git目录
if(request.url === '/pull/madaimeng') {
// 异步执行shell命令,拉取最新代码
exec('cd /home/ec2-user/git/madaimeng && git pull', function(err,stdout,stderr) {
if(err) {
console.log('Git pull error: ' + stderr);
response.write('Git pull error: ' + stderr);
} else {
// 这个stdout的内容就是shell结果
console.log('Git pull done. ' + stdout);
response.write('Git pull done. ' + stdout);
}
response.end();
});
}
// 博客源码git目录
if(request.url === '/pull/madaimeng_backup') {
// 异步执行shell命令,拉取最新代码
exec('cd /home/ec2-user/git/madaimeng_backup && git pull', function(err,stdout,stderr) {
if(err) {
console.log('Git pull error: ' + stderr);
response.write('Git pull error: ' + stderr);
} else {
// 这个stdout的内容就是shell结果
console.log('Git pull done. ' + stdout);
response.write('Git pull done. ' + stdout);
}
response.end();
});
}
}).listen(1121);
console.log("Server has started.");
后台运行nohup node webhooks.js &
在vps本地测试
curl 127.0.0.1:1121/pull/madaimeng
或
curl localhost:1121/pull/madaimeng
$ curl localhost:1121/pull/madaimeng
当前目录: /home/ec2-user/git/madaimeng
Git pull done. 已经是最新的。
$ curl localhost:1121/pull/madaimeng_backup
当前目录: /home/ec2-user/git/madaimeng_backup
Git pull done. 已经是最新的。
利用Github的Webhook功能和Node.js完成项目的自动部署
https://www.jianshu.com/p/e4cacd775e5b
Hexo快速搭建静态博客并实现远程VPS自动部署
https://segmentfault.com/a/1190000006745478
异步调用改同步调用
一开始这么写的代码,发现每次触发后其实并没有更新 /home/ec2-user/git/madaimeng 中的代码
后来才想到,我的两个 exec
调用都是异步的,也就是同时开始执行的,执行git pull时还处于当前目录(非/home/ec2-user/git/madaimeng目录),也就是还没cd到目标目录中,所以肯定更新不了。
解决方法:
1、把cd
进入目录那一步由异步调用改为同步调用,使用 execSync
代替 exec
,后来发现这样不行,因为两个 exec
开的是不同的子进程,互相独立的
2、把两个exec
合并为一个,使用 &&
连接cd
和git pull
命令。
当时代码如下:
// nodejs启动一个http服务监听1121端口响应webhook
var http = require('http')
var exec = require('child_process').exec
http.createServer(function (request, response) {
// 解决中文乱码问题
response.writeHead(200, {'Content-Type': 'text/plain; charset=utf-8'});
// 该路径与git中配置的WebHooks中的路径部分需要完全匹配
// 博客html git目录
if(request.url === '/pull/madaimeng') {
// 进入目标目录并打印目录
exec('cd /home/ec2-user/git/madaimeng && pwd', function(err,stdout,stderr) {
console.log('当前目录: ' + stdout);
response.write('当前目录: ' + stdout);
});
// 执行命令,拉取最新代码
exec('git pull', function(err,stdout,stderr) {
if(err) {
console.log('Git pull error: ' + stderr);
response.write('Git pull error: ' + stderr);
} else {
// 这个stdout的内容就是shell结果
console.log('Git pull done. ' + stdout);
response.write('Git pull done. ' + stdout);
}
response.end();
});
}
}).listen(1121);
console.log("Server has started.");
Node.js Error: write after end 错误
nodejs 启动 web 服务中处理请求时报错
events.js:183
throw er; // Unhandled 'error' event
^
Error: write after end
at write_ (_http_outgoing.js:622:15)
at ServerResponse.write (_http_outgoing.js:617:10)
at /home/ec2-user/git/madaimeng_backup/webhooks.js:19:19
at ChildProcess.exithandler (child_process.js:273:7)
at emitTwo (events.js:126:13)
at ChildProcess.emit (events.js:214:7)
at maybeClose (internal/child_process.js:915:16)
at Process.ChildProcess._handle.onexit (internal/child_process.js:209:5)
报错的 webhooks.js 代码如下
// nodejs启动一个http服务监听1121端口响应webhook
var http = require('http')
var exec = require('child_process').exec
http.createServer(function (req, res) {
// 该路径与git中配置的WebHooks中的路径部分需要完全匹配
if(req.url === '/pull'){
exec('pwd', function(err,stdout,stderr) {
console.log('当前目录: ' + stdout);
});
// 执行命令,拉取最新代码
exec('git pull', function(err,stdout,stderr) {
if(err) {
console.log('Git pull error: ' + stderr);
res.write('Git pull error: ' + stderr);
} else {
// 这个stdout的内容就是shell结果
console.log('Git pull done. ' + stdout);
res.write('Git pull done. ' + stdout);
}
});
res.end();
}
}).listen(1121);
console.log("Server has started.");
原因是 node 中的方法调用都是异步执行后再回调的,在我的代码中,res.end();
放在了exec
函数之后的主进程中, exec
方法执行后回调 function 向res中写入响应体,但主流程中已经 res.end();
了,所以肯定会出现 write after end
错误,其实是对 node 的原理不熟悉。
把 res.end;
放到回调方法中的 res.write();
之后,或者直接 res.end(body);
即可。
yum安装nodejs和npm
Node.js官方安装指南:
Installing Node.js via package manager
https://nodejs.org/en/download/package-manager/
Red Hat Enterprise Linux / CentOS / Fedora 等发行版安装指南如下:
NodeSource Node.js Binary Distributions
https://github.com/nodesource/distributions/blob/master/README.md
使用官方脚本添加NodeSource源
nodejs 官方制作了添加 node 源的在线脚本,直接下载执行就行,不需要再手动添加 epel 和 remi 源了
# As root
curl -sL https://rpm.nodesource.com/setup_14.x | bash -
# No root privileges
curl -sL https://rpm.nodesource.com/setup_14.x | sudo bash -
最后会提示执行 sudo yum install -y nodejs
来安装 nodejs 和 npm
yum安装nodejs
按照安装 NodeSource 源时输出信息的提示,使用 yum 来安装 nodejssudo yum install -y nodejs
安装 nodejs 时自动会安装 npm 工具,完成后查看版本验证安装成功:
$ node -v
v14.8.0
$ npm -v
6.14.7
Node版本管理工具n
n 是一款 Node 版本管理工具,它本身也是一个 Node 模块,这个工具的名字就叫 n
安装node版本管理工具n
sudo npm install n -g
安装 node 版本管理模块 n
安装最新稳定版node
sudo n stable
安装最新稳定版 node
比如我当前的 node 版本是 14.8.0,稳定版是 12.18.3
$ node -v
v14.8.0
$ sudo n stable
installing : node-v12.18.3
mkdir : /usr/local/n/versions/node/12.18.3
fetch : https://nodejs.org/dist/v12.18.3/node-v12.18.3-linux-x64.tar.xz
installed : v12.18.3 to /usr/local/bin/node
active : v14.8.0 at /bin/node
安装最新版node
sudo n latest
安装最新版 node
安装最新LTS版node
sudo n lts
安装最新LTS版node
安装指定版本node
sudo n 版本号
安装指定版本node
切换默认node版本
安装完成多个版本后,直接输入不带参数的 n 命令,会出现一个已安装版本的列表
用键盘上下键选择版本,然后回车,就可以切换默认 Node 版本。
删除指定版本node
sudo n rm 版本号
删除指定版本node
下一篇 Spring-Cache
页面信息
location:
protocol
: host
: hostname
: origin
: pathname
: href
: document:
referrer
: navigator:
platform
: userAgent
: