本文目录一览:
- 1、nodejs 怎样检测子进程执行完成
- 2、手把手教你使用nodejs编写cli(命令行)
- 3、如何在nodejs里调用执行系统命令
- 4、Nodejs child_process 模块
- 5、怎样安装node模块child
nodejs 怎样检测子进程执行完成
nodejs是一种单线程模型,但是,使用nodejs的child_process模块可以实现多进程任务。利用child_process可以创建子进程,实现子进程和主进程之间的通信。
nodejs v0.12.7版本child_process提供以下同步和异步的方式创建进程:
异步创建:
child_process.spawn(command[, args][, options])
options.stdio
options.detached
options.customFds
child_process.exec(command[, options], callback)
child_process.execFile(file[, args][, options][callback])
child_process.fork(modulePath[, args][, options])
同步创建:
child_process.spawnSync(command[, args][, options])
child_process.execFileSync(command[, args][, options])
child_process.execSync(command[, options])
手把手教你使用nodejs编写cli(命令行)
前端日常开发中,会遇见各种各样的cli,比如一行命令帮你打包的webpack,一行命令帮你生成vue项目模板的vue-cli,还有创建react项目的create-react-app等等等等。这些工具极大地方便了我们的日常工作,让计算机自己去干繁琐的工作,而我们,就可以节省出大量的时间用于学习、交流、开发、 逛steam 。
但是有时候一些十分特别的需求,我们是找不到适合的cli工具去做的。比如说,你的项目十分庞大,你给项目添加一个新的路由,要经过 创建目录 - 创建.vue文件 - 更新vue-router的路由列表 这一趟流程,就算快捷键创建目录文件用得再熟悉,也比不过你一行命令来得快,特别是路由目录嵌套深,.vue文件初始化模板复杂的时候。
所以呢,何不为自己项目写一个cli?就专门做这些繁琐的活?
nodejs的cli,本质就是跑node脚本嘛,基本上每位前端er都会:
然后命令行调用
可以做得更逼真一点,我们在package.json里面的scripts字段上添加一下脚本名:
然后命令行调用:
但是,看到这里你肯定会说,人家webpack还有vue-cli都是“有名字”的!什么 vue-cli init app 、 webpack -p 的,多漂亮,看看这个命令行, node index.js ,还 npm run hello ,谁不会啊,丑不拉几的,怕又不是来水文章的哦?差评!!
别急啊各位大人,接下来就说说,如何给这个node脚本起个名字。
姑且,先把这个cli的名字命名为 hello-cli ,就是我们能够在命令行里面,输入 hello-cli ,然后它就打印一句 hello world ,没有 node 也没有 npm ,就是:
这样,你的第一个cli脚本就成功安装了,可以在命令行里面,直接敲你的cli名字,看看结果输出吧。
另外,如果你仅希望你的cli脚本仅在项目里执行,则需要在你项目里面新建一个目录,重复上述的操作,只是在第三步的时候,不要llink到全局里面去,而是使用 npm i -D file:你的脚本cli目录路径 ,把它当成项目的依赖安装到node_modules里面去,如果安装成功,那么在项目的package.json你会看到多了一条依赖,这条依赖的值不是版本号,而是你脚本的路径。然后在node_modules里面会有一个.bin目录,里面就存放着你的可执行文件。
当然,这样安装的cli脚本,必须在项目的package.json的scripts字段上声明脚本命令,然后通过 npm run 的方式执行。
哦?这样子使用的话不就回到最最最开始的时候那种原始的 npm run hello 一样么。
是的,但是有质的区别。使用 node index.js 这种方式调用的话固然简单灵活,但是严重依赖脚本路径,一旦目录结构发生变动,写在scripts的命令就要更改一次;但是使用npm安装之后,本地的cli脚本就被拉到node_modules里面,目录结构变动对其影响不大。其次是不利于分享与发布,如果你想把你的cli脚本发布出去,那么有一个好听响亮的名字,比起在说明文档里面告诉使用者如何找到你的脚本路径再用node执行它,简直好上那么一万倍不是么?
这里也给我们提供了一个cli开发流程思路:
名字有了,输出也有了,看看我们跟那些大名鼎鼎的cli工具,在形式上还差点啥?对了,人家可以支持不同参数选项的,还可以根据输入的不同,产生不同的结果。
这样吧,我们给这个cli加一个功能,既然叫 hello-cli ,那不能只会 hello world 吧,必须要见谁就说 hello 才行:
虽然这个功能很简单,但是至少也是实现了“根据输入的不同,产生不同结果”的效果。
命令行上的参数,可以通过 process 这个变量获取, process 是一个全局对象而不是一个包,不需要通过 require 引入。通过 process 这个对象我们可以拿到当前脚本执行环境等一系列信息,其中就包括命令行的输入情况,这个信息,保存在 process.argv 这个属性里。我们可以打印一下:
打印结果:
可以看出,argv是个数组,前两位是固定的,分别是node程序的路径和脚本存放的位置,从第三位开始才是额外输入的内容。那么实现上面的功能就很简单了,只要读取argv数组的第三位,然后输出出来就可以了。
npm社区中也有一些优秀的命令行参数解析包,比如 yargs ,tj的 commander.js 等等
如果你想使用比较复杂的参数或者命令,建议还是用第三方包比较好,手写解析太耗精力了。
现在,你可以自由自在的写你自己的cli脚本了。
如果你希望写一个项目打完包自动推上git的cli,或者自动从git仓库里面拉取项目启动模板,那么,你需要通过node的 child_process 模块开启子进程,在子进程内调用git命令:
不仅是git命令,包括系统命令、其他cli命令都可以在这里执行。特别是系统命令,使用系统命令对文件目录进行操作,效率比fs高到不知道哪里去了。
社区上也有一些不错的包,比如阮一峰老师推荐的 shelljs
如果你不那么希望你的cli用起来那么“硬核”,希望更人性化一点,比如提供一些友好的输入、提示啊,给你的输出加点颜色区分重点啊,写个简单的进度条啊等等,那么你就需要美化一下你的输出了。
除了颜色这部分,不使用第三方包实现起来非常繁琐复杂,其他的功能,都可以试试自己写。
颜色部分使用了第三方包 colors ,这里就不演示了。
其他都是由nodejs自带的 readline 模块实现的。
绘制的思路跟canvas绘制动画一样,只不过canvas是清除画布,而命令行这里是通过 readline.clearScreenDown 清除输出。
这样,一个简易的,人性化的,带点点进度条动画的命令行cli工具就写好了,你也可以发挥你的想象力,去写一些更有趣的效果出来。
毕竟我们前端,有浏览器我们可以写动画,没了浏览器我们一样可以写动画。
如何在nodejs里调用执行系统命令
这篇文章主要介绍了Nodejs中调用系统命令、Shell脚本和Python脚本的方法和实例,本文给出了利用子进程调用系统命令、执行系统命令、调用传参数的shell脚本、调用python脚本的例子,需要的朋友可以参考下
每种语言都有自己的优势,互相结合起来各取所长程序执行起来效率更高或者说哪种实现方式较简单就用哪个,nodejs是利用子进程来调用系统命令或者文件,文档见,NodeJS子进程提供了与系统交互的重要接口,其主要API有: 标准输入、标准输出及标准错误输出的接口。
NodeJS 子进程提供了与系统交互的重要接口,其主要 API 有:
标准输入、标准输出及标准错误输出的接口
child.stdin 获取标准输入
child.stdout 获取标准输出
child.stderr 获取标准错误输出
获取子进程的PID:child.pid
提供生成子进程的方法:child_process.spawn(cmd, args=[], [options])
提供直接执行系统命令的方法:child_process.exec(cmd, [options], callback)
提供调用脚本文件的方法:child_process.execFile(file, [args], [options], [callback])
提供杀死进程的方法:child.kill(signal='SIGTERM')
用实例来感受一下,很有意思的,呵呵~~
1、利用子进程调用系统命令(获取系统内存使用情况)
新建nodejs文件,名为cmd_spawn.js,代码如下:
复制代码 代码如下:
var spawn = require('child_process').spawn;
free = spawn('free', [
Nodejs child_process 模块
child_process.exec(command[, options][, callback])
开启一个子进程执行 shell 命令,在回调中获取输出信息
在 lib/child_process 源码中 exec 内部只是处理参数后调用了 execFile 方法。
exec 调用 execFile
child_process.execFile(file[, args][, options][, callback])
execFile 源码
调用 spawn 创建进程 child
通过 child.stdout.on('data') 收集输出 stdout
当 child 进程 close 时把 _stdout 传入 callback 内输出
同样当 child 进程 触发 error 事件会把 _stderr 传入 callback 中输出,同时会 destroy 进程 child 的 stdout 和 stderr
execFile 通过 spawn 创建子进程执行命令,是 nodejs 围绕 spawn 方法的封装, 调用 spawn 执行命令一次性的把输出结果和错误通过回调输出。
exec 底层调用了 execFile,不过 exec 通过 option.shell = true 的配置使 spawn 创建的进程通过 /bin/sh -c 执行传入的 shell 脚本
适合执行开销小的命令
wiki Spawn (computing)
使用 spawn 创建子进程执行 命令时 options.stdio 比较常用的配置项就是默认的 pipe 和 inherit , ignore 选项将会忽略子进程的输入输出
如果使用 inherit 选项,命令的执行内容将会直接在控制台输出,因为指定了输出的 fd 的 1 process.stdio 标准输出流直接会在控制台中输出。
如果使用 pipe 选项, child.stdout 也可以通过 pipe 输出流的方式输出到可写流中, 比如 fs.createWriteStream 简单的文件可写流。
通过执行 index.js 执行 spwan API 设置 detached: true 创建守护进程并解除父进程引用。守护进程将会一直向 stdout.log 中写入数据。
通过守护进程的例子会发现 stdout.log 写入的 父进程 ppid 与 index.js 打印出的父进程 pid 不一样。这里的 ppid:1 是 init 进程,当父进程退出后通过父进程创建还在执行的子进程将会被 init 进程收养成为 孤儿进程
ChildProcess.prototype.spawn 创建子进程源码
通过 ChildProcess.prototype.spawn 创建子进程,通过 c++ 的 Pipe 创建不同 pipe 实例的和 Process 创建进程,这里可以看下 stido 中 pipe 和 ipc 模式创建不同的 Pipe 实例
pipe ipc 创建 Pipe 实例的区别
setupChannel 添加 ipc send() 方法
child_process和IPC探究
【node源码】child_process源码阅读
线程和进程
怎样安装node模块child
默认安装在 NodeJS 目录下的: \node_modules\npm 目录中,想要升级或降级的话(因为随 NodeJS 一起发布的 npm 不一定是最新版本),请参考: suoling.net/update-npm/ 上面链接中介绍的 npm 的升级降级方式比 npm 官方介绍的几种方法的操作要简...