0

Suppose I have something like

.PHONY: kill-server
kill-server:
   kill -9 $(lsof -t -i :9000)

Why it doesn't work and how do I fix this?

Adil Akhmetov
  • 121
  • 1
  • 1
  • 7
  • You did not specify, which _make_ you are using, but in all those which I know, `$(FOO)` expands the varialbe `FOO` inside make. See for instance [here](https://www.gnu.org/software/make/manual/html_node/Reference.html#Reference). – user1934428 May 18 '21 at 10:24
  • @user1934428 but for calling functions I do use `$()` as well, don't I? https://www.gnu.org/software/make/manual/html_node/Syntax-of-Functions.html#Syntax-of-Functions – Adil Akhmetov May 18 '21 at 10:31
  • For make functions, but _lsof_ is not a make function. Does [this](https://stackoverflow.com/questions/10024279/how-to-use-shell-commands-in-makefile) help? – user1934428 May 18 '21 at 10:33
  • `$(lsof -t -i :9000)` will be expanded by `make` when it reads the makefile. To defer execution until the point at which the `kill-server` is run use `$$(lsof -t -i :9000)` instead. – G.M. May 18 '21 at 10:37
  • @user1934428 anyway it just doesn't see something like `PID:="$(lsof -t -i:9000)"; echo $(PID)` as been suggested there – Adil Akhmetov May 18 '21 at 10:45
  • @G.M.: I'm not very proficient in _make_ (that's why I wrote a comment instead of an answer), but would perhaps something like `$(shell kill -9 $(lsof ...))` do the job? – user1934428 May 18 '21 at 10:48
  • @AdilAkhmetov : For a practical solution, wouldn't it make sense to put the whole shell code into a shell script, and invoke the script from your Makefile? Doing this avoids mixing make and shell syntax and is likely easier to debug too. – user1934428 May 18 '21 at 10:50
  • @G.M. thanks, now it seems to work. But how do I use it in if statements like `ifneq ($$(lsof -t -i :9000),)`? – Adil Akhmetov May 18 '21 at 10:51
  • @user1934428 yeah, you're right, but this is only two jobs (run and kill) which I don't want to separate into several files – Adil Akhmetov May 18 '21 at 10:52
  • Why not? They are different in a fundamental way: A Makefile (which is goal directed), and shell script (simply procedural). They are based on different syntax rules. Is there a logical reason,why they must reside in the same physical file? – user1934428 May 18 '21 at 11:54
  • 1
    FYI it is not the case that `$(lsof ...)` will be expanded by make "when it reads the makefile". This is part of a recipe, and a recipe will be expanded by make when make wants to run it, just before the shell is invoked to build the target. If the target is never built, the recipe will never be expanded. – MadScientist May 18 '21 at 13:20
  • @MadScientist Yes, sorry. My comment was badly worded -- should've been more careful. – G.M. May 18 '21 at 13:32

2 Answers2

1

You could pipe lsof to xargs in your makefile:

# Makefile - Version 1

# Send kill to server
kill-server:
    lsof -t -i :9000| xargs kill -9
Zlemini
  • 4,827
  • 2
  • 21
  • 23
0

Good grief. So much confusion.

It's very simple: $ is special to make. It introduces a make variable. If you write a recipe (which is a shell script) and you want the shell to see the $ you have to escape it so that make won't expand it as a make variable. That's completely trivial to do, you just write $$ anywhere you want to pass $ to the shell:

.PHONY: kill-server
kill-server:
        kill -9 $$(lsof -t -i :9000)

That's it. Done.

MadScientist
  • 92,819
  • 9
  • 109
  • 136