How to stop npm script running in background automatically
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:
- 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.) - 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.
franleplant
Updated on June 05, 2022Comments
-
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 over 9 yearsThank you for that Bash trick! it is awesome. Your answer is the one I was looking for.
-
nathancahill about 8 yearsI don't think runB has access to $TASK_PID from runA.
-
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 almost 8 yearsmac, and everything latest. Basically the variable isn't set, hence kill doesn't happen.
-
Grant over 3 yearsThanks, 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 usekillall node
when you're done. :D