Dlaczego mój skrypt o nazwie „killl” zawodzi, ale po zmianie nazwy działa doskonale?

12

Skrypt, o którym mowa, kończy najnowszy proces na moim lokalnym porcie 8080.

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

Nie działało, jeśli skrypt miał nazwę „killl” (rozumiesz? Kill Latest?). Dało mi monit o cmdsubst> zmianę nazwy skryptu na „asdf”, wszystko działa. Czy istnieje wyjaśnienie tego zachowania? Używam MacOS El Capitán.

Zeick
źródło
5
Czy masz wywoływaną inną funkcję, alias, narzędzie lub inne polecenie killl?
Kusalananda
9
Nie róbcie dwuznacznych nazw. killlmoże zostać źle zinterpretowany jako błędnie napisany kill. Lepiej jest być wyraźnym i opisowym: kill_latestlub kill_last.
cezar
6
Jaka jest wydajność type killlpowłoki, w której próbowałeś ją uruchomić?
Hauke ​​Laging

Odpowiedzi:

27

cmdsubst>jest drugim monitem drukowanym przez zshpowłokę, gdy czeka ona na zakończenie wprowadzania komendy.

Jeśli pojawi się ten monit po wprowadzeniu killl<Return>, to jedynym rozsądnym wyjaśnieniem jest to, że masz alias (który jest formą rozwijania makra ciągów), killlktóry rozwija się do czegoś, co zawiera nieskończone $(...)podstawianie poleceń, na przykład:

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

Gdzie zshprosi o zamknięcie $(...)podstawienia polecenia.

Jeszcze kilka notatek:

  • wynik lsofjest sortowany według pid. numery pid są opakowane, większy pid nie gwarantuje, że proces został rozpoczęty później.
  • -i:8080 zgłosi gniazda TCP lub UDP, które mają port 8080 jako port źródłowy lub docelowy, niezależnie od tego, czy jest to gniazdo nasłuchujące, przyjmujące czy łączące.
  • Jeśli chcesz uzyskać tylko pid, możesz skorzystać z -topcji lsof:lsof -ti:8080 | tail -n2
  • kill -9to kill -s KILL, który wysyła sygnał, że aplikacja nie może podjąć działania, aby zakończyć działanie z wdziękiem. Powinien być stosowany tylko w ostateczności.

Aby zabić ostatnio rozpoczęty proces, który jest powiązany z gniazdem (dowolnym końcem) na porcie 8080, możesz:

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

(zakłada GNU sort(jak znaleziono w macOS) i psimplementację, która obsługuje lstartkolumnę (jak macOS i procps-ng, chociaż kod musiałby zostać zaktualizowany do procps-ng, gdzie pola miesiąca i dnia są zamieniane)).

Stéphane Chazelas
źródło
1

Dało mi to monit cmdsubst>

Ponieważ po wpisaniu polecenia nie został wpisany

killl
wpisałeś

killl $ (
lub podobne. Nie miało to nic wspólnego z nazwą skryptu, ani nawet, że był to skrypt. Ten sam efekt można osiągnąć za pomocą całkowicie nieistniejącego polecenia:

Zeick $ (
Parser powłoki oczekiwał więcej danych wejściowych, aby zakończyć jedyne częściowo zakończone polecenie. Twoje myślenie o nazwie skryptu to kompletny czerwony śledź.

JdeBP
źródło
6
To dość duże założenie, że killl $(z jakiegoś powodu pisał na maszynie i jest bardzo mało prawdopodobne, aby to zrobił. Odpowiedź Stéphane'a Chazelasa jest bardziej prawdopodobna.
Herohtar
1
Jeśli jest to rzeczywiście spowodowane literówką, `jest bardziej prawdopodobne niż $(.
Emil Jeřábek
2
Nie, Emil Jeřábek; `jest mało prawdopodobne, ponieważ nie daje tego samego monitu . Spróbuj. Nie, Herhtar; nie jest założeniem, że wpisanie tego lub podobnego jest sposobem na uzyskanie tego monitu . To jest odliczenie.
JdeBP
1
Twierdzisz, że OP „nie killlnapisał”, kiedy, jak wyjaśnia Stéphane Chazelas, jest całkiem możliwe, że OP rzeczywiście napisał killl. W związku z tym uznałem twoją odpowiedź za błędną.
Kevin