How to stop npm script running in background automatically

10,078

Solution 1

I don't believe npm is the best tool to manage complex relationships between processes.

You would be far better served by creating a node script that uses node's child_process module to manage the launching and killing of co-processes, perhaps using spawn.

Having said that, and in the spirit of always trying to provide a direct, usable answer..

You could structure your npm scripts like (assumes bash shell):

scripts:{
    runBoth: "npm runA & npm runB",     // run tasks A and B in parallel
    runA:    "taskA & TASKA_PID=$!",    // run task A and capture its PID into $TASKA_PID
    runB:    "taskB && kill $TASKA_PID" // run task B and if it completes successfully, kill task A using its saved PID
}

The only 'magic' here is that:

  1. when you run a command in the background using the bash shell (which is what happens when you add & to the end), you can discover it PID using $!, but only immediately after the command is run. (See Advanced Bash-Scripting Guide: Chapter 9. Another Look at Variables - 9.1. Internal Variables for its description.)
  2. taskB must call process.exit(0) on success or process.exit(-1) on failure so that the && test is handled correctly. (See this answer for more information.)

Solution 2

The npm-run-all package may be what you're looking for:

$ npm install --save npm-run-all

Then in your package.json file:

"scripts": {
    "runA": "taskA",
    "runB": "taskB",
    "runBoth": "npm-run-all -p runA runB"
}

(-p runs them in parallel, use -s for sequential.)

Solution 3

Using the concurrently package looks like a less tricky & painful way. This avoids detached processes (&) alltogether. And promises to be more cross-plattform, too.

npm install concurrently --save

and then in package.json

"runBoth": "concurrently \"npm run taskA\" \"npm run taskB\"",

Tested (under Ubuntu 16.04, npm 5.6), also see here.

Share:
10,078
franleplant
Author by

franleplant

Updated on June 05, 2022

Comments

  • franleplant
    franleplant almost 2 years

    Im using npm scripts, I have some of them that should run in parallel. I've got something like this:

    ...
    scripts: {
       "a": "taskA &",
       "preb": "npm run a",
       "b": "taskB"
    }
    ...
    

    This is fine! But I'd like to kill automatically taskA running the background after taskB has finished.

    How can I do that? Thanks!

  • franleplant
    franleplant over 9 years
    Thank you for that Bash trick! it is awesome. Your answer is the one I was looking for.
  • nathancahill
    nathancahill about 8 years
    I don't think runB has access to $TASK_PID from runA.
  • Rob Raisch
    Rob Raisch almost 8 years
    @prongs - ok, what opsys? what version of node? Hard to help if I don't know about your setup. ;)
  • prongs
    prongs almost 8 years
    mac, and everything latest. Basically the variable isn't set, hence kill doesn't happen.
  • Grant
    Grant over 3 years
    Thanks, exactly what I was looking for. And if you add the ampersand at the end it runs even that script in the background. (eg: "npm-run-all -p runA runB &") Works great. -- Just be sure to use killall node when you're done. :D