Skip to content

Instantly share code, notes, and snippets.

@timoxley
Last active April 19, 2024 11:51
Show Gist options
  • Save timoxley/1689041 to your computer and use it in GitHub Desktop.
Save timoxley/1689041 to your computer and use it in GitHub Desktop.
check if a port is being used with nodejs
var isPortTaken = function(port, fn) {
var net = require('net')
var tester = net.createServer()
.once('error', function (err) {
if (err.code != 'EADDRINUSE') return fn(err)
fn(null, true)
})
.once('listening', function() {
tester.once('close', function() { fn(null, false) })
.close()
})
.listen(port)
}
@IgnusG
Copy link

IgnusG commented Sep 9, 2016

Ty for this!

@jonathan-casarrubias
Copy link

I actually need more this than portfinder since I need to listen when process b is not using the port x so process a can be closed.

I will test if works, tho.

Thanks

@slebetman
Copy link

Whoever wrote portfinder does not know about port 0

@prust
Copy link

prust commented Dec 15, 2016

For my purposes, I needed to know whether a process was listening on a port (indicating that it was hung & needed to be killed), not just whether the port was available. These aren't exactly the same thing, since newer versions of Node try IPv6 and then fall back to IPv4, so it returns false even though a process is listening, since a second process can still listen on the other IP version. The following code returns true if the port is taken on either IPv4 or IPv6:

function isPortTaken(port, fn) {
  var success_ix = 0;
  var net = require('net')
  var test_ipv4 = net.createServer()
  .once('error', function (err) {
    if (err.code != 'EADDRINUSE') return fn(err)
    fn(null, true)
  })
  .once('listening', function() {
    test_ipv4.once('close', function() { success_ix++; if (success_ix == 2) fn(null, false) })
    .close()
  })
  .listen(port, '0.0.0.0');

  var test_ipv6 = net.createServer()
  .once('error', function (err) {
    if (err.code != 'EADDRINUSE') return fn(err)
    fn(null, true)
  })
  .once('listening', function() {
    test_ipv6.once('close', function() { success_ix++; if (success_ix == 2) fn(null, false) })
    .close()
  })
  .listen(port, '::');
}

Note that this attempts binding to all interfaces (*), if you want to check specifically against localhost, use ::1 instead of :: and use 127.0.0.1 instead of 0.0.0.0. Also note that the callback will be called twice if the port is taken on both IPv4 and IPv6.

@lyret
Copy link

lyret commented Mar 14, 2017

This is a version of the original using a promise :)

const isPortTaken = (port) => new Promise<boolean>((resolve, reject) => {
    const tester = Net.createServer()
         .once('error', err => (err.code == 'EADDRINUSE' ? resolve(false) : reject(err)))
         .once('listening', () => tester.once('close', () => resolve(true)).close())
         .listen(port)
})

@bkdotcom
Copy link

bkdotcom commented Mar 31, 2017

@lyret

you've implemented isPortAvailable or isPortNotTaken()
in my opinion, "isPortTaken" should not return false when the port is available

@cevhyruz
Copy link

i think its best to make it as a node global module to be able to call it in any project directories... anyways nice style ;0

@colxi
Copy link

colxi commented Sep 8, 2017

I published a simple npm package, inspired by this code: is Port Available

@tluanga34
Copy link

This is simple and easy to use. No need of installing extra package. I just can copy & paste it in my code and it just works. Thank you so much for making it simple.

@Akumzy
Copy link

Akumzy commented Jan 4, 2019

This is a version of the original using a promise :)

const isPortTaken = (port) => new Promise<boolean>((resolve, reject) => {
    const tester = Net.createServer()

//resolve true not false

     .once('error', err => (err.code == 'EADDRINUSE' ? resolve(true) : reject(err)))

// resolve false not true

     .once('listening', () => tester.once('close', () => resolve(false)).close())
     .listen(port)

})

@tbhaxor
Copy link

tbhaxor commented Feb 5, 2019

I like to use this instead! :-)

https://github.com/indexzero/node-portfinder

Thnx man 😉

@perokhel
Copy link

perokhel commented Feb 9, 2021

I like to use this instead! :-)

https://github.com/indexzero/node-portfinder

Thanks. This is a very simple and easy to use package.

@sadofriod
Copy link

a promise implement

import { createServer } from "net";

const isPortTaken = (port: number, type: 'IPv4' | 'IPv6' = 'IPv4') => {
  let hasError = 0;
  return new Promise((res) => {
    const server = createServer()
      .once('error', err => { if (err) { res(false) } })
      .once('listening', () => {
        server
          .once('close', () => {
            hasError++;
            if (hasError > 1) {
              res(false)
            } else {
              res(true)
            }
          })
          .close()
      })
      .listen(port, type === 'IPv4' ? '0.0.0.0' : '::')
  })

};

@tysonrm
Copy link

tysonrm commented Feb 20, 2024

Test without producing an error
on mac and most unix/linux

const { spawnSync } = require('child_process')

function checkPort(port) {
  const output = spawnSync(
    `lsof -i tcp:${port} | awk '{print $2}' |grep --invert PID`,
    { shell: true }
  )
  if (output.error) {
    console.error(output.error)
    return
  }
  const pid = Buffer.from(output.stdout.buffer).toString().split('\n')[0]
  console.log({ pid })
  return pid
}

const pid = checkPort(443)) 
if (pid) {
  console.log(`server is running, process id  ${pid}`)
}

@ffd8
Copy link

ffd8 commented Feb 22, 2024

const pid = checkPort(443)) 

@tysonrm – nice technique! FYI, there's an extra ) when making the checkPort() example.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment