node调用命令行值得学习一下

基本调用 spawn
  • https://nodejs.org/dist/latest-v15.x/docs/api/child_process.html
const { spawn } = require('child_process');
const ls = spawn('ls', ['-lh', '/usr']);

ls.stdout.on('data', (data) => {
  console.log(`stdout: ${data}`);
});

ls.stderr.on('data', (data) => {
  console.error(`stderr: ${data}`);
});

ls.on('close', (code) => {
  console.log(`child process exited with code ${code}`);
});
spawn背后的故事
  • child_process.exec
    • 直接调用了这个: module.exports.execFile
    • 实际还是调用了spawn
  • child_process.spawn()调用了internalBinding, 也就是node的C++部分
  • 参见: https://medium.com/front-end-weekly/internals-of-node-advance-node-%EF%B8%8F-8612f6a957d7
spawn的包装函数
  • 有四个函数对spawn进行了包装.
    • child_process.spawn(),
    • child_process.fork()执行并且建立一个IPC channel, 可以传消息
    • child_process.exec()包装spawn, 并且使用新的shell
    • child_process.execFile()包装spawn, 但是不使用新的shell,
  • 这四个函数都返回childprocess实例
    • childprocess实现了eventEmitter, 因此可以注册listener
    • childprocess还实现了很多方法和事件, 可以参考官方文档
    • exec和execfile还可以传入一个回调函数, 在完成命令后回调
    • 注意不要望文生义, 以为execFile是执行文件的, 其实不论哪一个, 都可以执行可执行文件.
exec和promise
# exec方式
exec 'cat *.js missing_file | wc -l', (error, stdout, stderr) ->
	if error
		console.log chalk.yellowBright "exec"
		console.error chalk.redBright "exec error: #{error}"
		return
	console.log chalk.yellowBright "exec"
	console.log chalk.greenBright "stdout: #{stdout}"
	console.error chalk.redBright "stderr: #{stderr}"
# promise的exec
px = util.promisify exec
do ->
	{ stdout, stderr } = await px 'ls -a .*'
	console.log chalk.yellowBright "execpromise"
	console.log 'stdout:', chalk.greenBright stdout
	console.error 'stderr:', chalk.redBright stderr
# 最简洁的exec
const {exec} = require("child_process")
exec('yourApp').unref() # 参考文档中的subprocess.unref(), 这个意思是不等待子进程完成, 父进程直接退出.
异常的catch
import { spawn,exec } from 'child_process'
px = util.promisify exec
cmd="sudo #{cmdpath}/apfs-recover /dev/#{disk} 0 \"#{frompath}\" > \"#{topath}\""
try
	{ stdout, stderr } = await px cmd
catch err
	console.log chalk.redBright "copy error:#{frompath}"
命令的退出码
dir = exec("ls -la", function(err, stdout, stderr) {
  if (err) {
    // should have err.code here?  
  }
  console.log(stdout);
});

dir.on('exit', function (code) {
  // exit code is code
});