1

Say I have a simple Node.js server like:

const http = require('http');

const server = http.createServer((req,res) => res.end('foobar'))

server.listen(3000, () => {
   console.log(JSON.stringify({"listening": 3000}));
});

and then with bash:

#!/usr/bin/env bash

node server.js | while read line; do
  if [[ "$line" == '{"listening":3000}' ]]; then
      :
  fi
done

# here I want to process more crap

my goal is to only continue the script after the server has started actually listening for requests. The best thing I can come up with this this:

#!/usr/bin/env bash

mkfifo foo
mkfifo bar

(node server.js &> foo) &

(
while true; do
  cat foo | while read line; do
     if [[ "$line" != '{"listening":3000}' ]]; then
       echo "$line"
       continue;
    fi
    echo "ready" > bar
  done
done
) &

cat bar && {
  # do my thing here?
}

is there a less verbose/simpler way to do this? I just want to proceed only when the server is ready and the only good way I know of doing that is to using stdout to print a message and listen for that.

2 Answers2

0

A heavyweight way to do it uses

#!/usr/bin/env expect

spawn node server.js

set timeout -1
expect {{"listening":3000}}

# now you can process all the crap, but in Expect

interact

With bash, you don't need to process the foo file in bash. How about

#!/usr/bin/env bash

node server.js &> server.out &

# busy wait
while true; do
    grep -q '{"listening":3000}' server.out && break
    sleep 1
done

# continue crap processing

You could maybe daemonize the server while you're at it:

node server.js </dev/null &> server.out &
disown $!
glenn jackman
  • 84,176
  • 15
  • 116
  • 168
0

Glenn's answer with expect seems to me like a great general solution.

If you want a simpler way, or don't want / can't install expect, here's a smaller version in bash:

#!/usr/bin/env bash

process() {
    # do your stuff
    echo ok
}

node server.js | ( grep -L '{"listening":3000}' ; process ) &

I'm leveraging grep's -L option (-l would work fine too but produce output), making it return as soon as a match is found. Control is then handed to the process function, and you can even continue reading the output if you'd like.

Add wait at the end if you don't want the script to return until the server shuts down.

Pik'
  • 166
  • 4