Użyj polecenia systemowego zamiast wbudowanego Bash bez określania pełnej ścieżki


17

Używam Bash jako interaktywnej powłoki i zastanawiałem się, czy istnieje prosty sposób, aby Bash uruchomił polecenie systemowe zamiast wbudowanego polecenia powłoki w przypadku, gdy oba mają tę samą nazwę.

Na przykład użyj system kill(od util-linux), aby wydrukować identyfikator procesu (pid) nazwanego procesu (procesów) zamiast wysyłać sygnał:

$ /bin/kill -p httpd
2617
...

Bez określenia pełnej ścieżki polecenia systemowego zamiast polecenia systemowego jest używane wbudowane Bash. killWbudowane nie ma -popcji więc polecenie kończy się niepowodzeniem:

$ kill -p httpd
bash: kill: p: invalid signal specification

Próbowałem odpowiedzi wymienionych w Make bash, używając zewnętrznego polecenia `time` zamiast wbudowanej powłoki, ale większość z nich działa tylko dlatego, że w timerzeczywistości jest słowem kluczowym powłoki, a nie wbudowaną powłoką .

Poza tymczasowym wyłączeniem wbudowanego Bash enable -n kill, najlepszym rozwiązaniem, jakie do tej pory widziałem, jest użycie:

$(which kill) -p httpd

Czy istnieją inne łatwiejsze (wymagające mniej pisania) sposoby wykonywania poleceń zewnętrznych zamiast wbudowanej powłoki?

Zauważ, że killto tylko przykład i chciałbym uogólnionego rozwiązania podobnego do sposobu, w jaki prefiks commandwbudowanego zapobiega uruchamianiu funkcji o takiej samej nazwie jak polecenie zewnętrzne. W większości przypadków zazwyczaj wolę używać wbudowanej wersji, ponieważ oszczędza to rozwidlania nowego procesu, a czasami wbudowane funkcje nie są dostępne w poleceniu zewnętrznym.


Zamknięcie which killw backticks (nie można ich umieścić w komentarzach) jest nieco krótsze.
abligh,

@abligh Dobry punkt. Spędziłem lata trenując się do używania „nowej” składni er do zastępowania poleceń. :)
Anthony G - Sprawiedliwość dla Moniki

@abligh: FYI, możesz wstawić `backticks` w komentarzach, poprzedzając je ukośnikami odwrotnymi (\). Ale są powody, by się z tym trzymać $(…)- patrz to , to i to .
G-Man mówi „Przywróć Monikę”

Odpowiedzi:


20

Zakładając, że envmasz na swojej drodze:

env kill -p http

envuruchamia plik wykonywalny nazwany pierwszym argumentem w (ewentualnie) zmodyfikowanym środowisku; jako taki nie wie o wbudowanych poleceniach powłoki ani nie działa z nimi.

Powoduje to pewne cruft kontroli zadań powłoki, ale nie opiera się na zewnętrznej komendzie:

exec kill -p bash &

execwymaga pliku wykonywalnego do zastąpienia bieżącej powłoki, więc nie używa żadnych wbudowanych funkcji. Zadanie jest uruchamiane w tle, aby zastąpić rozwidloną powłokę tła, a nie bieżącą powłokę.


2
envjest wyraźnie właściwą odpowiedzią IMHO.
abligh,

@abligh: Masz rację w komentarzu do mojej skasowanej odpowiedzi. command -p cmdwywoływanie zewnętrznego polecenia zsh, a nie bash.
cuonglm,

6
(exec kill -p http)powoduje, że zadanie zastępuje podpowłokę zamiast bieżącej powłoki i nie musisz radzić sobie z cruft kontroli zadań.
Michael Hoffman,

1
@AnthonyGeoghegan Rzeczywiście, ale envtakże nie wie o wbudowanych powłokach, ponieważ nie jest to powłoka. Można by uzyskać ten sam efekt z nicelub xargsdowolny inny program takiego.
user253751,

1

Najprostszym sposobem na zrobienie tego, co chcesz, jest umieszczenie linii

alias kill="/bin/kill"

do twojego ~/.bashrcpliku. Następnie każde nowe logowanie / wywołanie bash zinterpretuje „zabij” jako /bin/kill.


Myślałem już o aliasie i było to jedno z rozwiązań wymienionych w pytaniu, z którym się połączyłem, ale mam nadzieję na bardziej ogólne rozwiązanie (podobne do commandrozwiązania), zamiast tworzyć osobny alias dla każdego polecenia „zacieniowanego”. Zredagowałem teraz moje pytanie, aby było jaśniejsze i bardziej jednoznaczne. W większości przypadków zwykle wolę używać wbudowanej wersji, ponieważ procesy mogą być określone za pomocą identyfikatorów zadań. W każdym razie dzięki.
Anthony G - sprawiedliwość dla Moniki

1

Jeśli znasz rozwiązanie, które wymaga trochę pisania i potrzebujesz rozwiązania, które wymaga mniej pisania, skompiluj je:

runFile() { local cmd="$1"; shift; cmd="$(which "$cmd")" && "$cmd" "$@"; }

Skrót rzeczy, które zwykle wymagają pewnego wysiłku, jest tym, co wyróżniają komputery.


1
To dobra ogólna uwaga, więc będę głosować za odpowiedzią. W ciągu ostatnich kilku lat stworzyłem kolekcję aliasów, funkcji i skryptów dla systemów, z których regularnie korzystam. Jednak wolę korzystać z niestandardowych rozwiązań tam, gdzie to możliwe, ponieważ czasami muszę pracować nad nowymi instalacjami lub serwerami, których nie skonfigurowałem. Dzięki.
Anthony G - sprawiedliwość dla Moniki

1

W tym bardzo szczególnym przypadku polecenie pgrepdokładnie odpowiada potrzebom.

W ogólnym sensie funkcja działa. Z „polecenia pliku”:

fcmd(){ local a=$1; shift; $(which "$a") "$@"; }

zadzwoń jako

fcmd kill -p httpd

Ale jeśli potrzebujesz mniej pisania, nie ma krótszej drogi niż dobry alias.

Z pojęcia „list pid” (lp):

alias lp='/bin/kill -p'

następnie wpisz:

lp httpd

0

(W zsh) Możesz poprzedzić dowolną nazwę polecenia znakiem =, aby uzyskać wersję systemową zamiast wbudowanej. Jest to również przydatny sposób na uniknięcie aliasów, które psują określony scenariusz.

$ =kill -p httpd

1
Próbowałem tego z wersją Bash 4.3.30 i to nie działało. Nigdy wcześniej nie widziałem takiej składni; czy możesz dodać link do miejsca, w którym ta funkcja jest udokumentowana? Normalnie prefiksowałbym alias odwrotnym ukośnikiem, aby uruchomić nie-aliasowaną wersję polecenia.
Anthony G - sprawiedliwość dla Moniki

@Anthony może to zshjedyna rzecz. Używam go regularnie, ale sprawdzę bashjutro z komputera.
Caleb,

Podejrzewałem, że może to być jakaś powłoka, której nie znam (znam tylko bash, myślnik i csh). Była inna odpowiedź (ponieważ usunięta), która tylko działała zsh. Chociaż otagowałem to pytanie bashi użyłem go w tytule, powinieneś zachować tę odpowiedź, ponieważ użytkownik zsh nadal uznałby ją za przydatną.
Anthony G - sprawiedliwość dla Moniki

-1

Możesz wysłać raport o błędzie na stronie killpodręcznika i zapytać, dlaczego obejmuje to niestandardowe opcje, które są pobierane pkilli używane, pkillgdy chcesz uzyskać dostęp do funkcjipkill.

Jeśli zadzwonisz:

pkill httpd

unikasz opisywanych problemów.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.