Zdefiniowałem funkcję powłoki (nazwijmy ją clock
), której chcę użyć jako opakowania innego polecenia, podobnego do time
funkcji, np clock ls -R
.
Moja funkcja powłoki wykonuje niektóre zadania, a następnie kończy się na exec "$@"
.
Chciałbym, aby ta funkcja działała nawet z wbudowanymi powłokami, np. clock time ls -R
Powinna wypisywać wynik time
wbudowanego, a nie /usr/bin/time
pliku wykonywalnego. Ale exec
zawsze kończy się uruchomienie polecenia.
Jak mogę sprawić, by moja funkcja Bash działała jako opakowanie, które przyjmuje również argumenty wbudowane powłoki?
Edycja : Właśnie dowiedziałem się, że time
nie jest to wbudowane Bash, ale specjalne słowo zastrzeżone związane z potokami. Nadal jestem zainteresowany rozwiązaniem dla wbudowanych, nawet jeśli nie działa time
, ale bardziej ogólne rozwiązanie byłoby jeszcze lepsze.
źródło
exec bash -c \' "$@" \'
. O ile polecenie w pierwszym parametrze nie jest rozpoznawane jako skrypt powłoki, to będzie interpretowane jako plik binarny do bezpośredniego uruchomienia. Alternatywnie i prościej, po prostu przegapexec
i zadzwoń"@"
z oryginalnej powłoki.Odpowiedzi:
Zdefiniowałeś funkcję bash. Więc już jesteś w powłoce bash podczas wywoływania tej funkcji. Ta funkcja mogłaby więc wyglądać następująco:
Tę funkcję można wywołać za pomocą wbudowanych poleceń bash, specjalnych słów zastrzeżonych, poleceń i innych zdefiniowanych funkcji:
Alias:
Wbudowane bash:
Inna funkcja:
Plik wykonywalny:
źródło
$@
aexec $@
, jeśli wiem, że uruchamiam właściwe polecenie?exec
polecenie zastępuje powłokę. Dlatego nie ma już wbudowanych, aliasów, specjalnych słów zastrzeżonych, zdefiniowanych słów, ponieważ plik wykonywalny jest wykonywany przez wywołanie systemoweexecve()
. To syscall oczekuje pliku wykonywalnego.exec $0
W przypadku jednego procesu, a$@
nadal dwóch.$@
ma działającą powłokę jako proces nadrzędny, a polecenie jako proces podrzędny. Ale jeśli chcesz używać wbudowanych, aliasów i tak dalej, musisz zachować powłokę. Lub rozpocznij nowy.Jedynym sposobem na uruchomienie wbudowanej powłoki lub słowa kluczowego powłoki jest uruchomienie nowej powłoki, ponieważ exec „zamienia powłokę na podane polecenie”. Powinieneś zamienić swój ostatni wiersz na:
Działa to zarówno z wbudowanymi, jak i zastrzeżonymi słowami; zasada jest taka sama.
źródło
Jeśli opakowanie musi wstawić kod przed danym poleceniem, alias działałby, ponieważ są rozwijane na bardzo wczesnym etapie:
Aliasy są prawie dosłownie wstawiane w miejsce słowa aliasu, więc końcowe
;
jest ważne - powodujeclock time foo
rozwinięcie dodo this; do that; time foo
.Możesz użyć tego do tworzenia magicznych aliasów, które nawet omijają cytowanie.
Do wstawiania kodu po poleceniu można użyć haka „DEBUG”.
Konkretnie:
Hak wciąż działa przed poleceniem, ale gdy zwraca
false
, mówi bashowi, aby anulował wykonanie (ponieważ hak już go uruchomił przez eval).Jako kolejny przykład możesz użyć tego do aliasu,
command please
abysudo command
:źródło
Jedynym rozwiązaniem, jakie do tej pory mogłem wymyślić, byłoby przeprowadzenie analizy wielkości liter w celu rozróżnienia, czy pierwszy argument jest poleceniem, wbudowanym słowem kluczowym, czy też błąd w ostatnim przypadku:
Nie radzi sobie
time
jednak z tym, więc może istnieć lepsze (i bardziej zwięzłe) rozwiązanie.źródło