# Обновление Node под pm2 без сюрпризов

Опубликовано 2026-11-05 · Node.js, nvm, pm2, systemd, Linux · https://home.tigran.manukyan.dev/ru/notes/node-upgrade-under-pm2.html

**TL;DR:** При обновлении Node.js через nvm под pm2: привяжите `nvm alias default` к мажорной версии, поправьте сохранённый PATH в ~/.pm2/dump.pm2 для приложений в fork mode, перегенерируйте systemd-юнит pm2 с новым бинарником node и проверьте `readlink /proc/PID/exe`, прежде чем удалять старую версию.

Вышел security-релиз, и я перевёл несколько pm2-приложений на свежую версию Node через nvm. Сам `nvm install` занял минуту. А вот найти все места, где пряталась старая версия, вышло заметно дольше. Ниже порядок, который сработал с одним рестартом на каждое приложение.

## 1. Привяжите default в nvm к мажорной версии

Если `default` у вас указывает на `lts/*`, nvm переписывает этот алиас при каждом запросе списка версий. Как только новая ветка становится LTS, `default` начинает указывать на версию, которую вы не ставили, и новые шеллы стартуют вообще без `node`.

```
nvm install 24 --reinstall-packages-from=22
nvm alias default 24
```

`--reinstall-packages-from` ставит ту же *версию* pm2, что была, а не последнюю. Здесь это ровно то, что нужно.

## 2. Приложения в fork mode помнят старый PATH

pm2 сохраняет окружение каждого приложения в `~/.pm2/dump.pm2`. Приложения в fork mode запускают `node` через сохранённый `PATH`, поэтому после рестарта демона они тихо продолжают работать на старом бинарнике. Приложения в cluster mode используют node самого демона.

Сделайте бэкап дампа и замените старую версию в `PATH`, `NVM_BIN`, `NVM_INC` и `_`. `pm2 restart --update-env` тоже подойдёт, но если запускать его неинтерактивной командой по SSH, он подхватит урезанный PATH этого шелла.

## 3. Перегенерируйте systemd-юнит

В юните, который создаёт `pm2 startup`, путь к node зашит намертво. Сгенерируйте его заново с новым бинарником:

```
NEW=$HOME/.nvm/versions/node/v24.x.y
sudo env PATH=$NEW/bin:$PATH $NEW/bin/node $NEW/lib/node_modules/pm2/bin/pm2 \
  startup systemd -u $USER --hp $HOME
sudo systemctl daemon-reload
sudo systemctl restart pm2-$USER
```

`pm2 update` по SSH для этого не подходит: он перезапустит демон внутри scope вашей SSH-сессии, а не под systemd.

## 4. Проверьте и только потом удаляйте

```
for p in $(pgrep -f node); do readlink /proc/$p/exe; done | sort | uniq -c
pm2 save
```

`nvm uninstall` — только когда на старую версию больше ничего не ссылается.
