Скрипты Node: от основ до продвинутого уровня
Основные подходы к созданию скриптов Node.js
Как реализовать утилиту для поиска строк в файлах с использованием аргументов командной строки?
Эффективный способ заключается в применении встроенных модулей fs/promises и process.argv. Это позволяет быстро написать скрипт, который принимает путь к файлу и искомую строку, читает файл и выводит совпадения. Такой подход широко используется для администрирования и обработки логов.
const fs = require('fs/promises');
const [,, filePath, searchWord] = process.argv;
(async () => {
try {
const data = await fs.readFile(filePath, 'utf8');
const lines = data.split('\n').filter(line => line.includes(searchWord));
lines.forEach(line => console.log(line));
} catch (err) {
console.error('Ошибка:', err.message);
}
})();Node js https (https в node.js)
Пояснение шагов:
- Импорт модуля fs/promises для асинхронной работы с файлами.
- Деструктуризация process.argv для получения аргументов (первые два элемента - node и путь к скрипту, остальные - пользовательские).
- Обёртка в асинхронную IIFE для использования await.
- Чтение файла, разбивка на строки, фильтрация по include.
- Вывод результата в консоль, обработка ошибок через try/catch.
Как выполнить простой скрипт без параметров?
Самый простой вариант - создать JavaScript файл с любым кодом и запустить его командой node. Этот способ подходит для быстрых тестов, проверки идей и одноразовых операций.
// hello.js
console.log('Привет, Node.js!');
console.log('Текущее время:', new Date().toLocaleString());Node js lts (версия node.js lts)
Запуск: node hello.js. Вывод будет содержать строки приветствия и текущую дату. Никакие дополнительные модули не требуются.
Как передавать именованные параметры в скрипт?
Для повышения удобства можно обрабатывать флаги вручную, анализируя process.argv. Этот метод полезен, когда не хочется подключать внешние библиотеки.
const args = process.argv.slice(2);
const params = {};
for (let i = 0; i < args.length; i += 2) {
const key = args[i].replace(/^--/, '');
params[key] = args[i + 1];
}
console.log('Полученные параметры:', params);
// Пример запуска: node script.js --name John --age 30
Node js npm (менеджер пакетов npm в node.js)
Скрипт разбирает пары --ключ значение. Рекомендуется следить, чтобы чётное количество аргументов и значения не начинались с --.
Как использовать сторонние npm пакеты для парсинга аргументов?
Библиотеки yargs или commander предоставляют мощные средства для описания интерфейса командной строки. Они автоматически генерируют справку, проверяют типы и поддерживают вложенные команды. Этот вариант идеален для серьёзных утилит.
// установка: npm install yargs
const yargs = require('yargs/yargs');
const { hideBin } = require('yargs/helpers');
const argv = yargs(hideBin(process.argv))
.option('name', { alias: 'n', type: 'string', demandOption: true, describe: 'Имя пользователя' })
.option('greeting', { alias: 'g', type: 'string', default: 'Привет' })
.argv;
console.log(`${argv.greeting}, ${argv.name}!`);Node js scripts (скрипты node.js)
Запуск: node greet.js --name Мир. Выведет "Привет, Мир!". yargs обрабатывает ошибки и выводит справку при --help.
Как читать и записывать файлы асинхронно?
Для работы с файлами используется модуль fs (или fs/promises для promise-based API). Это необходимо для скриптов, которые обрабатывают данные, конфигурации или логи.
const fs = require('fs/promises');
async function processFile() {
try {
const content = await fs.readFile('./input.txt', 'utf8');
const transformed = content.toUpperCase();
await fs.writeFile('./output.txt', transformed);
console.log('Файл обработан');
} catch (err) {
console.error('Ошибка:', err);
}
}
processFile();
Сначала читается исходный файл, затем преобразуется в верхний регистр и записывается в новый файл. Обработка ошибок обязательна.
Как запускать системные команды из скрипта?
Модуль child_process позволяет выполнять внешние программы и получать их вывод. Это пригодится для интеграции с Bash, git, Docker и другими инструментами.
const { exec } = require('child_process');
exec('ls -la', (error, stdout, stderr) => {
if (error) {
console.error(`Ошибка: ${error.message}`);
return;
}
if (stderr) {
console.error(`Stderr: ${stderr}`);
}
console.log('Вывод:', stdout);
});
Функция exec запускает команду в shell и возвращает результат в колбеке. Для больших объёмов данных лучше использовать spawn.
Как настроить псевдонимы команд в package.json?
В поле scripts файла package.json можно определить сокращения для часто используемых команд. Это упрощает работу в команде и стандартизирует запуск.
{
"scripts": {
"start": "node server.js",
"dev": "nodemon server.js",
"clean": "rm -rf dist && mkdir dist",
"greet": "node greet.js --name"
}
}
Теперь команды npm start, npm run dev, npm run clean будут выполнять указанные действия. Параметры можно передавать через -- (npm run greet -- World).
Продвинутые примеры скриптов Node.js
Пример 1: Копирование файлов с прогрессом через потоки и yargs
// copy.js
const fs = require('fs');
const path = require('path');
const yargs = require('yargs/yargs');
const { hideBin } = require('yargs/helpers');
const argv = yargs(hideBin(process.argv))
.option('source', { alias: 's', type: 'string', demandOption: true, describe: 'Исходный файл' })
.option('dest', { alias: 'd', type: 'string', demandOption: true, describe: 'Целевой файл' })
.argv;
const sourcePath = path.resolve(argv.source);
const destPath = path.resolve(argv.dest);
const readStream = fs.createReadStream(sourcePath);
const writeStream = fs.createWriteStream(destPath);
let totalBytes = 0;
readStream.on('data', (chunk) => {
totalBytes += chunk.length;
process.stdout.write(`\rСкопировано ${totalBytes} байт`);
});
readStream.pipe(writeStream);
writeStream.on('finish', () => {
console.log('\nКопирование завершено');
});
readStream.on('error', (err) => {
console.error('Ошибка чтения:', err.message);
});
writeStream.on('error', (err) => {
console.error('Ошибка записи:', err.message);
});
$ node copy.js -s bigfile.mp4 -d backup.mp4 Скопировано 1024000 байт Копирование завершено
Пояснение: используются потоки для эффективной обработки больших файлов, отображается прогресс копирования в реальном времени.
Пример 2: Мониторинг изменений в папке с chokidar
// watcher.js
const chokidar = require('chokidar');
const path = require('path');
const watchDir = process.argv[2] || '.';
const watcher = chokidar.watch(watchDir, { persistent: true });
watcher
.on('add', filePath => console.log(`Файл добавлен: ${path.relative('.', filePath)}`))
.on('change', filePath => console.log(`Файл изменён: ${path.relative('.', filePath)}`))
.on('unlink', filePath => console.log(`Файл удалён: ${path.relative('.', filePath)}`));
console.log(`Наблюдение за каталогом "${watchDir}" запущено...`);
$ node watcher.js ./logs Наблюдение за каталогом "./logs" запущено... Файл добавлен: error.log Файл изменён: error.log
Пояснение: скрипт отслеживает появление, изменение и удаление файлов в указанной папке, полезно для автоматизации при разработке.
Пример 3: Генерация тестовых данных с faker
// seed.js
const { faker } = require('@faker-js/faker');
const fs = require('fs/promises');
const COUNT = 100;
const users = Array.from({ length: COUNT }, (_, i) => ({
id: i + 1,
name: faker.person.fullName(),
email: faker.internet.email(),
createdAt: faker.date.past().toISOString()
}));
(async () => {
await fs.writeFile('users.json', JSON.stringify(users, null, 2));
console.log(`Сгенерировано ${COUNT} пользователей`);
})();
$ node seed.js Сгенерировано 100 пользователей
Пояснение: создаётся файл с фиктивными данными пользователей для тестирования баз данных или API.
Пример 4: Пакетная конвертация изображений с sharp
// convert.js
const sharp = require('sharp');
const path = require('path');
const fs = require('fs/promises');
const inputDir = './images';
const outputDir = './thumbnails';
(async () => {
await fs.mkdir(outputDir, { recursive: true });
const files = await fs.readdir(inputDir);
for (const file of files) {
if (file.endsWith('.jpg') || file.endsWith('.png')) {
const inputPath = path.join(inputDir, file);
const outputPath = path.join(outputDir, `thumb_${file}`);
await sharp(inputPath)
.resize(200, 200)
.toFile(outputPath);
console.log(`Обработан: ${file}`);
}
}
console.log('Конвертация завершена');
})();
$ node convert.js Обработан: photo1.jpg Обработан: photo2.png Конвертация завершена
Пояснение: скрипт находит все изображения JPG и PNG в папке, уменьшает их до 200x200 пикселей и сохраняет в другую папку.
Пример 5: Выполнение удалённой команды по SSH
// ssh-exec.js
const { Client } = require('ssh2');
const conn = new Client();
conn.on('ready', () => {
conn.exec('uptime', (err, stream) => {
if (err) throw err;
stream.on('data', (data) => {
console.log('STDOUT: ' + data);
});
stream.stderr.on('data', (data) => {
console.log('STDERR: ' + data);
});
stream.on('close', () => conn.end());
});
}).connect({
host: 'example.com',
username: 'user',
privateKey: require('fs').readFileSync('/path/to/key')
});
$ node ssh-exec.js STDOUT: 10:30:15 up 30 days, 2:15, 1 user, load average: 0.00, 0.01, 0.05
Пояснение: скрипт подключается к удалённому серверу по SSH, выполняет команду uptime и выводит результат. Полезно для автоматизации администрирования.