Часто в проектах необходимо автоматизировать запуск функций или файлов в определенное время. Для решения этой задачи в Node.js можно использовать библиотеку node-cron
.
В этой статье мы разберем аспекты установки пакета, рассмотрим лучшие практики работы с библиотекой, напишем проект и задеплоим его в облаке.
Cron — это планировщик задач в Unix-подобных операционных системах (например, Linux), который позволяет автоматически запускать команды или скрипты по расписанию. Расписание указывается в формате crontab
, где каждая строка описывает время выполнения задачи и команду, которую нужно запустить.
node-cron — это библиотека для Node.js, которая реализует функциональность Cron внутри JavaScript-приложений. Она позволяет создавать задачи, которые будут выполняться по заданному расписанию, ориентируясь на реальное время в выбранном часовом поясе, аналогично Cron в Unix-системах
Основные преимущества node-cron:
node-cron имеет синтаксис, аналогичный обычному Cron:
Допустимые значения для полей:
Поле |
Значение |
Секунды |
0-59 |
Минуты |
0-59 |
Часы |
0-23 |
День месяца |
1-31 |
Месяц |
1-12 (или названия на английском языке) |
День недели |
0-7 (или названия на английском языке, 0 или 7 — воскресенье) |
Использование кратных значений
const cron = require('node-cron');
cron.schedule('1,2,4,5 * * * *', () => {
console.log('выполняется каждую 1, 2, 4 и 5 минуту');
});
Использование диапазона
const cron = require('node-cron');
cron.schedule('1-5 * * * *', () => {
console.log('выполняется каждую 1-5 минуту');
});
Использование значений шагов
Значения шагов можно использовать в сочетании с диапазонами, указав после диапазона символ /
и число. Например: 1-10/2
— это то же самое, что 2, 4, 6, 8, 10
. Шаги могут использоваться после звездочки, поэтому, если вы хотите запускать каждые две минуты, просто используйте */2
.
const cron = require('node-cron');
cron.schedule('*/2 * * * *', () => {
console.log('выполняется каждые 2 минуты');
});
Использование наименований
Для обозначения месяца и дня недели можно использовать их полные названия:
const cron = require('node-cron');
cron.schedule('* * * January,September Sunday', () => {
console.log('выполняется по воскресеньям января и сентября');
});
Или сокращенные:
const cron = require('node-cron');
cron.schedule('* * * Jan,Sep Sun', () => {
console.log(''выполняется по воскресеньям января и сентября');
});
В node-cron используется основной метод, который планирует выполнение задачи, — Schedule. Как аргументы он принимает выражение cron, функцию-задачу и дополнительную конфигурацию:
scheduled
— состояние задачи, запущена она или нет. Тип данных — Boolean.timezone
— часовой пояс, время которого будет использовать cron. Тип данных — String.Пример:
const cron = require('node-cron');
cron.schedule('0 1 * * *', () => {
console.log('Выполнится в 01:00 по Московскому времени');
}, {
scheduled: true,
timezone: "Europe/Moscow"
});
Для управления статусами задач используются два метода:
Start
— служит для запуска остановленной задачи.Stop
— служит для остановки запущенной задачи.Пример:
Запуск задачи
const cron = require('node-cron');
const task = cron.schedule('* * * * *', () => {
console.log('Остановленная задача');
}, {
scheduled: false
});
task.start();
Остановка задачи
const cron = require('node-cron');
const task = cron.schedule('* * * * *', () => {
console.log(Будет выполняться каждую минуту, пока не остановится);
});
task.stop();
vds
Подготовим наше пространство для работы с Node.js и node-cron.
Чтобы запустить локальную разработку, нужно установить актуальную версию Node.js (рекомендуем v22.14.0 LTS). Вместе с Node.js установится npm — стандартный менеджер пакетов JavaScript.
Для Windows:
Для Linux / MacOS:
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
\. "$HOME/.nvm/nvm.sh"
nvm install 22
node -v && npm -v
Убедитесь, что версии Node.js и npm корректно отображаются.
Создайте новый каталог для проекта и перейдите в него:
mkdir node-cron-project && cd node-cron-project
Инициализируйте проект:
npm init -y
Установите node-cron:
npm install --save node-cron
Рассмотрим простой, но интересный проект на основе библиотеки node-cron.
Задача: автоматически получать курс доллара США к рублю и сохранять эти данные в файл.
Проект простой, но он отлично демонстрирует основные возможности node-cron и показывает, как использовать библиотеку для регулярных задач.
Установим дополнительные зависимости для проекта:
npm install axios fs
axios
— для выполнения HTTP-запросов, будем использовать для работы с API.fs
— для работы с файловой системой, будем использовать для записи данных в файл.Задачи нашего приложения будут следующими:
exchange_rates.txt
.Создадим файл index.js
, в котором мы будем писать весь наш код.
const cron = require('node-cron');
const axios = require('axios');
const fs = require('fs');
if (!fs.existsSync('exchange_rates.txt')) {
fs.writeFileSync('exchange_rates.txt', '');
}
async function getExchangeRate() {
try {
const response = await axios.get('https://open.er-api.com/v6/latest/USD');
const rate = response.data.rates.RUB;
return rate;
} catch (error) {
console.error('Ошибка при получении курса:', error);
return null;
}
}
function saveData(rate) {
const currentTime = new Date().toLocaleString();
const data = { time: currentTime, rate };
fs.appendFileSync('exchange_rates.txt', `${JSON.stringify(data)}\n`);
console.log(`Курс сохранён: ${currentTime} - ${rate} RUB`);
}
cron.schedule('* * * * *', async () => {
const rate = await getExchangeRate();
if (rate !== null) {
saveData(rate);
}
});
console.log('Сбор данных запущен...');
Рассмотрим код подробнее:
if (!fs.existsSync('exchange_rates.txt'))
проверяем наличие файла exchange_rates.txt
. Если его нет — создаем.getExchangeRate
: Получает курс доллара к рублю через публичный API. В данном примере используется API от open.er-api.com.saveData
: Сохраняет полученные данные (курс и текущее время) в файл exchange_rates.txt
. Данные добавляются в конец файла, чтобы можно было отслеживать историю изменений.cron.schedule('* * * * *')
, которое выполняется каждую минуту. В это время вызывается функция getExchangeRate
, а результат сохраняется в файл.Для запуска нашего проекта воспользуемся командой:
node index.js
После запуска получаем вывод в консоль:
Спустя некоторое время получаем логи в консоль:
И в созданном файле exchange_rates.txt
появилась информация о дате, времени и курсе:
Этот проект демонстрирует простое и эффективное использование node-cron для регулярного сбора данных и их сохранения. Вы можете легко адаптировать его для других целей, заменив источник данных или частоту выполнения задачи.
Применим node-cron в прикладной задаче. Напишем скрипт, который автоматически отправляет письма. Данный кейс часто применяется компаниями для отправки различной рекламной информации. Это решение простое в реализации, но функциональное.
Для начала нам необходимо получить токен для своей почты Gmail:
nodemailer
своему приложению и создайте его.Для начала установим необходимые библиотеки. node-cron уже установлен, поэтому нам необходимо установить только nodemailer
.
npm install nodemailer
Теперь создайте файл app.js
и напишите туда следующий код:
const nodemailer = require('nodemailer');
const cron = require('node-cron');
const recipients = [
'recipient1@gmail.com',
'recipient2@mail.ru'
];
let transporter = nodemailer.createTransport({
service: 'gmail',
auth: {
user: 'sender@example.com',
pass: 'PASSWORD'
}
});
function sendEmail(recipient) {
let mailOptions = {
to: recipient,
subject: 'Запланированное письмо',
text: 'Письмо отправленное автоматически по заданному расписанию node-cron',
html: '<b>Письмо отправленное автоматически по заданному расписанию node-cron</b>'
};
transporter.sendMail(mailOptions, function(error, info){
if (error) {
console.log(`Ошибка отправки письма на email ${recipient}:`, error);
} else {
console.log(`Письмо успешно отправлено на email ${recipient}:`, info.response);
}
});
}
cron.schedule('* * * * *', () => {
console.log('Запуск cron-tab');
recipients.forEach((recipient) => {
sendEmail(recipient);
});
});
Здесь:
recipients
с получателями нашего письма.let transporter
хранит в себе информацию об аутентификации отправителя. В переменную user
вам необходимо написать свою gmail-почту, а в pass
— полученный ранее код.sendEmail
принимает в себя получателя письма, переменная let mailOptions
хранит информацию о нашем письме: получателя, тему и текст (в примере указаны два варианта: просто текст и текст в HTML-формате). Функция transporter.sendMail
отправляет письмо.cron.schedule('* * * * *')
создает задачу отправлять письмо каждую минуту.Для запуска файла пишем команду:
node app.jS
И спустя пару минут получаем вывод в консоль:
Проверив почту, получаем наши письма:
После всех этапов создания нам необходимо выгрузить наше приложение в облако.
Для нашего небольшого приложения с автоматической отправкой писем подойдет конфигурация CPU 1 x 3.3ГГц, RAM 1 ГБ, NVMe 15 ГБ, 1 IPv4 стоимостью 300 ₽ в месяц.
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
\. "$HOME/.nvm/nvm.sh"
nvm install 22
node -v && npm -v
Если всё установлено корректно, мы получим следующий вывод:
cd /home && mkdir nodemailer
app.js
и package.json
.На Windows для этого можно использовать FileZilla. На Linux/MacOS воспользуйтесь командой:
rsync -av --exclude="node_modules" ./ root@109.73.207.170:/home/nodemailer
Она состоит из:
--exclude="node_modules"
— не включаем директорию с установленными библиотеками../
— путь, откуда копируемroot@109.73.207.170:/home/nodemailer
— путь, куда копируем. Обратите внимание на формат: username@server_ip:/path
.cd /home/nodemailer && ls
Если всё правильно, мы получим вывод:
npm install
node app.js
/etc/systemd/system/nodemailer.service
:sudo nano /etc/systemd/system/nodemailer.service
Добавьте в файл следующее содержимое:
[Unit]
Description=NodeMailer Service
After=network.target
[Service]
User=root
WorkingDirectory=/home/nodemailer
ExecStart=/root/.nvm/versions/node/v22.14.0/bin/node /home/nodemailer/app.js
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
Данный файл необходим для удобного управления и постоянной работы нашего приложения, даже после закрытия терминала. Обратите внимание, в ExecStart
необходимо указать абсолютный путь до установленной node и абсолютный путь до файла который мы будем запускать.
При необходимости измените значения следующих переменных:
WorkingDirectory
— директория проектаExecStart
— команда для запуска приложенияsystemd
и включите службу:sudo systemctl daemon-reload
sudo systemctl enable nodemailer.service
sudo systemctl start nodemailer.service
sudo systemctl status nodemailer.service
При нормальном запуске в поле «Active» находится значение «active (running)».
Просмотр логов:
sudo journalctl -u nodemailer.service -f
При необходимости управлять службами можно командами:
Перезапуск
sudo systemctl restart nodemailer.service
Остановка
sudo systemctl stop nodemailer.service
Удаление службы (если необходимо)
sudo systemctl disable nodemailer.service
sudo rm /etc/systemd/system/nodemailer.service
sudo systemctl daemon-reload
Надежные VDS/VPS для ваших проектов
Библиотека node-cron в проектах на платформе Node.js является мощным инструментом для автоматизации задач, связанных с выполнением повторяющихся операций в заданное время. В данной статье мы создали простое приложение, которое получает по API курс доллара к рублю и записывает данные в файл, и рассмотрели реальный пример использования библиотеки. Мы наглядно убедились, что библиотека позволяет легко настраивать выполнение заданий по расписанию, будь то получение и дальнейшая обработка данных либо взаимодействие с пользователями.
Таким образом, node-cron представляет собой отличный выбор для тех разработчиков, которым требуется надежная и удобная система планирования задач в рамках проектов на Node.js. Ее функциональность и удобство делают эту библиотеку незаменимым инструментом в арсенале любого современного backend-разработчика.