DEV Community

spongechameleon
spongechameleon

Posted on

A short story on npm scripts & killing processes (how to make your tools work for you!)

The background

I have a project. It has static files. They are:

  • A HTML file

  • A Sass file (.scss)

  • A Typescript file (.ts)

To get my sass to compile into regular .css, I use the node-sass npm package.

To get my typescript to compile into regular .js, I use the tsc compiler.

To get my browser to automatically update whenever one of these files is changed, I use the browser-sync npm package.

How I start up:

  • Open a terminal. Go to project directory. Start vim.

  • Open another terminal. Go to project directory. Run tsc & node-sass & browser-sync &

    • (Full disclosure: node-sass and browser-sync are run with options, but that's not important)
  • Go back to vim and edit.

How I close down:

  • Close vim (but how?!). Close terminal.

  • Go to the other terminal. Find and kill my processes, one-by-one:

    • ps aux | grep node-sass
    • Mentally take note of the displayed PID (process ID) from the second column
    • kill <PID I definitely always remember perfectly>
    • Repeat for tsc and browser-sync

This is clearly a lot of typing and PID-remembering. Nobody likes that. We can do better.


The npm script

My start up command is too much typing. So we’re going to have package.json do the heavy lifting.

“scripts”: {
  “ts”: “tsc”,
  “sass”: “node-sass”,
  “browser”: “browser-sync”,
  “serve”: “npm run ts & npm run sass & npm run browser &”
}
Enter fullscreen mode Exit fullscreen mode

Now, all we have to run is npm run serve and everything is taken care of for us.

OK, but why go through all the trouble of making scripts for each single command? Why not just do:

“scripts”: {
  “serve”: “tsc & node-sass & browser-sync &”
}
Enter fullscreen mode Exit fullscreen mode

The answer to that is all about our friend, &, the ampersand. Anything with an & will run continuously and show up in the output of ps aux. And we intentionally want all of our processes- whatever they really are- to show up as npm processes!

Hence:

  • The “serve” script that only runs npm commands

  • The absence of an & in the “ts/sass/browser” scripts


The kill

So here’s why we want all of those tools to show up as npm commands:

ps aux | grep [n]pm | awk ‘{ print $2 }’

This command:

  • Outputs all processes

  • Filters by [n]pm (only considers processes with the first letter of “n”)

  • Grabs the second column/word of output, which in this case is the PID

Now all that’s left is to kill all of those PIDs we collected:

kill $(ps aux | grep [n]pm | awk ‘{ print $2 }’)

Booyah. But… hate typing that? Me too. So, we can either just alias this in our .bashrc as ‘npmkill’ or something…


The generalized, easy to type kill

…or take an extra minute to whip together a quick bash script that:

  • Accepts a grep search term

  • Lets us see our processes before we kill them

#!/usr/bin/bash
ps aux | grep $1

read -p ‘kill processes? (y/n): ‘ confirm

if [ $confirm == ‘y’ ]
then
  kill $(ps aux | grep $1 | awk ‘{ print $2 }’)
fi
Enter fullscreen mode Exit fullscreen mode

The $1 refers to the first argument passed to the script, so if we call our script pidkill.sh then running pidkill [n]pm would mean $1 == [n]pm.

The read -p ‘<prompt>: ‘ confirm allows us to (a) enter our response on the same line and (b) saves our response to the $confirm variable.

Then it’s a simple if statement and our shell expansion!

Don’t forget to alias your script in .bashrc if you want to be able to use it anywhere, otherwise you’ll have to be in the directory of the script or type out its path every time.

alias pidkill=’~/pidkill.sh’ does the trick for me.

Thanks for reading and happy coding!

sponge

Top comments (0)