Coder Social home page Coder Social logo

terminate's Introduction

terminate

A minimalist yet reliable way to Terminate a Node.js Process (and all Child Processes) by Process ID.

terminate-the-node-process-final

GitHub Workflow Status codecov.io npm version Node.js Version JavaScript Style Guide: Good Parts HitCount contributions welcome

Usage

Install from NPM

npm install terminate --save

In your script

const terminate = require('terminate');

terminate(process.pid, function (err) {
  if (err) { // you will get an error if you did not supply a valid process.pid
    console.log('Oopsy:', err); // handle errors in your preferred way.
  }
  else {
    console.log('done'); // terminating the Processes succeeded.
    // NOTE: The above won't be run in this example as the process itself will be killed before.
  }
});

Usage

All the available parameters and their descriptions are viewable in the TypeScript definition file: index.d.ts.

// Function signature
terminate(pid: number, signal?: string, opts?: TerminateOptions, callback?: DoneCallback): void

// Function signature of the Promise version
terminate(pid: number, signal?: string, opts?: TerminateOptions): Promise<void>
  • pid - The Process ID you want to terminate.
  • signal - The signal to kill the processes with. Defaults to "SIGKILL" if it's empty or not defined.
  • opts.pollInterval - Interval to poll whether pid and all of the childs pids have been killed. Defaults to 500 (0.5s).
  • opts.timeout - Max time (in milliseconds) to wait for process to exit before timing out and calling back with an error. Defaults to 5000 (5s).
  • callback - The callback function to call when the termination is done. It has this signature: (error: Error | null): void whereas error will be null if the operation succeeds.

Promise API

If you are using Node.js 8+, you can load the Promise version importing the module terminate/promise.js like this:

const terminate = require('terminate/promise');

(async () => {
  try {
    await terminate(process.pid);
    console.log('done');
  } catch (err) {
    console.log('Oopsy:', err);
  }
})();

tl;dr

Why?

In our Faster project we run the server using Child Process(es). When we want to re-start the server,
we needed to ensure the process (and any Child Processes) were Terminated before attempting to re-start.

Prevents Zombie Processes

Imagine you are running your Node.js app on a Multi-Core Processor and don't want to "waste" the CPU by only using one of those cores
(remember: one of Node's selling points is that its single-process running on a single-core), you can "farm out" tasks to the other cores using Child Process(es)

If you then want to restart your app you naively (we did this!) terminate the "main" process and expect all the "child" processes to be ended too.

Sadly this results in Zombie Processes which you would have to either manually kill or restart the machine/VM to clear.
Instead you need to find all the Process IDs for the child processes that your app created and terminate those before you can re-start your app.

Using terminate you no longer have this problem.


Dependencies Retire Status

While researching how to get a list of child processes given a Process ID we found ps-tree: https://github.com/indexzero/ps-tree
it was un-maintained and had no tests so we submitted an issue offering to update the module with tests.
Charlie replied welcoming an update so we submitted a Pull Request with 100% test coverage which was Merged by Charlie
ps-tree in turn uses event-stream (by Dominc Tarr) for streaming the result of its process lookups.
event-stream does not publish its' code coverage, but is tested (and more importantly used by millions of people)
has had many itterations and has been stable for a while:

NPM

While we don't like the fact that event-stream has dependencies which have limited automated tests,
we are willing to place reliance on the module given how "real-world tested" it is.

If at any point we find that relying event-stream or its underlying dependencies is the source of a bug or sleepless nights,
we can either make time to contribute the tests or write our own version of ps-tree without dependencies
(which should "only" take a day but won't be as elegant...)

Research

Background Reading

Useful StackOverflow Questions/Answers

Other potential modules we could have used:

Name

Terminate seemed like the best (of the available) name,
if you have a better suggestion, please share!



This Project Reminded me of Two xkcd Comics:

xkcd terminate

xkcd time robot

terminate's People

Contributors

adrianblynch avatar arhell avatar asakusuma avatar asntc avatar benjaminlees avatar cono52 avatar dependabot[bot] avatar iteles avatar jarofghosts avatar jedwards1211 avatar jpunt avatar micalevisk avatar mitchellporter avatar morigs avatar nelsonic avatar simonlab avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

terminate's Issues

Windows 7 killing not working

I wrote code to terminate a node process on windows 7 but it says it cannot find 'ps' and then does not work. Is there a work around it?
regards

Refactor the Code in terminate function to use (JavaScript The) "Good Parts"

at present the code in this module works as expected.
but... it does not follow our "style guide": https://github.com/dwyl/goodparts
ideally, all our projects should follow this guide to ensure we have consistency across all our JS.

If anyone has the time/patience to re-factor the code in /terminate.js to conform to goodparts please comment on this issue to show your interest.

Note: "Refactoring" is when you don't change any existing tests. only update the terminate.js file to use a different code style.

Note2: If you haven't already done so, please read and โญ the "Contributing Guide": https://github.com/dwyl/contributing to ensure that our "steps" are followed and someone can read your Pull Request without any delays. ๐Ÿ‘

The task(s) are:

  • clone the repo to your local machine
  • create a new branch called goodparts-refactor
  • npm install goodparts --savedev
  • add the following line to the scripts section of package.json
"lint": "node_modules/.bin/goodparts terminate.js"
  • run the linter npm run lint
  • update this issue with a screenshot of the error messages you see in your console/terminal, so that we know how many there were ...
  • now attempt to run the "fix" with the following command:
node_modules/.bin/goodparts terminate.js --fix

That should "fix" a few of the "basic" code style issues, but it will not address any "major" ones.

  • confirm the "fix" worked as expected by re-running the tests: npm test
  • Now the "fun" part: re-thinking the code to follow an alternative (more beginner-friendly) code style...! This will involve quite a few changes dependent on how many things the goodparts (ESLint) is reporting...
    • each time you make a change re-run the tests and lint. My preferred way of doing this is to re-run my test & lint commands in two separate terminal windows/tabs using nodemon each time the file is updated.
  • Once all the warnings raised by goodparts have been resolved and the code conforms to the styleguide, commit your changes referencing this issue in your commit message.
  • finally, if that all worked, add the "Repo Badge" to the README.md JavaScript Style Guide: Good Parts to signal to everyone that this repo conforms to our code style guide.
  • once the badge is added to the readme make a commit to that effect: git commit -m 'adds goodparts repo badge see: https://github.com/dwyl/repo-badges#goodparts-javascript-code-style-'
  • push up your branch and create a pull request referencing this issue.

Remove `console.log`s or expose option to squelch them

This module is great and works perfectly, but it would be nice to have a way to not output to stdout on kill. This has tripped me up while using it to make a command line tool that can be piped into other sources as it disrupts the output. I think that things are usually best to be silent unless something unexpected happens or they are asked to be verbose.

I would be happy to PR the change, but wanted to get your opinion on it as a possibility.

processes don't seem to be killed immediately on windows

I increased the test timeouts once to fix my appveyor build but I'm still seeing it fail sometimes.

Maybe it would be best to make terminate wait until the processes have exited, for instance by polling every second? We can use process.kill(pid, 0) to test if the child processes are running, even if the parent is not.

Replace `chalk` with `cli-color`

As noted in #73 chalk has made a Unnecessary Breaking Change!

"require() of ES modules is not supported"

So I propose replacing:

var chalk = require('chalk');
var red = chalk.red, green = chalk.green, cyan = chalk.cyan;

with:

var clc = require("cli-color");
var red = clc.redBright, green = clc.greenBright, cyan = clc.cyanBright;

This will avoid future @dependabot PRs failing.

ERROR kill ESRCH

Terminate has worked pretty well so far in testing, but I did see this error today and had to kill the process manually :(

Any idea what may have caused this? I am testing locally on a macbook with node v14.16.1

 ERROR  kill ESRCH                                                                                                                                                23:14:48

  at process.kill (internal/process/per_thread.js:200:13)
  at handlePsTreeCallback (node_modules/terminate/handlePsTreeCallback.js:28:13)
  at node_modules/terminate/terminate.js:44:5
  at node_modules/ps-tree/index.js:87:7
  at Stream.a.end (node_modules/event-stream/index.js:87:5)
  at Stream.onend (internal/streams/legacy.js:46:10)
  at Stream.emit (events.js:327:22)
  at Stream.EventEmitter.emit (domain.js:467:12)
  at end (node_modules/map-stream/index.js:116:39)
  at Stream.stream.end (node_modules/map-stream/index.js:122:5)

Doesn't actually call back when completed

The callback is called immediately after the spawn, which is asynchronous. It should instead be attached to the 'exit' event of the spawn command so that you don't call it before the processes are actually killed.

Terminate hanging in docker container?

So I'm not sure if this is a docker issue or a terminate issue.

Here is my code block:

  terminate(server.pid, (err) => {
    if (err) {
      console.log(err);
    }

    console.log(`[REBUILDING]: Change detected at ${path}`);

    server = spawn('npm', ['start']);

    server.stdout.on('data', function(data) {
        console.log(data.toString());
    });

    server.stderr.on('data', d => console.log(d.toString()))
  });

Basically, the first time I call this block it hangs (never gets to spawning the new process). The 2nd time, it actually builds (from the first time) but then errors out because the PID is being terminated twice.

Nothing special as far as the stack goes. Using child processes to run babel builds, chokidar to watch for changes & rebuild/restart the server as needed. This is running inside of a docker container which is where the weirdness might be.

I expect the server to restart after each time I save a file, it restarts every other file save. Chokidar is logging each time I save, so this must be an issue with terminate's compatibility with docker/docker compose.

Promise interface

Thanks for writing this module.

A promise interface would make it more useful.

Possible switch to a permissive license?

I really like "terminate" as it does solve some child-process killing issues that I have faced in a project that I soon intent do pursue commercially. Now that I have executed a license check against all my project's dependencies, it appears that terminate is the only dependency that uses a non-permissive licensing model. In reality this means that I'll either have to implement "something like terminate" myself or be prepared to hand over the source code of my whole project if anyone asks for it (not really a viable option :-)).

Therefore I'd like to ask if you'd consider releasing this library also under a different (permissive) licensing model, such as MIT?
Thanks for your consideration and your efforts in making terminate ๐Ÿ‘

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.