3

A script for terminating a server on a certain port:

#!/bin/bash

PORT="$1"
SIGNAL="$2"

if [ "${SIGNAL}" != "" ]; then SIGNAL=" -${SIGNAL}"; fi

lsof -i:"${PORT}" |\
  grep -e "localhost:${PORT}" -e TCP -e LISTEN |\
  tr -s ' ' |\
  cut -d' ' -f2 |\
  tee /dev/tty |\
  xargs --no-run-if-empty kill "$SIGNAL"

Works: killbyport 4242

But if I want to do a kill -9 I'd do: killbyport 4242 9, and that errors:

kill: (-9): No such process

The xargs and kill aren't cooperating – how do I fix it?

(PS: I want to fix this script, rather than change it to something else. It's almost working.)

5
  • Always paste your script into https://shellcheck.net, a syntax checker, or install shellcheck locally. Make using shellcheck part of your development process.
    – waltinator
    Mar 13, 2022 at 2:26
  • @waltinator Thanks. Note shellcheck gives "No issues detected!" :)
    – lonix
    Mar 13, 2022 at 2:30
  • You do not need to escape the newline after the pipe character. IMHO it is best to avoid escaping newline when possible. Mar 13, 2022 at 16:10
  • @pabouk Interesting, why do you suggest not to escape newlines?
    – lonix
    Mar 14, 2022 at 2:49
  • Backslash used for line continuation has multiple problems: * You have to be careful that the backslash is not followed by a whitespace (invisible in most editors by default) or any other character. * You cannot add a comment to such a line. --- See for example this answer for Python (almost the same situation as in a shell): stackoverflow.com/a/61933/320437 Mar 14, 2022 at 8:36

3 Answers 3

12

The problem is that you’re explicitly adding a space to SIGNAL:

SIGNAL=" -${SIGNAL}"

and then referencing it in quotes:

kill "$SIGNAL"
Since kill is seeing an argument that doesn’t begin with dash (because it begins with space, and then dash), it isn’t seen as an option, but as an ordinary argument — in this case, a PID.  A quick fix is to not add the space to SIGNAL:

SIGNAL="-${SIGNAL}"

But it doesn’t make sense that this is working when SIGNAL is null.  See But what if …?.  The first example (ignorecase) almost exactly matches your situation.

1
  • Your link led me to the answer, thanks. I added my fix below.
    – lonix
    Mar 13, 2022 at 3:06
3

@G-Man's answer led me in the right direction. For completeness, the fix is to use this instead:

xargs --no-run-if-empty kill ${SIGNAL:+"-$SIGNAL"}
2

The result of this is to run the command kill " -9" ... which is wrong. Kill will interpret " -9" as a pid instead of "-9" which would be signal 9.

You are being too clever with your quoting.

4
  • isn't it the leading whitespace that's the real problem here, rather than the quoting? Mar 13, 2022 at 2:34
  • @steeldriver: It's both.  Adding the space is an error, but, if $2 was a valid non-negative integer, kill $SIGNAL (without quotes) would have worked (but for the wrong reason). Mar 13, 2022 at 2:38
  • Without the quotes, the extra space is stripped. With the quotes, the kill works, but doesn't use the specified signal because it thinks it is a pid that it can't find.
    – user10489
    Mar 13, 2022 at 2:58
  • I've never been accused of being too clever... thanks! ;)
    – lonix
    Mar 13, 2022 at 6:05

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .