Search code examples
node.jsprocessportpm2

How to get list nodejs processes/app port and path?


As a freelance SysAdmin/Developer I need to get/update existing app/web on the client server. Sometime I need to update existing NodeJS app that I don't know the port or the path.

If I want to know the port, I can do easily by find apache2/PHP app config using apache2ctl -S command. But it's difficult to find the nodeJS app path even I know the port.

Usually the node app is running using pm2. pm list only show list of processes name/command like below:

root@lamp-s-4vcpu-8gb-sgp1-01:~# pm2 list
┌────┬────────────────────┬──────────┬──────┬───────────┬──────────┬──────────┐
│ id │ name               │ mode     │ ↺    │ status    │ cpu      │ memory   │
├────┼────────────────────┼──────────┼──────┼───────────┼──────────┼──────────┤
│ 11 │ .com               │ fork     │ 0    │ stopped   │ 0%       │ 0b       │
│ 6  │ DEV API            │ fork     │ 0    │ stopped   │ 0%       │ 0b       │
│ 0  │ balance Web        │ fork     │ 7    │ stopped   │ 0%       │ 0b       │
│ 4  │ balance queue      │ fork     │ 0    │ stopped   │ 0%       │ 0b       │
│ 9  │ index              │ fork     │ 133… │ online    │ 0.3%     │ 144.0mb  │
│ 10 │ index              │ fork     │ 21   │ online    │ 0.2%     │ 134.5mb  │
│ 12 │ index              │ fork     │ 13   │ online    │ 0.4%     │ 155.4mb  │
│ 7  │ longbgst           │ fork     │ 52   │ online    │ 0%       │ 40.0mb   │
│ 8  │ npm                │ fork     │ 220… │ stopped   │ 0%       │ 0b       │
│ 2  │ npm run staging    │ fork     │ 116… │ stopped   │ 0%       │ 0b       │
│ 1  │ old                │ fork     │ 0    │ stopped   │ 0%       │ 0b       │
│ 5  │ v-api dev          │ fork     │ 0    │ stopped   │ 0%       │ 0b       │
│ 3  │ develop API        │ fork     │ 358… │ stopped   │ 0%       │ 0b       │
└────┴────────────────────┴──────────┴──────┴───────────┴──────────┴──────────┘
[PM2][WARN] Current process list running is not in sync with saved list. Type 'pm2 save' to synchronize or enable autosync via 'pm2 set pm2:autodump true'

and pm2 show command only show path not the port example:

root@lamp-s-4vcpu-8gb-sgp1-01:~# pm2 show 10
 Describing process with id 10 - name index
┌───────────────────┬─────────────────────────────────────────┐
│ status            │ online                                  │
│ name              │ index                                   │
│ namespace         │ default                                 │
│ version           │ 1.0.0                                   │
│ restarts          │ 21                                      │
│ uptime            │ 2D                                      │
│ script path       │ /var/www/api-path-id/dist/index.js      │
│ script args       │ N/A                                     │
│ error log path    │ /root/.pm2/logs/index-error.log         │
│ out log path      │ /root/.pm2/logs/index-out.log           │
│ pid path          │ /root/.pm2/pids/index-10.pid            │
│ interpreter       │ node                                    │
│ interpreter args  │ N/A                                     │
│ script id         │ 10                                      │
│ exec cwd          │ /var/www/api-path-id                    │
│ exec mode         │ fork_mode                               │
│ node.js version   │ 11.15.0                                 │
│ node env          │ api_path_id                             │
│ watch & reload    │ ✘                                       │
│ unstable restarts │ 0                                       │
│ created at        │ 2020-11-16T03:29:39.945Z

Usually I need to look up using pm2 show command for each pm2 process to find the app path then got to the path and find the port on .env/config file. It's very take a long time if there are so many processes. Is any faster way to see list of running nodejs app with the port and path?

I tried commands from this question answer but not returned path or process name like below:

root@lamp-s-4vcpu-8gb-sgp1-01:~# ss -tnlp | grep "node /"
LISTEN   0         128               127.0.0.1:6030             0.0.0.0:*        users:(("node /var/www/v",pid=26000,fd=25))
LISTEN   0         128                 0.0.0.0:6031             0.0.0.0:*        users:(("node /var/www/a",pid=26006,fd=25))
LISTEN   0         128               127.0.0.1:6039             0.0.0.0:*        users:(("node /var/www/a",pid=26013,fd=25))
root@lamp-s-4vcpu-8gb-sgp1-01:~#
root@lamp-s-4vcpu-8gb-sgp1-01:~# ss -ntlp | grep $(pm2 ls | grep "SITENAME" | awk '{print $10}') | awk '{print $4}'
Usage: grep [OPTION]... PATTERN [FILE]...
Try 'grep --help' for more information.

ss -lntp | grep node command show all port but it gives wrong path (maybe cutted/substr).

root@lamp-s-4vcpu-8gb-sgp1-01:~# ss -lntp | grep node
LISTEN   0         128               127.0.0.1:6030             0.0.0.0:*        users:(("node /var/www/v",pid=26000,fd=25))
LISTEN   0         128                 0.0.0.0:6031             0.0.0.0:*        users:(("node /var/www/a",pid=26006,fd=25))
LISTEN   0         128               127.0.0.1:6039             0.0.0.0:*        users:(("node /var/www/a",pid=26013,fd=25))
LISTEN   0         128               127.0.0.1:3001             0.0.0.0:*        users:(("node",pid=29886,fd=24))
root@lamp-s-4vcpu-8gb-sgp1-01:~# cd /var/www/a
-bash: cd: /var/www/a: No such file or directory

I need list of port and path(or atleast pm2 process name).


Solution

  • I just learn some Linux commands to make this:

    METHOD 1 usingss without sorting (not recommended)

    Step 1 - Get the PIDs

    ss -lntp | grep node | cut -d "=" -f2 - | cut -d "," -f 1 - > pids.txt
    

    Explanation:

    1. ss -lntp will print the list of Socket Statistics.
    2. grep node will print only node process/sockets.
    3. cut -d "=" -f2 - will cut the output of command #2 using = as the delimiter and get the second column (-f2). example result is 26000,fd
    4. cut -d "," -f 1 - to remove ,fd from command #3 and will cut the output of step #2 using , as the delimiter and get the first column (-f1). example result is 26000
    5. > pids.txt to save the output to pids.txt file.

    Step 2 - Get the Ports

    ss -lntp | grep node | awk '{ print $4 }' > ports.txt
    

    Explanation:

    1. ss -lntp will print the list of Socket Statistics.
    2. grep node will print only node process/sockets.
    3. awk '{ print $4 }' will print the fourth column, i.e. the one containing 0.0.0.0:6031
    4. > ports.txt to save the output to ports.txt file.

    Step 3 - Get the Paths from the PIDs

    ps -eLf | grep -Fwf pids.txt   | awk '!x[$2]++' | awk '{ print $11 }' > proc.txt
    

    Explanation:

    1. ps -eLf will print the list of Process status.
    2. grep -Fwf pids.txt will print only pid/process number from pids.txt.(but its still have so many duplicate main process)
    3. awk '!x[$2]++' will filter only unique pid number only. the pid number is on 2nd column so use $2
    4. awk '{ print $11 }' will print only 11th column. the path is on 11th column so use $11
    5. > proc.txt to save the output to proc.txt file.

    Step 4 - Show list merged paths, ports and processes

    paste -d" " proc.txt ports.txt pids.txt
    

    example output(same server as my question)

    root@lamp-s-4vcpu-8gb-sgp1-01:~# paste -d" " proc.txt ports.txt pids.txt
    /var/www/******/dist/index.js 127.0.0.1:6030 26000
    /var/www/api-****-id/dist/index.js 0.0.0.0:6031 26006
    /var/www/api.****.com/dist/index.js 127.0.0.1:6039 26013
    /var/www/***-nuxt/node_modules/.bin/nuxt 127.0.0.1:3001 29886
    

    can be simply to a line:

    ss -lntp | grep node | cut -d "=" -f 2 - | cut -d "," -f 1 - > pids.txt && ss -lntp | grep node | awk '{ print $4 }' > ports.txt && ps -eLf | grep -Fwf pids.txt   | awk '!x[$2]++' | awk '{ print $11 }' > proc.txt && paste -d" " proc.txt ports.txt pids.txt
    

    Maybe above commands can be improved, because I just learn today some commands like ss, sort, paste, cut, awk and ps

    Above method work fine if list of pids from ss command is ascending sequence. But after try on another server above commands sometime does not work properly because the pids and path position can be swapped. So I tried to find out another way using sort like below:.

    METHOD 2 using netstat with PID sorting (recommended)

    Step 1 - Get the PIDs

    netstat -lntp | grep node | sort -k 7,7 |  awk '{ print $7 }' | cut -d "/" -f 1 - > pids.txt
    

    Step 2 - Get the Ports

    netstat -lntp | grep node | sort -k 7,7 |  awk '{ print $4 }' > ports.txt
    

    Step 3 - Get the Paths from the PIDs

    ps -eLf | grep -Fwf pids.txt   | awk '!x[$2]++' |  sort -k 2,2 | awk '{ print $11 }' > proc.txt
    

    Step 4 - Show list merged paths, ports and processes

    paste -d" " proc.txt ports.txt pids.txt