Menu

process.argv в Node.js: аргументы командной строки

process.argv это массив с командной строкой, которой запустили программу: исполняемый файл node, путь к скрипту, а затем все введённые аргументы. Чтобы получить только свои аргументы, используйте process.argv.slice(2).

На этой странице есть исполняемые редакторы: меняйте, запускайте и сразу видите результат.

process.argv это массив с командной строкой, которой запустили вашу программу на Node.js. Индекс 0 это путь к исполняемому файлу node, индекс 1 это путь к вашему скрипту, а ваши собственные аргументы начинаются с индекса 2. Поэтому process.argv.slice(2) даёт ровно то, что пользователь ввёл после имени файла, и всегда в виде строк.

Первые два элемента это полные пути, поэтому программа выводит только их последнюю часть (node и index.js), а затем [ 'Ada', '42', '--verbose' ]. Измените строку аргументов на Grace 7 и запустите снова: массив поменяется следом.

Что попадает в process.argv

Оболочка делит строку после node по пробелам и передаёт Node.js полученные части. Флаги, записанные до имени файла, относятся к самому Node.js, а не к вашей программе:

node --max-old-space-size=4096 index.js --port=8080
# process.argv.slice(2) is [ '--port=8080' ]
# process.execArgv is      [ '--max-old-space-size=4096' ]

Кавычки объединяют слова в один аргумент ("Ada Lovelace" приходит одной строкой), а шаблоны вроде *.txt оболочка раскрывает в имена файлов ещё до того, как их увидит Node.js.

Аргументы через slice(2)

Большинство скриптов деструктурируют ожидаемые аргументы и дают каждому значение по умолчанию:

Программа вывела Hello, Ada: один аргумент заполнил name, а greeting взял значение по умолчанию. Добавьте Hi после Ada в строке аргументов, и она выведет Hi, Ada; очистите строку, и получите Hello, world.

Числа приходят строками

У оболочки нет типов. Каждый аргумент это строка, поэтому арифметика с ними ломается, пока вы их не преобразуете:

a + b склеил строки в 75, а Number() дал 12. Слово, которое не является числом, превращается в NaN, поэтому проверяйте через Number.isNaN и выводите подсказку по использованию, а не работайте дальше со сломанным значением.

Разбор флагов --name=value вручную

Для пары флагов хватит короткого цикла. Этот превращает --port=8080 в port: '8080', одиночный --verbose в true, а всё остальное оставляет позиционными аргументами:

Программа вывела {"port":"8080","verbose":true} и [ 'build', 'src' ], причём port остался строкой. Этот цикл не понимает короткие флаги вроде -p и значение в следующем аргументе (--port 8080); для этого используйте встроенный парсер ниже.

util.parseArgs, встроенный парсер

В Node.js 18.3 и новее есть util.parseArgs, который понимает длинные и короткие флаги, значения в следующем аргументе, булевы флаги и значения по умолчанию:

const { parseArgs } = require('node:util');

// node index.js -p 8080 --verbose src
const { values, positionals } = parseArgs({
    options: {
        port: { type: 'string', short: 'p', default: '3000' },
        verbose: { type: 'boolean', short: 'v' },
    },
    allowPositionals: true,
});

console.log(values);      // [Object: null prototype] { port: '8080', verbose: true }
console.log(positionals); // [ 'src' ]

По умолчанию parseArgs читает process.argv.slice(2). Он бросает ошибку на опции, которую вы не объявили, и так ловит опечатки вроде --prot; передайте strict: false, чтобы принимать неизвестные флаги. Типы опций бывают только string и boolean, так что числам всё равно нужен Number(). values это объект без прототипа, поэтому он выводится с [Object: null prototype]; читайте его как обычный объект.

Частые ошибки

Считать process.argv[0] первым аргументом. Это путь к node. Ваш первый аргумент это process.argv[2].

Забыть, что всё это строки. '10' > '9' равно false, потому что строки сравниваются посимвольно. Сначала преобразуйте.

Передавать секреты в аргументах. Командные строки попадают в историю оболочки и в списки процессов, которые видят другие пользователи машины. Пароли и API ключи передавайте через переменные окружения.

Часто задаваемые вопросы

Как передать аргументы в npm скрипт?

Напишите их после --: npm run start -- --port=4000. Всё, что идёт после --, npm передаёт вашему скрипту, и оно появляется в process.argv.slice(2).

Почему process.argv[2] равен undefined?

Потому что программу запустили без этого аргумента. Задайте значение по умолчанию (process.argv[2] ?? 'guest') или выведите подсказку по использованию и остановитесь через process.exit(1).

Стоит ли брать yargs или commander вместо process.argv?

Для скрипта с парой флагов хватит встроенного util.parseArgs. Пакеты вроде commander и yargs добавляют справку, подкоманды и валидацию, и это окупается, когда у инструмента несколько команд.

Иллюстрация языков программирования Coddy

Учитесь программировать с Coddy

Начать