Por que meu script chamado "killl" falha, mas depois de renomear funciona perfeitamente?

12

O script em questão finaliza o processo mais recente na minha porta 8080 do host local.

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

Não funcionou, se o script tivesse o nome 'killl' (entendeu? Kill Latest?). Ele me deu uma solicitação para cmdsubst> renomear o script para 'asdf', tudo funciona. Existe uma explicação para esse comportamento? Estou usando o MacOS El Capitán.

Zeick
fonte
5
Você tem outra função, alias, utilitário ou outro comando chamado killl?
Kusalananda
9
Não torne os nomes ambíguos. killlpode ser mal interpretado como escrito incorretamente kill. É melhor ser explícito e mais descritivo: kill_latestou kill_last.
Cezar
6
Qual é a saída do type killlshell em que você tentou iniciá-lo?
Hauke ​​Laging

Respostas:

27

cmdsubst>é o prompt secundário impresso pelo zshshell enquanto aguarda o final de uma substituição de comando ser inserida.

Se você receber esse prompt depois de entrar killl<Return>, a única explicação razoável é que você tem um alias (que é uma forma de expansão de macro de cadeia) killlque se expande para algo que contém uma $(...)substituição de comando não terminada , como:

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

Onde zshestá pedindo para você fechar essa $(...)substituição de comando.

Mais algumas notas:

  • a saída de lsofé classificada por pid. números de pid são agrupados, um pid maior não garante que o processo foi iniciado mais tarde.
  • -i:8080 relatará os soquetes TCP ou UDP que têm a porta 8080 como a porta de origem ou de destino, seja um soquete de escuta, aceitação ou conexão.
  • Se você deseja obter apenas o pid, pode usar a -topção de lsof:lsof -ti:8080 | tail -n2
  • kill -9é kill -s KILL, que envia um sinal que o aplicativo não pode agir para sair normalmente. Só deve ser usado como último recurso.

Para eliminar o processo iniciado mais recentemente, com um soquete vinculado (uma ou outra extremidade) na porta 8080, você pode:

#! /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)}'

(assume o GNU sort(como encontrado no macOS) e uma psimplementação que suporta a lstartcoluna (como o macOS e o procps-ng, embora o código precise ser atualizado para o processo onde os campos mês e dia são trocados)).

Stéphane Chazelas
fonte
1

Isso me deu um aviso para cmdsubst>

Porque quando você digitou o comando, você não digitou

killl
você digitou

killl $ (
ou similar. Isso não tinha nada a ver com o nome do script, ou mesmo que era um script em primeiro lugar. Você poderia ter conseguido o mesmo efeito com um comando totalmente inexistente:

Zeick $ (
O analisador do shell esperava mais entradas para concluir o único comando parcialmente completo. Seu pensamento sobre o nome do script é um arenque vermelho completo.

JdeBP
fonte
6
Essa é uma suposição bastante grande de dizer que ele digitou killl $(por algum motivo e é muito improvável que ele tenha feito isso. A resposta de Stéphane Chazelas é mais provável.
Herohtar 31/10
1
Se é realmente devido a um erro de digitação, `é mais provável que $(.
Emil Jeřábek apoia Monica
2
Não, Emil Jeřábek; `não é provável, pois não fornece o mesmo prompt . Tente. Não, Herhtar; não é uma suposição ao digitar isso ou semelhante, é o caminho para obter esse prompt . É uma dedução.
JdeBP #
1
Você afirma que o OP "não killldigitou" quando, como explica Stéphane Chazelas, é inteiramente possível que o OP realmente digitou killl. Portanto, votei sua resposta como incorreta.
Kevin