12

The script in question terminates the latest process on my localhost port 8080.

#!/bin/bash
x=$(lsof -i:8080 | tail -1 | awk '{print $2}')
kill -9 $x

It didn't work, if the script was named 'killl' (get it? Kill Latest?). It gave me a prompt for cmdsubst> Renaming the script to 'asdf', everything works. Is there an explanation for this behaviour? I'm using MacOS El Capitán.

3
  • 5
    Do you have another function, alias, utility or other command called killl?
    – Kusalananda
    Commented Oct 31, 2017 at 9:34
  • 9
    Don't make the names ambiguous. killl can be misinterpreted as wrongly spelled kill. It's better to be explicit and more descriptive: kill_latest or kill_last.
    – cezar
    Commented Oct 31, 2017 at 9:43
  • 6
    What is the output of type killl in the shell where you tried to start it? Commented Oct 31, 2017 at 10:23

2 Answers 2

28

cmdsubst> is the secondary prompt printed by the zsh shell when it's waiting for the end of a command substitution being entered.

If you get that prompt after just entering killl<Return>, then the only reasonable explanation is that you have an alias (which is some form of string macro expansion) for killl that expands to something that contains an unterminated $(...) command substitution, like:

$ alias 'killl=echo $(lsof -ti'
$ killl :22
cmdsubst>

Where zsh is asking you to close that $(...) command substitution.

A few more notes:

  • the output of lsof is sorted by pid. pid numbers are wrapped, a larger pid is not a guarantee that the process was started later.
  • -i:8080 will report TCP or UDP sockets that have the 8080 port as the source or destination port, whether it's a listening, accepting or connecting socket.
  • If you want to get the pid only, you can use the -t option of lsof: lsof -ti:8080 | tail -n2
  • kill -9 is kill -s KILL, which sends a signal that the application cannot act upon to exit gracefully. It should only be used as a last resort.

To kill the most recently started process that has a socket bound (either end) on port 8080, you could do:

#! /bin/sh -
unset IFS
pids=$(lsof -ti:8080) &&
  LC_ALL=C ps -o pid=,lstart= -p $pids |
  LC_ALL=C sort -k6,6n -k4,4M -k3,3n -k5,5 -k1,1n |
  awk 'END{system("kill " $1)}'

(assumes GNU sort (as found on macOS) and a ps implementation that supports the lstart column (like macOS' and procps-ng's, though the code would have to be updated for procps-ng where the month and day fields are swapped)).

1

It gave me a prompt for cmdsubst>

Because when you typed the command you did not type

killl
you typed

killl $(
or similar. This was nothing to do with the name of the script, or even that it was a script in the first place. You could have achieved the same effect with a wholly nonexistent command:

Zeick $(
The shell's parser was expecting more input to complete the only partly complete command. Your thinking about the script name is a complete red herring.

4
  • 6
    That's a pretty big assumption to say he typed killl $( for some reason, and very unlikely that he did so. Stéphane Chazelas' answer is more likely the case.
    – Herohtar
    Commented Oct 31, 2017 at 14:59
  • 1
    If it is indeed due to a typo, then ` is more likely than $(. Commented Oct 31, 2017 at 15:50
  • 2
    No, Emil Jeřábek; ` is not likely at all since it does not give the same prompt. Try it. No, Herhtar; it's not an assumption when typing that or similar is the way to get that prompt. It is a deduction.
    – JdeBP
    Commented Oct 31, 2017 at 16:20
  • 1
    You assert that OP "did not type killl," when as Stéphane Chazelas explains, it is entirely possible that OP did indeed type killl. Therefore, I have downvoted your answer as wrong.
    – Kevin
    Commented Nov 1, 2017 at 5:09

You must log in to answer this question.

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