| name | pm2 |
| description | PM2 — process manager for long-running training jobs on remote servers. ecosystem.config.js, common commands, and SSH workflow with uv. |
PM2
Installation
npm install -g pm2
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
source ~/.bashrc
nvm install --lts && npm install -g pm2
ecosystem.config.js (standard pattern)
module.exports = {
apps: [{
name: "stgraph-train",
cwd: "/home/user/fraud-detection-blockchain",
script: "uv",
args: "run python -m stgraph_fs.cli train --config configs/train.yaml",
autorestart: false,
watch: false,
max_restarts: 0,
time: true,
env: {
CUDA_VISIBLE_DEVICES: "0",
}
}]
};
CRITICAL: Always set autorestart: false. PM2 restarts processes by default — a training job that finishes will loop forever without this.
Starting jobs
pm2 start ecosystem.config.js
pm2 start --name stgraph-train --no-autorestart --cwd /path/to/repo -- \
uv run python -m stgraph_fs.cli train --config configs/train.yaml
pm2 start ecosystem.config.js --only stgraph-train
Monitoring & logs
pm2 ls
pm2 status
pm2 logs stgraph-train
pm2 logs stgraph-train --lines 200
pm2 logs --err
pm2 monit
Job control
pm2 stop stgraph-train
pm2 restart stgraph-train
pm2 delete stgraph-train
pm2 kill
SSH workflow for remote training
git add . && git commit -m "..." && git push
ssh user@server
cd /path/to/repo
git pull && uv sync
uv run python -m stgraph_fs.cli train --fast_dev_run
pm2 start ecosystem.config.js
pm2 ls
exit
Log file locations
~/.pm2/logs/<app-name>-out.log
~/.pm2/logs/<app-name>-error.log
{
out_file: "./logs/train-out.log",
error_file: "./logs/train-err.log",
merge_logs: true,
}
Persist across reboot (requires sudo)
pm2 save
pm2 startup
Pitfalls
- Missing
autorestart: false will cause a completed training job to restart in an infinite loop, overwriting outputs/.
- Only run one training job at a time per GPU — concurrent jobs will OOM or corrupt outputs.
pm2 logs streams in real time; use --lines N to see recent history without streaming.
- After SSH disconnect, PM2 daemon keeps running — you don't need
nohup or screen.
pm2 kill stops the daemon entirely — all jobs stop. Use pm2 stop for individual jobs.