Commander.js 是完整的 node.js 命令行解决方案。受 Ruby Commander 启发。
项目地址:是进行node.js命令行开发是时必备技能。

安装

  1. npm install commander

声明 program 变量

为简化使用,Commander 提供了一个全局对象。本文档的示例代码均按此方法使用:

  1. const { program } = require('commander');
  2. program.version('0.0.1');

如果程序较为复杂,用户需要以多种方式来使用 Commander,如单元测试等。创建本地 Command 对象是一种更好的方式:

  1. const { Command } = require('commander');
  2. const program = new Command();
  3. program.version('0.0.1');

选项

Commander 使用.option() 方法来定义选项,同时可以附加选项的简介。每个选项可以定义一个短选项名称(-后面接单个字符)和一个长选项名称(—后面接一个或多个单词),使用逗号、空格或|分隔。

选项可以通过在Command对象上调用.opts()方法来获取。对于多个单词的长选项,使用驼峰法获取,例如--template-engine选项通过program.opts().templateEngine获取。

多个短选项可以合并简写,其中最后一个选项可以附加参数。
例如,-a -b -p 80 也可以写为 -ab -p80 ,甚至进一步简化为 -abp80

--可以标记选项的结束,后续的参数均不会被命令解释,可以正常使用。

默认情况下,选项在命令行中的顺序不固定,一个选项可以在其他参数之前或之后指定。

常用选项类型,boolean 型选项和带参数选项

有两种最常用的选项,一类是 boolean 型选项,选项无需配置参数,另一类选项则可以设置参数(使用尖括号声明在该选项后,如--expect <value>)。如果在命令行中不指定具体的选项及参数,则会被定义为undefined

示例代码:options-common.js

  1. program
  2. .option('-d, --debug', 'output extra debugging')
  3. .option('-s, --small', 'small pizza size')
  4. .option('-p, --pizza-type <type>', 'flavour of pizza');
  5. program.parse(process.argv);
  6. const options = program.opts();
  7. if (options.debug) console.log(options);
  8. console.log('pizza details:');
  9. if (options.small) console.log('- small pizza size');
  10. if (options.pizzaType) console.log(`- ${options.pizzaType}`);
  1. $ pizza-options -d
  2. { debug: true, small: undefined, pizzaType: undefined }
  3. pizza details:
  4. $ pizza-options -p
  5. error: option '-p, --pizza-type <type>' argument missing
  6. $ pizza-options -ds -p vegetarian
  7. { debug: true, small: true, pizzaType: 'vegetarian' }
  8. pizza details:
  9. - small pizza size
  10. - vegetarian
  11. $ pizza-options --pizza-type=cheese
  12. pizza details:
  13. - cheese

通过program.parse(arguments)方法处理参数,没有被使用的选项会存放在program.args数组中。该方法的参数是可选的,默认值为process.argv

选项的默认值

选项可以设置一个默认值。

示例代码:options-defaults.js

  1. program
  2. .option('-c, --cheese <type>', 'add the specified type of cheese', 'blue');
  3. program.parse();
  4. console.log(`cheese: ${program.opts().cheese}`);
  1. $ pizza-options
  2. cheese: blue
  3. $ pizza-options --cheese stilton
  4. cheese: stilton

其他的选项类型,取反选项,以及可选参数的选项

可以定义一个以no-开头的boolean型长选项。在命令行中使用该选项时,会将对应选项的值置为false。当只定义了带no-的选项,未定义对应不带no-的选项时,该选项的默认值会被置为true。

如果已经定义了--foo,那么再定义--no-foo并不会改变它本来的默认值。可以为一个boolean类型的选项指定一个默认的布尔值,在命令行里可以重写它的值。

示例代码:options-negatable.js

  1. program
  2. .option('--no-sauce', 'Remove sauce')
  3. .option('--cheese <flavour>', 'cheese flavour', 'mozzarella')
  4. .option('--no-cheese', 'plain with no cheese')
  5. .parse();
  6. const options = program.opts();
  7. const sauceStr = options.sauce ? 'sauce' : 'no sauce';
  8. const cheeseStr = (options.cheese === false) ? 'no cheese' : `${options.cheese} cheese`;
  9. console.log(`You ordered a pizza with ${sauceStr} and ${cheeseStr}`);
  1. $ pizza-options
  2. You ordered a pizza with sauce and mozzarella cheese
  3. $ pizza-options --sauce
  4. error: unknown option '--sauce'
  5. $ pizza-options --cheese=blue
  6. You ordered a pizza with sauce and blue cheese
  7. $ pizza-options --no-sauce --no-cheese
  8. You ordered a pizza with no sauce and no cheese

选项的参数使用方括号声明表示参数是可选参数(如 --optional [value])。该选项在不带参数时可用作boolean选项,在带有参数时则从参数中得到值。

示例代码:options-boolean-or-value.js

  1. program
  2. .option('-c, --cheese [type]', 'Add cheese with optional type');
  3. program.parse(process.argv);
  4. const options = program.opts();
  5. if (options.cheese === undefined) console.log('no cheese');
  6. else if (options.cheese === true) console.log('add cheese');
  7. else console.log(`add cheese type ${options.cheese}`);
  1. $ pizza-options
  2. no cheese
  3. $ pizza-options --cheese
  4. add cheese
  5. $ pizza-options --cheese mozzarella
  6. add cheese type mozzarella

关于可能有歧义的用例,请见可变参数的选项

必填选项

通过.requiredOption方法可以设置选项为必填。必填选项要么设有默认值,要么必须在命令行中输入,对应的属性字段在解析时必定会有赋值。该方法其余参数与.option一致。

示例代码:options-required.js

  1. program
  2. .requiredOption('-c, --cheese <type>', 'pizza must have cheese');
  3. program.parse();
  1. $ pizza
  2. error: required option '-c, --cheese <type>' not specified

变长参数选项

定义选项时,可以通过使用...来设置参数为可变长参数。在命令行中,用户可以输入多个参数,解析后会以数组形式存储在对应属性字段中。在输入下一个选项前(-或—开头),用户输入的指令均会被视作变长参数。与普通参数一样的是,可以通过--标记当前命令的结束。

示例代码:options-variadic.js

  1. program
  2. .option('-n, --number <numbers...>', 'specify numbers')
  3. .option('-l, --letter [letters...]', 'specify letters');
  4. program.parse();
  5. console.log('Options: ', program.opts());
  6. console.log('Remaining arguments: ', program.args);
  1. $ collect -n 1 2 3 --letter a b c
  2. Options: { number: [ '1', '2', '3' ], letter: [ 'a', 'b', 'c' ] }
  3. Remaining arguments: []
  4. $ collect --letter=A -n80 operand
  5. Options: { number: [ '80' ], letter: [ 'A' ] }
  6. Remaining arguments: [ 'operand' ]
  7. $ collect --letter -n 1 -n 2 3 -- operand
  8. Options: { number: [ '1', '2', '3' ], letter: true }
  9. Remaining arguments: [ 'operand' ]

关于可能有歧义的用例,请见可变参数的选项

版本选项

version方法可以设置版本,其默认选项为-V--version,设置了版本后,命令行会输出当前的版本号。

  1. program.version('0.0.1');
  1. $ ./examples/pizza -V
  2. 0.0.1

版本选项也支持自定义设置选项名称,可以在version方法里再传递一些参数(长选项名称,描述信息),用法与option方法类似。

  1. program.version('0.0.1', '-v, --vers', 'output the current version');

其他选项配置

大多数情况下,选项均可通过.option()方法添加。但对某些不常见的用例,也可以直接构造Option对象,对选项进行更详尽的配置。

示例代码: options-extra.js

  1. program
  2. .addOption(new Option('-s, --secret').hideHelp())
  3. .addOption(new Option('-t, --timeout <delay>', 'timeout in seconds').default(60, 'one minute'))
  4. .addOption(new Option('-d, --drink <size>', 'drink size').choices(['small', 'medium', 'large']));
  1. $ extra --help
  2. Usage: help [options]
  3. Options:
  4. -t, --timeout <delay> timeout in seconds (default: one minute)
  5. -d, --drink <size> drink cup size (choices: "small", "medium", "large")
  6. -h, --help display help for command
  7. $ extra --drink huge
  8. error: option '-d, --drink <size>' argument 'huge' is invalid. Allowed choices are small, medium, large.

自定义选项处理

选项的参数可以通过自定义函数来处理,该函数接收两个参数:用户新输入的参数值和当前已有的参数值(即上一次调用自定义处理函数后的返回值),返回新的选项参数值。

自定义函数适用场景包括参数类型转换,参数暂存,或者其他自定义处理的场景。

可以在自定义函数的后面设置选项参数的默认值或初始值(例如参数用list暂存时需要设置一个初始空集合)。

示例代码:options-custom-processing.js

  1. function myParseInt(value, dummyPrevious) {
  2. // parseInt takes a string and a radix
  3. const parsedValue = parseInt(value, 10);
  4. if (isNaN(parsedValue)) {
  5. throw new commander.InvalidOptionArgumentError('Not a number.');
  6. }
  7. return parsedValue;
  8. }
  9. function increaseVerbosity(dummyValue, previous) {
  10. return previous + 1;
  11. }
  12. function collect(value, previous) {
  13. return previous.concat([value]);
  14. }
  15. function commaSeparatedList(value, dummyPrevious) {
  16. return value.split(',');
  17. }
  18. program
  19. .option('-f, --float <number>', 'float argument', parseFloat)
  20. .option('-i, --integer <number>', 'integer argument', myParseInt)
  21. .option('-v, --verbose', 'verbosity that can be increased', increaseVerbosity, 0)
  22. .option('-c, --collect <value>', 'repeatable value', collect, [])
  23. .option('-l, --list <items>', 'comma separated list', commaSeparatedList)
  24. ;
  25. program.parse();
  26. const options = program.opts();
  27. if (options.float !== undefined) console.log(`float: ${options.float}`);
  28. if (options.integer !== undefined) console.log(`integer: ${options.integer}`);
  29. if (options.verbose > 0) console.log(`verbosity: ${options.verbose}`);
  30. if (options.collect.length > 0) console.log(options.collect);
  31. if (options.list !== undefined) console.log(options.list);
  1. $ custom -f 1e2
  2. float: 100
  3. $ custom --integer 2
  4. integer: 2
  5. $ custom -v -v -v
  6. verbose: 3
  7. $ custom -c a -c b -c c
  8. [ 'a', 'b', 'c' ]
  9. $ custom --list x,y,z
  10. [ 'x', 'y', 'z' ]

命令

通过.command().addCommand()可以配置命令,有两种实现方式:为命令绑定处理函数,或者将命令单独写成一个可执行文件(详述见后文)。子命令支持嵌套(示例代码)。

.command()的第一个参数可以配置命令名称及命令参数,参数支持必选(尖括号表示)、可选(方括号表示)及变长参数(点号表示,如果使用,只能是最后一个参数)。

使用.addCommand()program增加配置好的子命令。

例如:

  1. // 通过绑定处理函数实现命令(这里的指令描述为放在`.command`中)
  2. // 返回新生成的命令(即该子命令)以供继续配置
  3. program
  4. .command('clone <source> [destination]')
  5. .description('clone a repository into a newly created directory')
  6. .action((source, destination) => {
  7. console.log('clone command called');
  8. });
  9. // 通过独立的的可执行文件实现命令 (注意这里指令描述是作为`.command`的第二个参数)
  10. // 返回最顶层的命令以供继续添加子命令
  11. program
  12. .command('start <service>', 'start named service')
  13. .command('stop [service]', 'stop named service, or all if no name supplied');
  14. // 分别装配命令
  15. // 返回最顶层的命令以供继续添加子命令
  16. program
  17. .addCommand(build.makeBuildCommand());

使用.command()addCommand()来传递配置的选项。当设置hidden: true时,该命令不会打印在帮助信息里。当设置isDefault: true时,若没有指定其他子命令,则会默认执行这个命令(样例)。

设置命令参数

通过.arguments可以为最顶层命令指定命令参数,对子命令而言,参数都包括在.command调用之中了。尖括号(例如<required>)意味着必选,而方括号(例如[optional])则代表可选。可以向.description()方法传递第二个参数,从而在帮助中展示命令参数的信息。该参数是一个包含了 “命令参数名称:命令参数描述” 键值对的对象。

示例代码:arguments.js

  1. program
  2. .version('0.1.0')
  3. .arguments('<username> [password]')
  4. .description('test command', {
  5. username: 'user to login',
  6. password: 'password for user, if required'
  7. })
  8. .action((username, password) => {
  9. console.log('username:', username);
  10. console.log('environment:', password || 'no password given');
  11. });

在参数名后加上...来声明可变参数,且只有最后一个参数支持这种用法,例如

  1. program
  2. .version('0.1.0')
  3. .command('rmdir <dirs...>')
  4. .action(function (dirs) {
  5. dirs.forEach((dir) => {
  6. console.log('rmdir %s', dir);
  7. });
  8. });

可变参数会以数组的形式传递给处理函数。

处理函数

命令处理函数的参数,为该命令声明的所有参数,除此之外还会附加两个额外参数:一个是解析出的选项,另一个则是该命令对象自身。

示例代码:thank.js

  1. program
  2. .arguments('<name>')
  3. .option('-t, --title <honorific>', 'title to use before name')
  4. .option('-d, --debug', 'display some debugging')
  5. .action((name, options, command) => {
  6. if (options.debug) {
  7. console.error('Called %s with options %o', command.name(), options);
  8. }
  9. const title = options.title ? `${options.title} ` : '';
  10. console.log(`Thank-you ${title}${name}`);
  11. });

处理函数支持async,相应的,需要使用.parseAsync代替.parse

  1. async function run() { /* 在这里编写代码 */ }
  2. async function main() {
  3. program
  4. .command('run')
  5. .action(run);
  6. await program.parseAsync(process.argv);
  7. }

在命令行上使用命令时,选项和命令参数必须是合法的,使用未知的选项,或缺少所需的命令参数,会提示异常。
如要允许使用未知的选项,可以调用.allowUnknownOption()。默认情况下,传入过多的参数并不报错,但也可以通过调用.allowExcessArguments(false)来启用过多参数的报错。

独立的可执行(子)命令

.command()带有描述参数时,就意味着使用独立的可执行文件作为子命令。
Commander 将会尝试在入口脚本(例如 ./examples/pm)的目录中搜索program-command形式的可执行文件,例如pm-install, pm-search。通过配置选项executableFile可以自定义名字。

你可以在可执行文件里处理(子)命令的选项,而不必在顶层声明它们。

示例代码:pm

  1. program
  2. .version('0.1.0')
  3. .command('install [name]', 'install one or more packages')
  4. .command('search [query]', 'search with optional query')
  5. .command('update', 'update installed packages', { executableFile: 'myUpdateSubCommand' })
  6. .command('list', 'list packages installed', { isDefault: true });
  7. program.parse(process.argv);

如果该命令需要支持全局安装,请确保有对应的权限,例如755

自动化帮助信息

帮助信息是 Commander 基于你的程序自动生成的,默认的帮助选项是-h,--help

示例代码:pizza

  1. $ node ./examples/pizza --help
  2. Usage: pizza [options]
  3. An application for pizza ordering
  4. Options:
  5. -p, --peppers Add peppers
  6. -c, --cheese <type> Add the specified type of cheese (default: "marble")
  7. -C, --no-cheese You do not want any cheese
  8. -h, --help display help for command

如果你的命令中包含了子命令,会默认添加help命令,它可以单独使用,也可以与子命令一起使用来提示更多帮助信息。用法与shell程序类似:

  1. shell help
  2. shell --help
  3. shell help spawn
  4. shell spawn --help

自定义帮助

可以添加额外的帮助信息,与内建的帮助一同展示。

示例代码: custom-help

  1. program
  2. .option('-f, --foo', 'enable some foo');
  3. program.addHelpText('after', `
  4. Example call:
  5. $ custom-help --help`);

将会输出以下的帮助信息

  1. Usage: custom-help [options]
  2. Options:
  3. -f, --foo enable some foo
  4. -h, --help display help for command
  5. Example call:
  6. $ custom-help --help

位置参数对应的展示方式如下:

  • beforeAll:作为全局标头栏展示
  • before:在内建帮助信息之前展示
  • after:在内建帮助信息之后展示
  • afterAll:作为全局末尾栏展示

beforeAllafterAll两个参数作用于命令及其所有的子命令。

第二个参数可以是一个字符串,也可以是一个返回字符串的函数。对后者而言,为便于使用,该函数可以接受一个上下文对象,它有如下属性:

  • error:boolean值,代表该帮助信息是否由于不当使用而展示
  • command: 代表展示该帮助信息的Command对象

使用代码展示帮助信息

.help():展示帮助信息并退出。可以通过传入{ error: true }来将帮助信息作为stderr输出,并以代表错误的状态码退出程序。

.outputHelp():只展示帮助信息,不退出程序。传入{ error: true }可以将帮助信息作为stderr输出。

.helpInformation(): 得到字符串形式的内建的帮助信息,以便用于自定义的处理及展示。

.usage 和 .name

通过这两个选项可以修改帮助信息的首行提示,name 属性也可以从参数中推导出来。例如:

  1. program
  2. .name("my-command")
  3. .usage("[global options] command")

帮助信息会首先输出:

  1. Usage: my-command [global options] command

.helpOption(flags, description)

每一个命令都带有一个默认的帮助选项。可以重写flags和description参数。传入false则会禁用内建的帮助信息。

  1. program
  2. .helpOption('-e, --HELP', 'read more information');

.addHelpCommand()

如果一个命令拥有子命令,它也将有一个默认的帮助子命令。使用.addHelpCommand().addHelpCommand(false)可以打开或关闭默认的帮助子命令。

也可以自定义名字和描述:

  1. program.addHelpCommand('assist [command]', 'show assistance');

其他帮助配置

内建帮助信息通过Help类进行格式化。如有需要,可以使用.configureHelp()来更改其数据属性和方法,或使用.createHelp()来创建子类,从而配置Help类的行为。

数据属性包括:

  • helpWidth:指明帮助信息的宽度。可在单元测试中使用。
  • sortSubcommands:以字母序排列子命令
  • sortOptions:以字母序排列选项

可以得到可视化的参数列表,选项列表,以及子命令列表。列表的每个元素都具有termdescription属性,并可以对其进行格式化。关于其使用方式,请参考.formatHelp()

示例代码: configure-help.js

  1. program.configureHelp({
  2. sortSubcommands: true,
  3. subcommandTerm: (cmd) => cmd.name() // Just show the name, instead of short usage.
  4. });

自定义事件监听

监听命令和选项可以执行自定义函数。

  1. program.on('option:verbose', function () {
  2. process.env.VERBOSE = this.verbose;
  3. });
  4. program.on('command:*', function (operands) {
  5. console.error(`error: unknown command '${operands[0]}'`);
  6. const availableCommands = program.commands.map(cmd => cmd.name());
  7. mySuggestBestMatch(operands[0], availableCommands);
  8. process.exitCode = 1;
  9. });

零碎知识

.parse() 和 .parseAsync()

.parse的第一个参数是要解析的字符串数组,也可以省略参数而使用process.argv

如果参数遵循与 node 不同的约定,可以在第二个参数中传递from选项:

  • ‘node’: 默认值,argv[0]是应用,argv[1]是要跑的脚本,后续为用户参数;
  • ‘electron’: argv[1]根据 electron 应用是否打包而变化;
  • ‘user’: 来自用户的所有参数。

比如:

  1. program.parse(process.argv); // node
  2. program.parse();
  3. program.parse(['-f', 'filename'], { from: 'user' });

解析配置

当默认的解析方式无法满足需要,Commander也提供了其他的解析行为。

默认情况下,程序的选项在子命令前后均可被识别。如要只允许选项出现在子命令之前,可以使用.enablePositionalOptions()。这样可以在命令和子命令中使用意义不同的同名选项。

示例代码:positional-options.js

当启用了带顺序的选项解析,以下程序中,-b选项在第一行中将被解析为程序顶层的选项,而在第二行中则被解析为子命令的选项:

  1. program -b subcommand
  2. program subcommand -b

默认情况下,选项在命令参数前后均可被识别。如要使选项仅在命令参数前被识别,可以使用.passThroughOptions()。这样可以把参数和跟随的选项传递给另一程序,而无需使用--来终止选项解析。
如要在子命令中使用此功能,必须首先启用带顺序的选项解析。

示例代码: pass-through-options.js

当启用此功能时,以下程序中,--port=80在第一行中会被解析为程序的选项,而在第二行中则会被解析为一个命令参数:

  1. program --port=80 arg
  2. program arg --port=80

默认情况下,使用未知选项会提示错误。如要将未知选项视作普通命令参数,并继续处理其他部分,可以使用.allowUnknownOption()。这样可以混用已知和未知的选项。

默认情况下,传入过多的命令参数并不会报错。可以使用.allowExcessArguments(false)来启用这一检查。

作为属性的遗留选项

在 Commander 7 以前,选项的值是作为属性存储在command对象上的。
这种处理方式便于实现,但缺点在于,选项可能会与Command的已有属性相冲突。通过使用.storeOptionsAsProperties(),可以恢复到这种旧的处理方式,并可以不加改动的继续运行遗留代码。

  1. program
  2. .storeOptionsAsProperties()
  3. .option('-d, --debug')
  4. .action((commandAndOptions) => {
  5. if (commandAndOptions.debug) {
  6. console.error(`Called ${commandAndOptions.name()}`);
  7. }
  8. });

TypeScript

Commander 包里包含了 TypeScript 定义文件。

如果使用.ts格式编写命令,则需要通过 node 来执行命令。如:

  1. node -r ts-node/register pm.ts

createCommand()

使用工厂方法可以创建一个command,此时不需要使用new方法,如

  1. const { createCommand } = require('commander');
  2. const program = createCommand();

createCommand是 command 对象的一个方法,可以创建一个新的命令(而非子命令),使用command()创建子命令时内部会调用该方法,具体使用方式可参考custom-command-class.js

导入到 ES 模块

Commander 是一个 CommonJS 包,支持导入到 ES 模块中去。

  1. // index.mjs
  2. import commander from 'commander';
  3. const program = commander.program;
  4. const newCommand = new commander.Command();

Node 选项 —harmony

启用--harmony有以下两种方式:

  • 在子命令脚本中加上#!/usr/bin/env node --harmony。注:Windows 系统不支持;
  • 调用时加上--harmony参数,例如node --harmony examples/pm publish--harmony选项在开启子进程时仍会保留。

调试子命令

一个可执行的子命令会作为单独的子进程执行。

如果使用 node inspector 的node -inspect等命令来调试可执行命令,对于生成的子命令,inspector 端口会递增1。

如果想使用 VSCode 调试,则需要在launch.json配置文件里设置"autoAttachChildProcesses": true

重写退出和输出

默认情况下,在检测到错误、打印帮助信息或版本信息时 Commander 会调用process.exit方法。其默认实现会抛出一个CommanderError,可以重写该方法并提供一个回调函数(可选)。

回调函数的参数为CommanderError,属性包括 Number 型的exitCode、String 型的codemessage。子命令完成调用后会开始异步处理。正常情况下,打印错误信息、帮助信息或版本信息不会被重写影响,因为重写会发生在打印之后。

  1. program.exitOverride();
  2. try {
  3. program.parse(process.argv);
  4. } catch (err) {
  5. // 自定义处理...
  6. }

Commander默认用作命令行应用,其输出写入stdout和stderr。
对于其他应用类型,这一行为可以修改。并且可以修改错误信息的展示方式。

示例代码:configure-output.js

  1. function errorColor(str) {
  2. // 添加ANSI转义字符,以将文本输出为红色
  3. return `\x1b[31m${str}\x1b[0m`;
  4. }
  5. program
  6. .configureOutput({
  7. // Visibly override write routines as example!
  8. writeOut: (str) => process.stdout.write(`[OUT] ${str}`),
  9. writeErr: (str) => process.stdout.write(`[ERR] ${str}`),
  10. // Highlight errors in color.
  11. outputError: (str, write) => write(errorColor(str))
  12. });

其他文档

请参考关于如下话题的其他文档:

例子

在只包含一个命令的程序中,无需定义处理函数。

示例代码:pizza

  1. const { program } = require('commander');
  2. program
  3. .description('An application for pizza ordering')
  4. .option('-p, --peppers', 'Add peppers')
  5. .option('-c, --cheese <type>', 'Add the specified type of cheese', 'marble')
  6. .option('-C, --no-cheese', 'You do not want any cheese');
  7. program.parse();
  8. const options = program.opts();
  9. console.log('you ordered a pizza with:');
  10. if (options.peppers) console.log(' - peppers');
  11. const cheese = !options.cheese ? 'no' : options.cheese;
  12. console.log(' - %s cheese', cheese);

在包含多个命令的程序中,应为每个命令指定处理函数,或独立的可执行程序。

示例代码:deploy

  1. const { Command } = require('commander');
  2. const program = new Command();
  3. program
  4. .version('0.0.1')
  5. .option('-c, --config <path>', 'set config path', './deploy.conf');
  6. program
  7. .command('setup [env]')
  8. .description('run setup commands for all envs')
  9. .option('-s, --setup_mode <mode>', 'Which setup mode to use', 'normal')
  10. .action((env, options) => {
  11. env = env || 'all';
  12. console.log('read config from %s', program.opts().config);
  13. console.log('setup for %s env(s) with %s mode', env, options.setup_mode);
  14. });
  15. program
  16. .command('exec <script>')
  17. .alias('ex')
  18. .description('execute the given remote cmd')
  19. .option('-e, --exec_mode <mode>', 'Which exec mode to use', 'fast')
  20. .action((script, options) => {
  21. console.log('read config from %s', program.opts().config);
  22. console.log('exec "%s" using %s mode and config %s', script, options.exec_mode, program.opts().config);
  23. }).addHelpText('after', `
  24. Examples:
  25. $ deploy exec sequential
  26. $ deploy exec async`
  27. );
  28. program.parse(process.argv);

更多的示例代码点击这里查看。

支持

当前版本的Commander在LTS版本的Node上完全支持。Node版本应不低于v10。
(使用更低版本Node的用户建议安装更低版本的Commander。Commander 2.x具有最广泛的支持。)

社区支持请访问项目的 Issues

企业使用 Commander

现在 Commander 已作为 Tidelift 订阅的一部分。

Commander 和很多其他包的维护者已与 Tidelift 合作,面向企业提供开源依赖的商业支持与维护。企业可以向相关依赖包的维护者支付一定的费用,帮助企业节省时间,降低风险,改进代码运行情况。了解更多