澳门游戏平台大全 澳门十大电子游戏平台 js_脚本之家,js命令行教程图文详解_node

js_脚本之家,js命令行教程图文详解_node

本文先介绍原生的node.js实现命令行交互,了解原生的api,然后通过commander.js和inquirer.js实现一个完整的交互命令行工具。

在死磕进程一个礼拜后,终于把晦涩难懂文档看明白了,准备把自己的理解分享给大家,也希望大家能指出一些意见

process

进程的概念

process对象是一个全局变量,它提供了当前node.js进程的信息并对其控制。因为其是一个全局变量所以无需在文件中引入。

在Node.js中每个应用程序都是一个进程类的实例对象。
使用process对象代表应用程序,这是一个全局对象,可以通过它来获取Node.jsy应用程序以及运行该程序的用户、环境等各种信息的属性、方法和事件。

需要用到的几个api

进程中几个重要的属性

process.argv process.cwd() process.stdin process.stdout
process.stdin.resume() process.argv

stdin 标准输入可读流 stdout 标准输入可写流 stderr 标准错误输出流 argv
终端输入参数数组 env 操作系统环境信息 pid 应用程序进程id

process.argv

stdin以及stdout

属性返回一个数组。数组的第一个值是process.execPath,第二个是正在执行的JavaScript的文件路径,其余参数为其它命令参数,这是我们来自定义命令的关键。

process.stdin.on => { process.stdout.write

console.log

示例

env: 在mac终端输入 export NODE_ENV=develop

// argv.jsconsole.log
console.log //develop

执行node命令node argv.js

进程的方法

node argv.js --name zhu## 输出[ '/usr/local/bin/node', ## 执行当前脚本的Node二进制文件的绝对路径 '/Users/zhuhuilong/Node/Book/argv.js', ## 文件的绝对路径 '--name', ## 其余参数 'zhu' ]

process.memoryUsage() 查看内存使用信息 process.nextTick()
当前eventloop执行完毕执行回调函数 process.chdir()
chdir方法用于修改Node.js应用程序中使用的当前工作目录 process.cwd()
进程当前工作目录 process.kill() 杀死进程 process.uncaughtException()
当应用程序抛出一个未被捕获的异常时触发进程对象的uncaughtException事件

接收自定义的命令参数进行处理输出

say() //方法不存在process.on('uncaughtException',function{ console.log;});
// argv.jsconsole.loglet argvs = process.argvlet param = argvs.spliceif(param[0] && param[0] == '--name'){ if{ console.log }else{ console.log }}

child_process

运行argv.js

子进程是今天要讲的重点,我也有一些不太明白,希望能和大家多多交流

node argv.js --name zhu## 输出[ '/usr/local/bin/node', '/Users/zhuhuilong/Node/Book/argv.js', '--name', 'zhu' ]hello zhuparam [ '--name', 'zhu' ]

child_process出现的背景

process.stdin与process.stdout

在Node.js中,只有一个线程执行所有操作,如果某个操作需要大量消耗CPU资源的情况下,后续操作都需要等待。

process.stdin

在Node.js中,提供了一个child_process模块,通过它可以开启多个子进程,在多个子进程之间可以共享内存空间,可以通过子进程的互相通信来实现信息的交换。

process.stdin 属性返回连接到 stdin 的流。 它是一个 net.Socket 流,除非
fd 0 指向一个文件,在这种情况下它是一个可读流。

child_澳门十大电子游戏平台,process模块给予node任意创建子进程的能力,node官方文档对于child_proces模块给出了四种方法,映射到操作系统其实都是创建子进程。但对于开发者而已,这几种方法的api有点不同

process.stdout

child_process.exec(command[, options][, callback]) 启动
子进程来执行shell命令,可以通过回调参数来获取脚本shell执行结果

process.stdout 属性返回连接到 stdout 的流。 它是一个 net.Socket 流,除非
fd 1 指向一个文件,在这种情况下它是一个可写流。

child_process.execfile(file[, args][, options][, callback])
与exec类型不同的是,它执行的不是shell命令而是一个可执行文件

process.stdin.resume()

child_process.spawn(command[, args][,
options])仅仅执行一个shell命令,不需要获取执行结果

一个指向 标准输入流 的可读流。标准输入流默认是暂停 的,所以必须要调用
process.stdin.resume 接收。
作为流,process.stdin可以在旧模式下使用。为了兼容node
v0.10以前的版本。在旧模式喜爱使用stdin必须调用process.stdin.resume()。注意如果调用了process.stdin.resume()
stdin将转为旧模式。

child_process.fork(modulePath[, args][, options])可以用node
执行的.js文件,也不需要获取执行结果。fork出来的子进程一定是node进程

通俗来讲就是控制台等待我们输入内容不退出进程,对输入输出进行交互。

spawn

新建inputout.js

语法:child_process.spawn(command, [args], [options])

// inputout.jsprocess.stdin.setEncodinglet argvs = process.argvlet param = argvs.spliceif (param[0] && param[0] == '--name') { if  { console.log } else { process.stdout.write process.stdin.resume() process.stdin.on('data', chunk => { if (!!chunk.replace { process.stdout.write(`你输入的name是: ${chunk}`) process.stdin.emit } else { process.stdout.write }}process.stdin.on => { process.stdout.write

command 必须指定的参数,指定需要执行的命令 args
数组,存放了所有运行该命令需要的参数 options
参数为一个对象,用于指定开启子进程时使用的选项

>执行node inputout.js --name

const { spawn } = requireconst path = requirelet child1 = spawn('node', ['test1.js', 'yanyongchao'], { stdio: ['pipe', 'pipe', 'pipe'], // 三个元素数组 下面会详解 cwd: __dirname, 子进程工作目录 env: process.env, 环境变量 detached: true // 如果为true,当父进程不存在时也可以独立存在})

备注

其实上面都好理解除了sdtio数组,下面来一起分析stdio

在新版本node模式下可以使用process.stdin.on代替process.stdin.resume()恢复输入流接收。

stdio

process.stdin.on => { var chunk = process.stdin.read(); console.log if  { process.stdout.write; process.stdin.emit;process.stdin.on => { process.stdout.write;

stdio是一个数组,用来设置标准输入,标准输出,错误输出。个人理解

从上面的示例我们可以拿到process.argv参数对其进行处理交互,但如果要实现更复杂的命令交互,使用上面的方法会很吃力。下面我们使用commander.js和inquirer来实现一个完整的node命令行工具。

pipe:父进程和子进程之间建立一个管道

commander.js

const path = requireconst { spawn } = requirelet p = spawn('node', ['childs_t.js'], { cwd: path.join, stdio: ['pipe', 'pipe', process.stderr]})p.stdout.on => { console.log // 这里用stdout原因: 子进程的数据流与常规理解的数据流方向相反,// stdin:写入流,stdout、stderr:读取流。

process.stdout.write

node.js命令行界面的完整解决方案,受Ruby Commander启发。

如果在stdio中放一个流,process.stdout,process.stdin

commander.js的API简述

const { spawn } = requireconst path = require// 如果放的是一个流,则意味着父进程和子进程共享一个流const p = spawn('node', ['child_t.js'], { cwd: path.join, stdio: [process.stdin, process.stdout, process.stderr]})

process.stdout.write //控制台会输出asd

program.version() 声明版本

ipc

const program = requireconst pkg = requireprogram.version
const path = requireconst { spawn } = requirelet p = spawn('node', ['child_t.js'], { cwd: path.join, stdio: ['ipc', 'pipe', 'pipe']})p.on => { console.logp.send('hello chhild_process')

process.on => { process.send// child.send;//在父进程中向子进程发送消息// process.send;//在子进程中向主进程发送消息

Options 解析

detached模式

使用.option()方法定义commander的选项options,也可以作为选项的文档。

const { spawn } = requireconst fs = requireconst path = requirelet out = fs.openSync(path.join(__dirname, 'childs/msg.txt'), 'w', 0o666)let p = spawn('node', ['test4.js'], { detached: true, //保证父进程结束,子进程仍然可以运行 stdio: 'ignore', cwd: path.join})p.unref()p.on { console.logp.on { console.logp.on('error', function { console.log
var program = require; program .version .option('-p, --peppers', 'Add peppers') .option('-P, --pineapple', 'Add pineapple') .option('-b, --bbq-sauce', 'Add bbq sauce') .option('-c, --cheese [type]', 'Add the specified type of cheese [marble]', 'marble') .parse; console.log('you ordered a pizza with:');if  console.log;if  console.log;if  console.log;console.log(' - %s cheese', program.cheese);

fork开启一个子进程

添加自定义命令program.command()

衍生一个新的 Node.js 进程,并通过建立一个 IPC
通讯通道来调用一个指定的模块,该通道允许父进程与子进程之间相互发送信息
fork方法返回一个隐式创建的代表子进程的ChildProcess对象
子进程的输入/输出操作执行完毕后,子进程不会自动退出,必须使用process.exit()方法显式退出

var program = require; program .command //<>必选参数,如果是[]则是可选参数 .option('-r, --recursive', 'Remove recursively') .action { console.log('remove ' + dir + (cmd.recursive ? ' recursively' : '')) }) program.parse// command()可变参数/** 命令command有且只有最后一个参数可变不固定的。 要使参数变量可变,必须将...附加到参数名称。**/program .version .command('rmdir  [otherDirs...]') .action(function  { console.log; if  { otherDirs.forEach { console.log; } });program.parse;
const { fork } = requireconst path = requirelet child = fork(path.join(__dirname, 'childs/fork1.js'))child.on => { console.logchild.sendchild.on => { console.error

process.on('message',  => { console.log process.send //sendHandle是一个 net.Socket 或 net.Server 对象})

program.action() 定义命令的回调函数

exec开启子进程

var program = require;program .command .option("-r, --recursive", "Remove recursively") .option("-f, --force", "remove force") .action { // cmd为option参数选项 //console.log if  { console.log("remove " + dir + " recursively"); } if  { console.log("remove " + dir + " forcefully"); } });program.parse;
// exec同步执行一个shell命令let { exec } = requirelet path = require// 用于使用shell执行命令, 同步方法let p1 = exec('node exec.js a b c', {cwd: path.join}, function { console.log

inquirer.js

execFile开启子进程

Inquirer.js
使用NodeJs做的一个通用交互式命令行用户界面的集合。具有常用的控制台交互操作。

let { execFile } = requirelet path = requirelet p1 = execFile('node', ['exec.js', 'a', 'b', 'c'], { cwd: path.join}, function { console.log

由于交互的问题种类不同,inquirer为每个问题提供很多参数:

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

type:表示提问的类型,包括:input, confirm, list, rawlist, expand,
checkbox, password, editor; name: 存储当前问题回答的变量;
message:问题的描述; default:默认值;
choices:列表选项,在某些type下可用,并且包含一个分隔符;
validate:对用户的回答进行校验;
filter:对用户的回答进行过滤处理,返回处理后的值;
transformer:对用户回答的显示效果进行处理,但不会影响最终的答案的内容;
when:根据前面问题的回答,判断当前问题是否需要被回答;
pageSize:修改某些type类型下的渲染行数; prefix:修改message默认前缀;
suffix:修改message默认后缀。 创建cli.js

const program = requireconst inquirer = requireconst fs = requireconst path = requireconst pkg = requireconst CWD = process.cwd()const promptList = [ { type: 'list', message: '请选择一种模版', name: 'template', choices: ['vue', 'angular', 'webpack-m-pages'], filter: function { return val.toLowerCase() } }]program .version .command .description('create project template') .action { const TEMPLATE_PATH = path.join if (fs.existsSync { } else { fs.mkdirSync } if  { inquirer.prompt.then(anwsers => { console.logprogram.parse

运行 node cli/cli.js create vue

已经可以运行了,我们自定义一个命名替代每次都执行node

命令为:test-cli create

1、创建bin文件夹,在bin文件夹下创建index.js文件

#!/usr/bin/env noderequire

2、修改package.json文件

"bin": { "test-cli": "./bin/index.js" },

3、执行npm link (如果没有权限,执行sudo npm link)

5、发布 npm publish

6、发布完毕,需npm unlink解除本地的命令映射

npm install -g XXX

总结

以上所述是小编给大家介绍的node.js命令行教程图文详解,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

标签:, , , , , ,

相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图