5

I have a makefile like this, that kills a process if it's already running,

test: client server
    pgrep myserver && killall myserver
    /build/bin/myserver --background
    /build/bin/myclient --server 127.0.0.1

It works if I have a myserver started previously. When it's not, pgrep myserver just fails with non zero status, and Makefile take it as an error, e.g

pgrep myserver && killall myserver
make: *** [test] Error 1

Any suggestions?

16

Don't combine killall with pgrep. They don't use the same matching rules, so what pgrep shows may not be what killall kills. Use pkill, which is exactly the same as pgrep except that it kills the matching processes instead of displaying their PIDs. Beware that if you call both pgrep and pkill, there's a race condition: by the time pkill runs, some processes shown by pgrep may have terminated and some new processes may have started. Unless you care about the process IDs, there's no point in calling pgrep; you can just call pkill directly.

pkill returns the status 1 if it doesn't find any process to kill. Either add - at the beginning of the command, to tell make to ignore this error, or change the command to pkill myserver || true which does exactly the same thing as pkill myserver but always returns a success status.

test: client server
    pkill myserver || true
    /build/bin/myserver --background
    /build/bin/myclient --server 127.0.0.1
6

You need a ||true to ensure the first command always returns success.

You can avoid the need for pgrep by throwing away stderr; e.g.

test: client server
  killall myserver 2>/dev/null || true
  myserver --background
  myclient --server 127.0.0.1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.