Насколько легко использовать язык программирования, во многом зависит от его способности разрабатывать программы командной строки.
Поскольку Node.js сегодня является одним из самых популярных инструментов разработки, умение использовать Node.js для разработки программ командной строки — это навык, которым должны овладеть веб-разработчики.

Недавно блог Npm опубликовал сериюстатей, которые, на мой взгляд, очень хорошо написаны. Ниже — руководство, которое я расширил на их основе; это, вероятно, лучшее доступное на данный момент решение.
1. Исполняемые скрипты
Начнём с самого простого случая.
Сначала напишите исполняемый скрипт с именем hello на JavaScript.
#!/usr/bin/env node
console.log('hello world');
Затем измените разрешения hello.
$ chmod 755 hello
Теперь hello можно выполнить.
$ ./hello hello world
Если вы хотите убрать префикс пути перед hello, можно добавить путь к hello в переменную окружения PATH. Однако лучший подход — создать package.json в текущем каталоге со следующим содержимым.
{
"name": "hello",
"bin": {
"hello": "hello"
}
}
Затем выполните команду npm link.
$ npm link
Теперь, когда вы снова выполняете hello, вам не нужно вводить путь.
$ hello hello world
2. Базовый синтаксис аргументов командной строки
Аргументы командной строки можно получить с помощью системной переменной process.argv.
#!/usr/bin/env node
console.log('hello ', process.argv[2]);
При выполнении просто добавьте аргументы сразу после файла скрипта.
$ ./hello tom hello tom
3. Создание процессов
Скрипты могут создавать дочерние процессы через модуль child_process для выполнения системных команд Unix.
#!/usr/bin/env node
var name = process.argv[2];
var exec = require('child_process').exec;
var child = exec('echo hello ' + name, function(err, stdout, stderr) {
if (err) throw err;
console.log(stdout);
});
Использование следующее.
$ ./hello tom hello tom
4. Модуль shelljs
shelljsЭтот модуль повторно оборачивает child_process, что делает вызов системных команд более удобным. Перед использованием его нужно установить.
npm install --save shelljs
Затем перепишите скрипт.
#!/usr/bin/env node
var name = process.argv[2];
var shell = require("shelljs");
shell.exec("echo hello " + name);
Приведённый выше код использует локальный режим shelljs, который выполняет команды shell через метод exec. Существует также глобальный режим, позволяющий писать команды shell непосредственно в скрипте.
require('shelljs/global');
if (!which('git')) {
echo('Sorry, this script requires git');
exit(1);
}
mkdir('-p', 'out/Release');
cp('-R', 'stuff/*', 'out/Release');
cd('lib');
ls('*.js').forEach(function(file) {
sed('-i', 'BUILD_VERSION', 'v0.1.2', file);
sed('-i', /.*REMOVE_THIS_LINE.*/n/, '', file);
sed('-i', /.*REPLACE_LINE_WITH_MACRO.*/n/, cat('macro.js'), file);
});
cd('..');
if (exec('git commit -am "Auto-commit"').code !== 0) {
echo('Error: Git commit failed');
exit(1);
}
5. Модуль yargs
shelljs решает только то, как вызывать команды оболочки, а модуль yargs занимается тем, как обрабатывать аргументы командной строки. Его также нужно установить.
$ npm install --save yargs
Модуль yargs предоставляет объект argv для чтения аргументов командной строки. См. переписанный hello.
#!/usr/bin/env node
var argv = require('yargs').argv;
console.log('hello ', argv.name);
При его использовании работает любой из следующих двух вариантов использования.
$ hello --name=tom hello tom $ hello --name tom hello tom
Если вы измените argv.name на argv.n, вы сможете использовать однобуквенную короткую форму параметра.
$ hello -n tom hello tom
Вы можете использовать метод alias, чтобы указать, что name является псевдонимом для n.
#!/usr/bin/env node
var argv = require('yargs')
.alias('n', 'name')
.argv;
console.log('hello ', argv.n);
Таким образом, можно использовать как короткие, так и длинные параметры.
$ hello -n tom hello tom $ hello --name tom hello tom
Объект argv имеет свойство подчеркивания (_), которое извлекает аргументы, не начинающиеся с дефиса.
#!/usr/bin/env node
var argv = require('yargs').argv;
console.log('hello ', argv.n);
console.log(argv._);
Использование следующее.
$ hello A -n tom B C hello tom [ 'A', 'B', 'C' ]
6. Настройка аргументов командной строки
Модуль yargs также предоставляет 3 метода для настройки аргументов командной строки.
- demand: является ли обязательным
- default: значение по умолчанию
- describe: подсказка
#!/usr/bin/env node
var argv = require('yargs')
.demand(['n'])
.default({n: 'tom'})
.describe({n: 'your name'})
.argv;
console.log('hello ', argv.n);
Приведённый выше код указывает, что параметр n нельзя опустить, его значение по умолчанию — tom, и приводится строка описания.
Метод options позволяет записать все эти конфигурации в один объект.
#!/usr/bin/env node
var argv = require('yargs')
.option('n', {
alias : 'name',
demand: true,
default: 'tom',
describe: 'your name',
type: 'string'
})
.argv;
console.log('hello ', argv.n);
Иногда некоторым параметрам не нужно значение, и они действуют только как переключатели. В этом случае можно использовать метод boolean, чтобы указать, что эти параметры возвращают булевы значения.
#!/usr/bin/env node
var argv = require('yargs')
.boolean(['n'])
.argv;
console.log('hello ', argv.n);
В приведённом выше коде параметр n всегда возвращает булево значение. Использование выглядит следующим образом.
$ hello hello false $ hello -n hello true $ hello -n tom hello true
Метод boolean также можно записать как свойство в объекте options.
#!/usr/bin/env node
var argv = require('yargs')
.option('n', {
boolean: true
})
.argv;
console.log('hello ', argv.n);
7. Справочная информация
Модуль yargs предоставляет следующие методы для создания справочной информации.
- usage: формат использования
- example: предоставляет примеры
- help: отображает справочную информацию
- epilog: отображается в конце справочной информации
#!/usr/bin/env node
var argv = require('yargs')
.option('f', {
alias : 'name',
demand: true,
default: 'tom',
describe: 'your name',
type: 'string'
})
.usage('Usage: hello [options]')
.example('hello -n tom', 'say hello to Tom')
.help('h')
.alias('h', 'help')
.epilog('copyright 2015')
.argv;
console.log('hello ', argv.n);
Результат выполнения выглядит следующим образом.
$ hello -h Usage: hello [options] Options: -f, --name your name [string] [required] [default: "tom"] -h, --help Show help [boolean] Examples: hello -n tom say hello to Tom copyright 2015
8. Подкоманды
Модуль yargs также позволяет задавать подкоманды в стиле Git с помощью метода command.
#!/usr/bin/env node
var argv = require('yargs')
.command("morning", "good morning", function (yargs) {
console.log("Good Morning");
})
.command("evening", "good evening", function (yargs) {
console.log("Good Evening");
})
.argv;
console.log('hello ', argv.n);
Использование следующее.
$ hello morning -n tom Good Morning hello tom
Эту возможность можно комбинировать с модулем shellojs.
#!/usr/bin/env node
require('shelljs/global');
var argv = require('yargs')
.command("morning", "good morning", function (yargs) {
echo("Good Morning");
})
.command("evening", "good evening", function (yargs) {
echo("Good Evening");
})
.argv;
console.log('hello ', argv.n);
У каждой подкоманды часто есть собственные аргументы, поэтому их нужно указывать отдельно в функции обратного вызова. В функции обратного вызова сначала необходимо использовать метод reset, чтобы сбросить объект yargs.
#!/usr/bin/env node
require('shelljs/global');
var argv = require('yargs')
.command("morning", "good morning", function (yargs) {
echo("Good Morning");
var argv = yargs.reset()
.option("m", {
alias: "message",
description: "provide any sentence"
})
.help("h")
.alias("h", "help")
.argv;
echo(argv.m);
})
.argv;
Использование следующее.
$ hello morning -m "Are you hungry?" Good Morning Are you hungry?
9. Разное
(1) Возвращаемое значение
Согласно традиции Unix, программа возвращает 0 при успешном завершении, иначе возвращает 1.
if (err) {
process.exit(1);
} else {
process.exit(0);
}
(2) Перенаправление
Unix позволяет программам перенаправлять данные с помощью каналов.
$ ps aux | grep 'node'
Скрипты могут получать перенаправленные данные, прослушивая событие data у стандартного ввода.
process.stdin.resume();
process.stdin.setEncoding('utf8');
process.stdin.on('data', function(data) {
process.stdout.write(data);
});
Вот как это использовать:
$ echo 'foo' | ./hello hello foo
(3) Системные сигналы
Операционная система может отправлять сигналы запущенным процессам, а объект процесса может прослушивать события сигналов.
process.on('SIGINT', function () {
console.log('Got a SIGINT');
process.exit(0);
});
Способ отправки сигналов следующий.
$ kill -s SIGINT [process_id]
Оригинал статьи: http://www.ruanyifeng.com/blog/2015/05/command-line-with-node.html