详解从Node.js的child_process模块来学习父子进程之间的通信

child_process模块提供了和popen(3)一样的方式来产生自进程,这个功能主要是通过child_process.spawn函数来提供的:

const spawn = require('child_process').spawn;
const ls = spawn('ls', ['-lh', '/usr']);
ls.stdout.on('data', (data) => {
 console.log(`stdout: ${data}`);
});
ls.stderr.on('data', (data) => {
 console.log(`stderr: ${data}`);
});
ls.on('close', (code) => {
 console.log(`child process exited with code $[code]`);
});

默认情况下,Node.js进程和子进程之间的stdin,stdout,stderr管道是已经存在的。通常情况下这个方法可以以一种非阻塞的方式来传递数据。(注意,有些程序在内部使用line-buffered I/O。因为这也不会影响到Node.js,这意味着传递给子进程的数据可能不会马上消费)。

chid-process的spawn方法是通过一种异步的方式来产生自进程的,因此不会阻塞Node.js的事件循环,然而child-process.spawnSync方法是同步的,他会阻塞事件循环只到产生的进程退出或者终止。

child_process.exec:产生一个shell客户端,然后使用shell来执行程序,当完成的时候传递给回调函数一个stdout和stderr

child_process.execFile:和exec相似,但是他不会马上产生一个shell

child_process.fork:产生一个新的Node.js进程,同时执行一个特定的模块来产生IPC通道,进而在父进程和子进程之间传输数据

child_process.execSync:和exec不同之处在于会阻塞Node.js的事件循环,然而child-process

child_process.execFileSync:和execFile不同之处在于会阻塞Node.js的事件循环,然而child-process在一些特殊情况下,例如自动化shell脚本,同步的方法可能更加有用。多数情况下,同步的方法会对性能产生重要的影响,因为他会阻塞事件循环

child_process.spawn(), child_process.fork(), child_process.exec(), and child_process.execFile()都是异步的API。每一个方法都会产生一个ChildProcess实例,而且这个对象实现了Node.js的EventEmitter这个API,于是父进程可以注册监听函数,在子进程的特定事件触发的时候被调用。 child_process.exec() 和 child_process.execFile()可以指定一个可选的callback函数,这个函数在子进程终止的时候被调用。

在windows平台上执行.bat和.cmd:

child_process.exec和child_process.execFile的不同之处可能随着平台不同而有差异。在Unit/Linux/OSX平台上execFile更加高效,因为他不会产生shell。在windows上,.bat/.cmd在没有终端的情况下是无法执行的,因此就无法使用execFile(child_process.spawn也无法使用)。在window上,.bat/.cmd可以使用spawn方法,同时指定一个shell选项;或者使用child_process.exec或者通过产生一个cmd.exe同时把.bat/.cmd文件传递给它作为参数(child_process.exec就是这么做的)。

const spawn = require('child_process').spawn;
const bat = spawn('cmd.exe', ['/c', 'my.bat']);//使用shell方法指定一个shell选项
bat.stdout.on('data', (data) => {
 console.log(data);
});
bat.stderr.on('data', (data) => {
 console.log(data);
}); 

bat.on('exit', (code) => {
 console.log(`Child exited with code $[code]`);
}); 

或者也可以使用如下的方式:

const exec = require('child_process').exec;//产生exec,同时传入.bat文件
exec('my.bat', (err, stdout, stderr) => {
 if (err) {
  console.error(err);
  return;
 }
 console.log(stdout);
}); 

child_process.exec(command[, options][, callback])

其中options中的maxBuffer参数表示stdout/stderr允许的最大的数据量,如果超过了数据量那么子进程就会被杀死,默认是200*1024比特;killSignal默认是'SIGTERM'。其中回调函数当进程结束时候调用,参数分别为error,stdout,stderr。这个方法返回的是一个ChildProcess对象。

const exec = require('child_process').exec;
const child = exec('cat *.js bad_file | wc -l',
 (error, stdout, stderr) => {
  console.log(`stdout: ${stdout}`);
  console.log(`stderr: ${stderr}`);
  if (error !== null) {
   console.log(`exec error: ${error}`);
  }
});

上面的代码产生一个shell,然后使用这个shell执行命令,同时对产生的结果进行缓存。其中回调函数中的error.code属性表示子进程的exit code,error.signal表示结束这个进程的信号,任何非0的代码表示出现了错误。默认的options参数值如下:

{
 encoding: 'utf8',
 timeout: 0,
 maxBuffer: 200*1024,//stdout和stderr允许的最大的比特数据,超过她子进程就会被杀死
 killSignal: 'SIGTERM',
 cwd: null,
 env: null
} 

如果timeout非0,那么父进程就会发送信号,这个信号通过killSignal指定,默认是"SIGTERM"来终结子进程,如果子进程超过了timeout指定的时间。注意:和POSIX系统上调用exec方法不一样的是,child_process.exec不会替换当前线程,而是使用一个shell去执行命令

child_process.execFile(file[, args][, options][, callback])

其中file表示需要执行的文件。 child_process.execFile()和exec很相似,但是这个方法不会产生一个shell。指定的可执行文件会马上产生一个新的线程,因此其效率比child_process.exec高。

const execFile = require('child_process').execFile;
const child = execFile('node', ['--version'], (error, stdout, stderr) => {
 if (error) {
  throw error;
 }
 console.log(stdout);
});

因为不会产生shell,一些I/O redirection和file globbing这些行为不支持

child_process.fork(modulePath[, args][, options])

其中modulePath表示要在子线程中执行的模块。其中options中的参数silent如果设置为true,那么子进程的stdin, stdout, stderr将会被传递给父进程,如果设置为false那么就会从父进程继承。execArgv默认的值为process.execArgv,execPath表示用于创建子进程的可执行文件。这个fork方法是child_process.spawn的一种特殊用法,用于产生一个Node.js的子进程,和spawn一样返回一个ChildProcess对象。返回的ChildProcess会有一个内置的传输通道用于在子进程和父进程之间传输数据(用ChildProcess的send方法完成)。我们必须注意,产生的Node.js进程和父进程之间是独立的,除了他们之间的IPC传输通道以外。每一个进程有独立的内存,有自己独立的V8引擎。由于产生一个子进程需要其他额外的资源分配,因此产生大量的子进程不被提倡。默认情况下,child_process.fork会使用父进程的process.execPath来产生一个Node.js实例,options中的execPath允许指定一个新的路径。通过指定execPath产生的新的进程和父进程之间通过文件描述符(子进程的环境变量NODE_CHANNEL_FD)来通信。这个文件描述符上的input/output应该是一个JSON对象。和POSIX系统调用fork不一样的是,child_process.fork不会克隆当前的进程

最后,我们来看看子进程和父进程之间是如何通信的:

服务器端的代码:

var http = require('http');
var cp = require('child_process');
var server = http.createServer(function(req, res) {
  var child = cp.fork(__dirname + '/cal.js');
  //每个请求都单独生成一个新的子进程
  child.on('message', function(m) {
    res.end(m.result + '\n');
  });
  //为其指定message事件
  var input = parseInt(req.url.substring(1));
  //和postMessage很类似,不过这里是通过send方法而不是postMessage方法来完成的
  child.send({input : input});
});
server.listen(8000);

子进程的代码:

function fib(n) {
  if (n < 2) {
    return 1;
  } else {
    return fib(n - 2) + fib(n - 1);
  }
}
//接受到send传递过来的参数
process.on('message', function(m) {
  //console.log(m);
  //打印{ input: 9 }
  process.send({result: fib(m.input)});
}); 

child_process.spawn(command[, args][, options])

其中options对象的stdio参数表示子进程的stdio配置;detached表示让子进程在父进程下独立运行,这个行为与平台有关;shell如果设置为true那么就会在shell中执行命令。这个方法通过指定的command来产生一个新的进程,如果第二个参数没有指定args那么默认就是一个空的数组,第三个参数默认是如下对象,这个参数也可以用于指定额外的参数:

{
 cwd: undefined, //产生这个进程的工作目录,默认继承当前的工作目录
 env: process.env//这个参数用于指定对于新的进程可见的环境变量,默认是process.env
}

其中cwd用于指定子进程产生的工作目录,如果没有指定表示的就是当前工作目录。env用于指定新进程的环境变量,默认为process.env。下面的例子展示了使用ls -lh/usr来获取stdout,stderr以及exit code:

const spawn = require('child_process').spawn;
const ls = spawn('ls', ['-lh', '/usr']);
ls.stdout.on('data', (data) => {
 console.log(`stdout: ${data}`);
});
ls.stderr.on('data', (data) => {
 console.log(`stderr: ${data}`);
});
ls.on('close', (code) => {
 console.log(`child process exited with code $[code]`);
});

下面是一个很详细的运行"ps ax|grep ssh"的例子:

const spawn = require('child_process').spawn;
const ps = spawn('ps', ['ax']);
const grep = spawn('grep', ['ssh']);
ps.stdout.on('data', (data) => {
 grep.stdin.write(data);
});
ps.stderr.on('data', (data) => {
 console.log(`ps stderr: ${data}`);
});
ps.on('close', (code) => {
 if (code !== 0) {
  console.log(`ps process exited with code $[code]`);
 }
 grep.stdin.end();
});
grep.stdout.on('data', (data) => {
 console.log(`${data}`);
});
grep.stderr.on('data', (data) => {
 console.log(`grep stderr: ${data}`);
});
grep.on('close', (code) => {
 if (code !== 0) {
  console.log(`grep process exited with code $[code]`);
 }
});

用下面的例子来检查错误的执行程序:

const spawn = require('child_process').spawn;
const child = spawn('bad_command');
child.on('error', (err) => {
 console.log('Failed to start child process.');
}); 

options.detached:

在windows上,把这个参数设置为true的话,这时候如果父进程退出了那么子进程还会继续运行,而且子进程有自己的console window。如果把子进程设置了这个为true,那么就不能设置为false了。在非window平台上,如果把这个设置为true,子进程就会成为进程组合和session的leader,这时候子进程在父进程退出以后会继续执行,不管子进程是否detached。可以参见setsid(2)。

默认情况下,父进程会等待detached子进程,然后退出。要阻止父进程等待一个指定的子进程可以使用child.unref方法,这个方法会让父进程的事件循环不包括子进程,这时候允许父进程独立退出,除非在父进程和子进程之间有一个IPC通道。下面是一个detach长期运行的进程然后把它的输出导向到一个文件:

const fs = require('fs');
const spawn = require('child_process').spawn;
const out = fs.openSync('./out.log', 'a');
const err = fs.openSync('./out.log', 'a');
const child = spawn('prg', [], {
 detached: true,//依赖于父进程
 stdio: [ 'ignore', out, err ]
});
child.unref();//允许父进程单独退出,不用等待子进程

当使用了detached选项去产生一个长期执行的进程,这时候如果父进程退出了那么子进程就不会继续执行了,除非指定了一个stdio配置(不和父进程之间有联系)。如果父进程的stdio是继承的,那么子进程依然会和控制终端之间保持关系。

options.stdio

这个选项用于配置父进程和子进程之间的管道。默认情况下,子进程的stdin,stdout,stderr导向了ChildProcess这个对象的child.stdin,child.stdout,child.stderr流,这和设置stdio为['pipe','pipe','pipe']是一样的。stdio可以是下面的任何一个字符串:

'pipe':相当于['pipe','pipe','pipe'],为默认选项

'ignore':相当于['ignore','ignore','ignore']

'inherit':相当于[process.stdin,process.stdout,process.stderr]或者[0,1,2]

一般情况下,stdio是一个数组,每一个选项对应于子进程的fd。其中0,1,2分别对应于stdin,stdout,stderr。如果还设置了多于的fds那么就会用于创建父进程和子进程之间的额外的管道,可以是下面的任何一个值:

'pipe':为子进程和父进程之间创建一个管道。父进程管道的末端会作为child_process对象的ChildProcess.stdio[fd]而存在。fds0-2创建的管道在ChildProcess.stdin,ChildProcess.stdout,ChildProcess.stderr也是存在的

'ipc':用于创建IPC通道用于在父进程和子进程之间传输消息或者文件描述符。ChildProcess对象最多有一个IPC stdio文件描述符,使用这个配置可以启用ChildProcess的send方法,如果父进程在文件描述符里面写入了JSON对象,那么ChildProcess.on("message")事件就会在父进程上触发。如果子进程是Node.js进程,那么ipc配置就会启用子进程的process.send(), process.disconnect(), process.on('disconnect'), and process.on('message')方法。

'ignore':让Node.js子进程忽视文件描述符。因为Node.js总是会为子进程开启fds0-2,设置为ignore就会导致Node.js去开启/dev/null,同时把这个值设置到子进程的fd上面。

'strem':和子进程之间共享一个可读或者可写流,比如file,socket,pipe。这个stream的文件描述符和子进程的文件描述符fd是重复的。注意:流必须有自己的文件描述符

正整数:表示父进程的打开的文件描述符。和stream对象可以共享一样,这个文件描述符在父子进程之间也是共享的
null/undefined:使用默认值。stdio的fds0,1,2管道被创建(stdin,stdout,stderr)。对于fd3或者fdn,默认为'ignore'

const spawn = require('child_process').spawn;
// Child will use parent's stdios
//使用父进程的stdios
spawn('prg', [], { stdio: 'inherit' });
//产生一个共享process.stderr的子进程
// Spawn child sharing only stderr
spawn('prg', [], { stdio: ['pipe', 'pipe', process.stderr] });
// Open an extra fd=4, to interact with programs presenting a
// startd-style interface.
spawn('prg', [], { stdio: ['pipe', null, null, null, 'pipe'] });

注意:当子进程和父进程之间建立了IPC通道,同时子进程为Node.js进程,这时候开启的具有IPC通道的子进程(使用unref)直到子进程注册了一个disconnect的事件处理句柄process.on('disconnect'),这样就会允许子进程正常退出而不会由于IPC通道的打开而持续运行。

Class: ChildProcess

这个类的实例是一个EventEmitters,用于代表产生的子进程。这个类的实例不能直接创建,必须使用 child_process.spawn(), child_process.exec(), child_process.execFile(), or child_process.fork()来完成

'close'事件:

其中code表示子进程退出的时候的退出码;signal表示终止子进程发出的信号;这个事件当子进程的stdio stream被关闭的时候触发,和exit事件的区别是多个进程可能共享同一个stdio streams!(所以一个进程退出了也就是exit被触发了,这时候close可能不会触发)

'exit'事件:

其中code表示子进程退出的时候的退出码;signal表示终止子进程发出的信号。这个事件当子进程结束的时候触发,如果进程退出了那么code表示进程退出的exit code,否则没有退出就是null。如果进程是由于收到一个信号而终止的,那么signal就是这个信号,是一个string,默认为null。

注意:如果exit事件被触发了,子进程的stdio stream可能还是打开的;Node.js为SUGUBT,SIGTERM创建信号处理器,而且Node.js进程在收到信号的时候不会马上停止。Node.js会进行一系列的清理工作,然后才re-raise handled signal。见waitpid(2)

'disconnect'事件:

在子进程或者父进程中调用ChildProcess.disconnect()方法的时候会触发。这时候就不能再发送和接受信息了,这是ChildProcess.connected就是false了

'error'事件:

当进程无法产生的时候,进程无法杀死的时候,为子进程发送消息失败的时候就会触发。注意:当产生错误的时候exit事件可能会也可能不会触发。如果你同时监听了exit和error事件,那么就要注意是否会无意中多次调用事件处理函数

'message'事件:

message参数表示一个解析后的JSON对象或者初始值;sendHandle可以是一个net.Socket或者net.Server对象或者undefined。当子进程调用process.send时候触发

child.connected:

调用了disconnect方法后就会是false。表示是否可以在父进程和子进程之间发送和接受数据,当值为false就不能发送数据了
 child.disconnect()

关闭子进程和父进程之间的IPC通道,这时候子进程可以正常退出如果没有其他的连接使得他保持活动。这时候父进程的child.connected和子进程的process.connected就会设置为false,这时候不能传输数据了。disconnect事件当进程没有消息接收到的时候被触发,当调用child.disconnect时候会立即触发。注意:当子进程为Node.js实例的时候如child_process.fork,这时候process.disconnect方法就会在子进程中调用然后关闭IPC通道。

child.kill([signal])

为子进程传入消息,如果没有指定参数那么就会发送SIGTERM信号,可以参见signal(7)来查看一系列信号

const spawn = require('child_process').spawn;
const grep = spawn('grep', ['ssh']);
grep.on('close', (code, signal) => {
 console.log(
  `child process terminated due to receipt of signal ${signal}`);
});
// Send SIGHUP to process
grep.kill('SIGHUP');

ChildProcess对象在无法传输信号的时候会触发error事件。为一个已经退出的子进程发送信号虽然无法报错但是可能导致无法预料的结果。特别的,如果这个PID已经被分配给另外一个进程那么这时候也会导致无法预料的结果。

child.pid:

返回进程的PID值

const spawn = require('child_process').spawn;
const grep = spawn('grep', ['ssh']);
console.log(`Spawned child pid: ${grep.pid}`);
grep.stdin.end();//通过grep.stdin.end结束

child.send(message[, sendHandle][, callback])

当父子进程之间有了IPC通道,child.send就会为子进程发送消息,当子进程为Node.js实例,那么可以用process.on('message')事件接收

父进程为:

const cp = require('child_process');
const n = cp.fork(`${__dirname}/sub.js`);
n.on('message', (m) => {
 console.log('PARENT got message:', m);
});
n.send({ hello: 'world' }); 

子进程为:

process.on('message', (m) => {
 console.log('CHILD got message:', m);
});
process.send({ foo: 'bar' }); 

子进程使用process.send方法为父进程发送消息。有一个特例,发送{cmd: 'NODE_foo'}。当一个消息在他的cmd属性中包含一个NODE_前缀会被看做使用Node.js核心(被Node.js保留)。这时候不会触发子进程的process.on('message')。而是使用process.on('internalMessage')事件,同时会被Node.js内部消费,一般不要使用这个方法。sendHandle这个用于给子进程传入一个TCP Server或者一个socket,为process.on('message')回调的第二个参数接受。callback当消息已经发送,但是子进程还没有接收到的时候触发,这个函数只有一个参数成功为null否则为Error对象。如果没有指定callback同时消息也不能发送ChildProcess就会触发error事件。当子进程已经退出就会出现这个情况。child.send返回false如果父子进程通道已经关闭,或者积压的没有传输的数据超过一定的限度,否则这个方法返回true。这个callback方法可以用于实现流控制:

下面是发送一个Server的例子:

const child = require('child_process').fork('child.js');
// Open up the server object and send the handle.
const server = require('net').createServer();
server.on('connection', (socket) => {
 socket.end('handled by parent');
});
server.listen(1337, () => {
 child.send('server', server);
});

子进程接受这个消息:

process.on('message', (m, server) => {
 if (m === 'server') {
  server.on('connection', (socket) => {
   socket.end('handled by child');
  });
 }
}); 

这时候server就被子进程和父进程共享了,一些连接可以被父进程处理,一些被子进程处理。上面的例子如果使用dgram那么就应该监听message事件而不是connection,使用server.bind而不是server.listen,但是当前只在UNIX平台上可行。
下面的例子展示发送一个socket对象(产生两个子进程,处理normal和special优先级):

父进程为:

const normal = require('child_process').fork('child.js', ['normal']);
const special = require('child_process').fork('child.js', ['special']);
// Open up the server and send sockets to child
const server = require('net').createServer();
server.on('connection', (socket) => {
 // If this is special priority
 if (socket.remoteAddress === '74.125.127.100') {
  special.send('socket', socket);
  return;
 }
 // This is normal priority
 normal.send('socket', socket);
});
server.listen(1337); 

子进程为:

process.on('message', (m, socket) => {
 if (m === 'socket') {
  socket.end(`Request handled with ${process.argv[2]} priority`);
 }
}); 

当socket被发送到子进程的时候那么父进程已经无法追踪这个socket什么时候被销毁的。这时候.connections属性就会成为null,因此我们建议不要使用.maxConnections。注意:这个方法在内部JSON.stringify去序列化消息

child.stderr:

一个流对象,是一个可读流表示子进程的stderr。他是child.stdio[2]的别名,两者表示同样的值。如果子进程是通过stdio[2]产生的,设置的不是pipe那么值就是undefined。

child.stdin:

一个可写的流对象。注意:如果子进程等待读取输入,那么子进程会一直等到流调用了end方法来关闭的时候才会继续读取。如果子进程通过stdio[0]产生,同时不是设置的pipe那么值就是undefined。child.stdin是child.stdio[0]的别名,表示同样的值。

const spawn = require('child_process').spawn;
const grep = spawn('grep', ['ssh']);
console.log(`Spawned child pid: ${grep.pid}`);
grep.stdin.end();//通过grep.stdin.end结束  

child.stdio:

一个子进程管道的稀疏数组,是 child_process.spawn()函数的stdio选项,同时这个值被设置为pipe。child.stdio[0], child.stdio[1], 和 child.stdio[2]也可以通过child.stdin, child.stdout, 和 child.stderr访问。下面的例子中只有子进程的fd1(也就是stdout)被设置为管道,因此只有父进程的child.stdio[1]是一个流,其他的数组中对象都是null:

const assert = require('assert');
const fs = require('fs');
const child_process = require('child_process');
const child = child_process.spawn('ls', {
  stdio: [
   0, // Use parents stdin for child
   'pipe', // Pipe child's stdout to parent
   fs.openSync('err.out', 'w') // Direct child's stderr to a file
  ]
});
assert.equal(child.stdio[0], null);
assert.equal(child.stdio[0], child.stdin);
assert(child.stdout);
assert.equal(child.stdio[1], child.stdout);
assert.equal(child.stdio[2], null);
assert.equal(child.stdio[2], child.stderr);

child.stdout:

一个可读流,代表子进程的stdout。如果子进程产生的时候吧stdio[1]设置为除了pipe以外的任何数,那么值就是undefined。其值和child.stdio[1]一样

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 基于socket.io和node.js搭建即时通信系统

    使用socket.io和nodejs搭建websocket服务器端 socket.io不仅可以搭建客户端的websocket服务,而且支持nodejs服务器端的websocket. 下面让我来介绍一下怎么安装配置nodejs. 进入http://nodejs.org/#download下载msi文件.一直点next安装.最后文件会自动安装在C:\nodejs目录下. 安装完成后,会自动配置环境环境变量.如果没有自动配置,自己手动在path处加上 ;C:\nodejs\. 安装完成后,需要配置np

  • WebSocket+node.js创建即时通信的Web聊天服务器

    本文实例node.js创建即时通信的Web聊天服务器,供大家参考,具体内容如下 1.使用nodejs-websocket  nodejs-websocket是基于node.js编写的一个后端实现websocket协议的库,  连接:https://github.com/sitegui/nodejs-websocket.  (1)安装  在项目目录下通过npm安装:npm install nodejs-websocket  (2)创建服务器 //引入nodejs-websocket var ws

  • 使用DNode实现php和nodejs之间通信的简单实例

    一.安装DNode 1, for nodejs, 执行 复制代码 代码如下: $ sudo npm install dnode 2, for php, 利用composer来安装DNode php 执行下列语句下载composer 复制代码 代码如下: $ wget http://getcomposer.org/composer.phar 创建一个文件composer.json,然后填入如下语句, 复制代码 代码如下: {     "require": {         "

  • iOS + node.js使用Socket.IO框架进行实时通信示例

    Socket.IO是一个基于WebSocket的实时通信库,在主流平台都有很好的支持,此文主要是通过一个小例子来演示Socket.IO的使用. 基础环境搭建 新建一个文件夹(JS工程),创建一个package.json,复制以下内容并保存. { "name": "socket-chat-example", "version": "0.0.1", "description": "my first s

  • 基于Node.js的WebSocket通信实现

    node的依赖包 node中实现Websocket的依赖包有很多,websocket.ws均可,本文选取ws来实现,首先安装依赖 npm install ws 聊天室实例 假如A,B,C,D用户均通过客户端连接到Websocket服务,其中每个人发的消息都需要将其通过Websocket转发给其他人,此场景类似于服务端将A的消息广播给组内其他用户. 服务端实现 首先来看服务端程序,具体的工作流程分以下几步: 创建一个WebSocketServer的服务,同时监听8080端口的连接请求. 每当有新的

  • nodejs socket服务端和客户端简单通信功能

    本文实例讲述了通过node.js的net模块实现nodejs socket服务端和客户端简单通信功能,可以用作客户端对服务端的端口监听以及事件回执. server端代码 var net = require('net'); //模块引入 var listenPort = 8080;//监听端口 var server = net.createServer(function(socket){ // 创建socket服务端 console.log('connect: ' + socket.remoteA

  • 详解从Node.js的child_process模块来学习父子进程之间的通信

    child_process模块提供了和popen(3)一样的方式来产生自进程,这个功能主要是通过child_process.spawn函数来提供的: const spawn = require('child_process').spawn; const ls = spawn('ls', ['-lh', '/usr']); ls.stdout.on('data', (data) => { console.log(`stdout: ${data}`); }); ls.stderr.on('data'

  • 详解阿里Node.js技术文档之process模块学习指南

    模块概览 process是node的全局模块,作用比较直观.可以通过它来获得node进程相关的信息,比如运行node程序时的命令行参数.或者设置进程相关信息,比如设置环境变量. 环境变量:process.env 使用频率很高,node服务运行时,时常会判断当前服务运行的环境,如下所示 if(process.env.NODE_ENV === 'production'){ console.log('生产环境'); }else{ console.log('非生产环境'); } 运行命令 NODE_EN

  • 详解在node.js中require方法的加载规则

    require 方法的加载规则 优先从缓存中加载 核心模块 路径形式的模块 第三方模块 一.优先从缓存中加载 main.js:执行加载a.js模块 require('./a') a.js:执行加载b.js模块,并输出a被加载了 require('./b') console.log('a.js 被加载了') b.js:输出b被加载了 console.log('b.js 被加载了') 结果: 可以看出:main去加载a.js,然后a在去加载b.js过程中,并没有打印两次 a.js被加载,Node会直

  • 详解用Node.js写一个简单的命令行工具

    本文介绍了用Node.js写一个简单的命令行工具,分享给大家,具体如下: 操作系统需要为Linux 1. 目标 在命令行输入自己写的命令,完成目标任务 命令行要求全局有效 命令行要求可以删除 命令行作用,生成一个文件,显示当前的日期 2. 代码部分 新建一个文件,命名为sherryFile 文件sherryFile的内容 介绍: 生成一个文件,文件内容为当前日期和创建者 #! /usr/bin/env node console.log('command start'); const fs = r

  • 详解使用 Node.js 开发简单的脚手架工具

    前言 像我们熟悉的 vue-cli,react-native-cli 等脚手架,只需要输入简单的命令 vue init webpack project,即可快速帮我们生成一个初始项目.在实际工作中,我们可以定制一个属于自己的脚手架,来提高自己的工作效率. 为什么需要需要脚手架? 减少重复性的工作,不再需要复制其他项目再删除无关代码,或者从零创建一个项目和文件. 根据交互动态生成项目结构和配置文件等. 多人协作更为方便,不需要把文件传来传去. 思路 要开发脚手架,首先要理清思路,脚手架是如何工作的

  • 详解把Node.js项目部署到阿里云服务器(CentOs)

    最近用node.js开发了一个web项目,开发完打算先部署到我自己买的阿里云学生服务器上,让客户先试用下网站.不知道如何把node.js项目部署到阿里云服务器,在问了飞哥哥之后,在网上找了下教程,部署成功.把教程整合了一下,做下分享. 服务器 服务器选择了阿里云学生服务器:9.92一个月,适合用来个人开发测试. 配置: 系统:CentOS6.5 64位(Linux系统的一种) 配置环境配置服务器环境 1.在阿里云管理控制台把云服务器实例启动 2.登入服务器:用Putty 或 Xshell(我使用

  • 详解用Node.js实现Restful风格webservice

    Restful风格的WebService正在渐渐取代传统的SOAP, Java 也有很多Restful的框架,很方便简洁,Jersey,restlet,甚至SpringMVC也可以,不得不说Rest让人从Web转型到WebService更容易和方便,当然深入Restful的理论还是发现比较复杂的,但是,开发和理论并不需要那么的贴合,有时候伪Restful更直观,靠谱些. 但是,作为很帅的Node.js怎么可以不和同样帅气的Restful相结合呢!?对于我们这种无视理论的开发者来说,Restful

  • 详解使用Node.js 将txt文件转为Excel文件

    最近同事需要对一份报告进行整理,一共有80个报告约9000多行放在一个txt文件中.虽然每份报告的格式比较类似,但其中部分字段对应的数量依旧会有差别.所以真要靠人工来做,无疑会是一件费时费力的并且是很枯燥的工作.据说如果有了这个程序,可以减少60%的工作量!那么为了我以后的下午茶,自然应该去尝试一下不是么? 不过既然是费时费力又枯燥的工作,自然就应该交给代码去解决.毕竟,我坚信任何的科学技术就是为了让人类偷懒而存在的.那么就先切入正题,先上GitHub的项目地址.欢迎批评指点. GitHub项目

  • 详解本地Node.js服务器作为api服务器的解决办法

    在看react-native教程的时候,遇到要在手机端调试,需要api服务器,但是由于Node.js自己就作为服务器,没有apache怎么解决这个问题,用apache和nginx也可以解决,但是有点复杂,我们就使用node已有的模块解决这个问题. //服务器端的代码 var express = require('express'); var app = express(); // set up handlebars view engine var handlebars = require('ex

  • 详解基于 Node.js 的轻量级云函数功能实现

    导语 在万物皆可云的时代,你的应用甚至不需要服务器.云函数功能在各大云服务中均有提供,那么,如何用"无所不能"的 node.js 实现呢? 一.什么是云函数? 云函数是诞生于云服务的一个新名词,顾名思义,云函数就是在云端(即服务端)执行的函数.各个云函数相互独立,简单且目的单一,执行环境相互隔离.使用云函数时,开发者只需要关注业务代码本身,其它的诸如环境变量.计算资源等,均由云服务提供. 二.为什么需要云函数? 程序员说不想买服务器,于是便有了云服务: 程序员又说连 server 都不

随机推荐