Unitech / Unitech/pm2

Problem with starting pm2 app in symlinked directories

Open
#5,939 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
JavaScript
Stars
43.3k
Forks
2.7k
PR merge metrics
No merged PRs in 30d

Description

I found https://github.com/Unitech/pm2/issues/1663 and while it is closed and seems resolved, the fundamental problem lives on.

In our experience there's a problem with resolving symlinks with pm2, take our example when using DeployHQ (I guess it applies to any deployment service that uses an atomic or zero-downtime deployment based on symlinks) to deploy a Next.js app (but any type of app will have the same problem) that is restarted with pm2.

Assume our deployment path is /var/www/example.com, and zero-downtime option is enabled. This means that the directory structure is like this:

$ ls -l /var/www/example.com
lrwxrwxrwx 1 next next   25 Jan 17 13:24 current -> ./releases/20250117122009
drwxr-xr-x 4 next next 4096 Jan 17 13:24 releases
drwxr-xr-x 2 next next 4096 Jan 15 18:23 shared

Now I navigate to the "current" path: cd /var/www/example.com/current
And run : pm2 start npm --name nextjs-app -- run start
Assume that the app is running correctly, I would run pm2 save to dump the state and allow pm2 startup to start the app on boot.

If I run pm2 show nextjs-app here's a truncated result:

┌───────────────────┬────────────────────────────────────────────────────────┐
│ status            │ online                                                 │
│ name              │ nextjs-app                                             │
│ script path       │ /usr/bin/npm                                           │
│ script args       │ run start                                              │
│ interpreter       │ node                                                   │
│ interpreter args  │ N/A                                                    │
│ exec cwd          │ /var/www/example.com/releases/20250117122009           │
│ exec mode         │ fork_mode                                              │
│ node.js version   │ 20.17.0                                                │
│ node env          │ N/A                                                    │
└───────────────────┴────────────────────────────────────────────────────────┘

Notice how the exec cwd is not the current symlink directory, but it has been resolved to the release subdirectory.

If I inspect the file ~/.pm2/dump.pm2, I find the problem:

[...]
    "pm_exec_path": "/usr/bin/npm",
    "pm_cwd": "/var/www/example.com/releases/20250117122009",
[...]
    "PWD": "/var/www/example.com/current",
[...]

At next deployment, when the app is restarted (an SSH command with pm2 restart is issued) the app will be restarted in the old directory, meaning the new version is not used. Furthermore, after a number of deployments (specifically one more that the Atomic Retention value, in our case it's 2) the app will not start because the deployment service has deleted the original release when the app has been started.

Our workaround is to edit the dump file, setting pm_cwd to /var/www/example.com/current, and then run pm2 kill and pm2 resurrect.

$ pm2 -v
5.4.2

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Reproduce the deployment flow with pm2 start, pm2 save, and pm2 restart from /var/www/example.com/current, then inspect ~/.pm2/dump.pm2 and the reported pm_cwd value. Done means restarting after the symlink moves uses the current release rather than the deleted release directory, including after pm2 kill and pm2 resurrect.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, node.js
Domain
cli, devops
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.