Zadanie tego pytania zajęło mi prawie 10 lat użytkowania Linuksa. To wszystko było próbą i błędem oraz losowym surfowaniem po Internecie w późnych godzinach nocnych.
Ale ludzie nie powinni potrzebować na to 10 lat. Gdybym dopiero zaczynał od Linuksa, chciałbym wiedzieć: kiedy do aliasu, kiedy do skryptu, a kiedy do napisania funkcji?
Jeśli chodzi o aliasy, używam ich do bardzo prostych operacji, które nie wymagają argumentów.
alias houston='cd /home/username/.scripts/'
To wydaje się oczywiste. Ale niektórzy to robią:
alias command="bash bashscriptname"
(i dodaj go do .bashrc
pliku)
Czy jest na to dobry powód? Bardzo się staram, ale naprawdę nie mogę wymyślić żadnych okoliczności, w których chciałbym to zrobić. Tak więc, jeśli istnieje przypadek skrajny, w którym miałoby to znaczenie, odpowiedz poniżej.
Ponieważ właśnie tam po prostu umieściłem coś w mojej ŚCIEŻCE i chmod +x
to, co jest kolejną rzeczą, która pojawiła się po latach prób i błędów Linuksa.
Co prowadzi mnie do następnego tematu. Na przykład dodałem ukryty folder ( .scripts/
) w katalogu domowym do mojej ŚCIEŻKI, po prostu dodając wiersz do mojego .bashrc
( PATH=$PATH:/home/username/.scripts/
), aby wszystko, co można tam wykonać, automatycznie się uzupełnia.
Gdybym musiał.
Tak naprawdę nie potrzebuję tego, prawda? Użyłbym tego tylko dla języków, które nie są powłoką, takich jak Python.
Jeśli jest to powłoka, mogę po prostu napisać funkcję wewnątrz tego samego .bashrc
:
funcname () {
somecommand -someARGS "$@"
}
Jak powiedziałem, wiele z tego znalazłem na zasadzie prób i błędów. I naprawdę naprawdę widziałem piękno funkcji, gdy zmarł mój komputer, i byłem zmuszony korzystać z komputerów ludzi wokół mnie, gdy z nich nie korzystali.
Zamiast przenosić cały katalog skryptów z komputera na komputer, w końcu po prostu zastąpiłem .bashrc innych użytkowników własnym, ponieważ nigdy nawet nie dokonali żadnej modyfikacji.
Ale czy coś mi umknęło?
Co byś powiedział początkującemu użytkownikowi systemu Linux o tym, kiedy należy alias, kiedy wykonać skrypt, a kiedy napisać funkcję?
Jeśli nie jest to oczywiste, zakładam, że osoby, które odpowiedzą na to pytanie, skorzystają ze wszystkich trzech opcji. Jeśli używasz tylko aliasów lub tylko skryptów lub tylko funkcji - lub jeśli używasz tylko aliasów i skryptów lub aliasów i funkcji lub skryptów i funkcji - to pytanie nie jest skierowane do Ciebie.
źródło
Odpowiedzi:
Alias nie powinien (ogólnie) robić więcej niż zmieniać domyślne opcje polecenia. To nic innego jak proste zastąpienie tekstu w nazwie polecenia. Nie może nic zrobić z argumentami, ale przekazuje je do polecenia, które faktycznie wykonuje. Jeśli więc po prostu potrzebujesz dodać argument z przodu jednego polecenia, alias zadziała. Typowe przykłady to
Z funkcji należy korzystać, gdy trzeba zrobić coś bardziej złożonego niż alias, ale nie byłoby to przydatne samo w sobie. Weźmy na przykład odpowiedź na pytanie, które zadałem na temat zmiany
grep
domyślnego zachowania w zależności od tego, czy jest ono w potoku:Jest to doskonały przykład funkcji, ponieważ jest zbyt skomplikowany dla aliasu (wymaga różnych ustawień domyślnych w zależności od warunku), ale nie jest to coś, czego potrzebujesz w nieinteraktywnym skrypcie.
Jeśli otrzymasz zbyt wiele funkcji lub funkcji za dużych, umieść je w osobnych plikach w ukrytym katalogu i umieść je w
~/.bashrc
:Skrypt powinien działać samodzielnie. Powinien mieć wartość jako coś, co można ponownie wykorzystać lub wykorzystać do więcej niż jednego celu.
źródło
.
lubsource
- skrypt jest wykonywany przez osobny proces bash i ma własne środowisko. Z tego powodu wszystko, co modyfikuje środowisko powłoki (np. Funkcje, zmienne itp.), Nie przetrwa w środowisku powłoki, z którego uruchamiany jest skrypt.Pozostałe odpowiedzi dostarczają miękkich ogólnych wskazówek opartych na osobistym guście, ale ignorują wiele istotnych faktów, które należy wziąć pod uwagę przy podejmowaniu decyzji między skryptami, funkcjami lub aliasami.
Aliasy i funkcje ¹
Skrypty
$PATH
wyszukiwania, wiele powłok przechowuje w pamięci skrót nazwy ścieżki, aby zaoszczędzić czas na przyszłych$PATH
przeglądaniach, ale taki jest zasięg pamięci skryptu, gdy nie jest używany.Skrypty można wywoływać na więcej sposobów niż funkcje i aliasy. Mogą być przekazywane jako argument do interpretera, podobnie jak
sh script
lub wywoływane bezpośrednio jako plik wykonywalny, w którym to przypadku interpreter w linii shebang (np.#!/bin/sh
) Jest wywoływany, aby go uruchomić. W obu przypadkach skrypt jest uruchamiany przez osobny proces interpretera z własnym środowiskiem innym niż środowisko twojej powłoki, na którego środowisko skrypt nie ma żadnego wpływu. Rzeczywiście, powłoka interpretera nie musi nawet odpowiadać powłoce wywołującej. Ponieważ skrypty wywoływane w ten sposób wydają się zachowywać jak każdy zwykły plik wykonywalny, mogą być używane przez dowolny program.Wreszcie, skrypt można odczytać i prowadzony przez bieżącej powłoki z
.
, lub w niektórych muszli,source
. W takim przypadku skrypt zachowuje się jak funkcja odczytywana na żądanie, a nie stale przechowywana w pamięci.Podanie
Biorąc powyższe pod uwagę, możemy opracować ogólne wytyczne dotyczące tworzenia skryptów lub funkcji / aliasów.
Czy inne programy poza powłoką muszą być w stanie z niego korzystać? Jeśli tak, musi to być skrypt.
Czy chcesz, aby była ona dostępna tylko z interaktywnej powłoki? Często zachodzi potrzeba zmiany domyślnego zachowania wielu poleceń, gdy są uruchamiane interaktywnie, bez wpływu na zewnętrzne polecenia / skrypty. W tym przypadku użyj zestawu aliasów / funkcji w pliku rc powłoki „tylko w trybie interaktywnym” (w
bash
tym celu.bashrc
).Czy musi zmienić środowisko powłoki? Możliwe są zarówno funkcja / alias, jak i skrypt źródłowy.
Czy używasz tego często? Prawdopodobnie bardziej efektywne jest utrzymywanie go w pamięci, więc jeśli to możliwe, uczyń go funkcją / aliasem.
I odwrotnie, czy używasz go rzadko? W takim przypadku nie ma sensu mieć pamięci, gdy jej nie potrzebujesz, więc zrób z niej skrypt.
¹ Chociaż funkcje i aliasy mają kilka ważnych różnic, są one pogrupowane razem, ponieważ funkcje mogą robić wszystko, co mogą aliasy. Aliasy nie mogą mieć zmiennych lokalnych ani przetwarzać argumentów i są niewygodne w przypadku elementów dłuższych niż jedna linia.
² Każdy uruchomiony proces w systemie Unix ma środowisko składające się z
variable=value
pary par, które często zawierają globalne ustawienia konfiguracji, takie jakLANG
domyślne ustawienia regionalne iPATH
określające ścieżkę wyszukiwania wykonywalnego.źródło
alias g='gradle'
autouzupełniania stopni podczas korzystania z mojegog
aliasu, ale nie wyskakuję z pudełka po użyciu skryptugradle $*
lub funkcji zgradle $@
Myślę, że to zależy od gustu każdej osoby. Dla mnie logika wygląda następująco:
Naprawdę nic nie stoi na przeszkodzie, abyś zrobił coś, co działa .
źródło
Przynajmniej częściowo jest to kwestia osobistego gustu. Z drugiej strony istnieją pewne wyraźne rozróżnienia funkcjonalne:
Patrząc na skrypty powłoki, które zrobiłem w ciągu ostatnich kilku lat, mniej więcej przestałem pisać aliasy (ponieważ z czasem wszystkie stają się funkcjami) i wykonuję skrypty tylko wtedy, gdy muszą być dostępne również ze środowisk innych niż bash.
PS: Co do
alias command="bash bashscriptname"
tego, nie widzę żadnego powodu, aby to robić. Nawet jeślibashscriptname
nie ma w PATH $, wystarczy prostealias c=/path/to/script
.źródło
alias command="bash bashscriptname"
skrypcie niekoniecznie musi być wykonywalny; w tymalias c=/path/to/script
musi.exec()
Oto kilka dodatkowych punktów na temat aliasów i funkcji:
Na przykład:
Jak widzimy, istnieją oddzielne przestrzenie nazw dla aliasów i funkcji; więcej szczegółów można znaleźć za pomocą
declare -A -p BASH_ALIASES
ideclare -f f
, który drukuje ich definicje (obie są przechowywane w pamięci).Przykład pokazujący ograniczenia aliasów:
Jak widzimy, aliasy nie są zagnieżdżane, w przeciwieństwie do funkcji. Ponadto ich użycie ogranicza się do sesji interaktywnych.
Na koniec zauważ, że możesz mieć dowolne obliczenia w aliasie, zadeklarując funkcję natychmiast wywołującą ją, tak jak:
który jest już szeroko stosowany w przypadku aliasów Git. Zaletą takiego działania w stosunku do zadeklarowania funkcji jest to, że alias nie może być po prostu nadpisany przez zebranie (lub użycie
.
) skryptu, który zdarza się zadeklarować funkcję o tej samej nazwie.źródło
Kiedy napisać skrypt ...
export
edytowanych zmiennych i / lub funkcji są przekazywane wartościowo do skryptu. Zmiany tych zmiennych nie są przenoszone z powrotem do skryptu nadrzędnego.Kiedy napisać funkcję ...
Kiedy pisać alias ...
~/.profile
lub~/.bashrc
.W skryptach, takich jak skrypty biblioteczne, czasami potrzebny jest alias dla funkcji, na przykład gdy nazwa funkcji jest zmieniana, ale wymagana jest kompatybilność wsteczna. Można to osiągnąć, tworząc prostą funkcję o starej nazwie, która przekazuje wszystkie argumenty do nowej funkcji ...
źródło
Jeszcze jedna kwestia, o której nie wierzę, została podniesiona: funkcja jest wykonywana w kontekście procesu wywoływania, podczas gdy skrypt wyświetla nową powłokę.
Może to być ważne dla wydajności - funkcja jest szybsza, ponieważ nie działa
fork()
iexec()
. W normalnych okolicznościach różnica jest trywialna, ale jeśli debugujesz system, który nie ma pamięci i rujnuje strony, może to mieć duże znaczenie.Ponadto, jeśli chcesz zmodyfikować obecne środowisko powłoki, powinieneś użyć funkcji. Na przykład funkcja może zmienić wyszukiwanie poleceń
$PATH
dla bieżącej powłoki, ale skrypt nie może tego zrobić, ponieważ działa na kopii fork / exec$PATH
.źródło
export -f
funkcji, choć dokładne jej wewnętrzne działanie jest nieco niejasne. Wierzę, że nie jest to przenośne do tradycyjnej powłoki Bourne'a.Skrypt i alias oraz skrypt i funkcja nie wykluczają się wzajemnie. Możesz zapisywać aliasy i funkcje w skryptach.
Skrypty są tylko kodem, który jest trwały . Przydatne funkcje i aliasy, których chcesz używać w przyszłości, są przechowywane w skryptach. Jednak skrypt jest często zbiorem więcej niż jednej funkcji.
Ponieważ aliasy nie są parametryzowane , są bardzo ograniczone; zwykle w celu zdefiniowania niektórych parametrów domyślnych.
Funkcja jest oddzielny element kodu , dobrze określone pojęcie kilku linii kodu, który nie może podzielić na mniejsze części, użyteczne; taki, który może być ponownie wykorzystany bezpośrednio lub inny przez inne funkcje.
źródło
Jeśli powinien być bardzo szybki, uczyń go aliasem lub funkcją.
Jeśli powinien być użyteczny poza preferowaną powłoką, uczyń go skryptem. 1
Jeśli wymaga argumentów, uczyń go funkcją lub skryptem.
Jeśli musi zawierać znaki specjalne, ustaw go jako alias lub skrypt. 2)
Jeśli musi współpracować z sudo, ustaw go jako alias lub skrypt. 3)
Jeśli chcesz to łatwo zmienić bez wylogowania i zalogowania, skrypt jest łatwiejszy. 4
Przypisy
1 Lub uczyń go pseudonimem, włóż go
~/.env
i ustawexport ENV="$HOME/.env"
, ale skomplikowane jest, aby działało przenośnie.2 Nazwy funkcji muszą być identyfikatorami, więc muszą zaczynać się od litery i mogą zawierać tylko litery, cyfry i znaki podkreślenia. Na przykład mam alias
alias +='pushd +1'
. To nie może być funkcja.3 I dodaj alias
alias sudo='sudo '
. Podobnie jak inne polecenia, takie jakstrace
,gdb
itp., Które przyjmują polecenie jako pierwszy argument.4 Zobacz także: fpath. Oczywiście możesz to zrobić
source ~/.bashrc
lub podobnie, ale często ma to inne skutki uboczne.źródło
+
w bash. Co ciekawe, po testach odkryłem, że w bash możesz utworzyć+
alias, ale nie funkcję, jak mówisz, ale zsh jest na odwrót -+
może być funkcją, ale nie aliasem.zsh
musisz pisaćalias -- +='some command here'
.+
jest przenośny. Zobacz specyfikację POSIX w Alias Namessudo
użycia. Jeśli chodzi o przypis 4, przechowuję moje aliasy~/.bash_aliases
i definicje funkcji,~/.bash_functions
aby mócsource
je łatwo zmienić (bez ryzyka skutków ubocznych).Wystarczy dodać kilka notatek:
Poza tym możesz użyć najprostszej możliwej formy, tj. Najpierw rozważ alias, potem funkcję, a potem skrypt.
źródło
sudo
. Ale najpierw potrzebujeszalias sudo='sudo '
.Moja ogólna zasada brzmi:
źródło
W środowisku z wieloma użytkownikami (lub wieloma sysaminami) używam skryptów do wszystkiego, nawet jeśli jest to po prostu krótkie opakowanie typu „wykonaj coś ....”.
Oczywiście jest technicznie wolniejszy / mniej wydajny niż alias lub funkcja, ale to prawie nigdy nie ma znaczenia - i pod warunkiem, że znajdzie się na ścieżce, skrypt zawsze działa.
Twoja funkcja może być wywołana z crona, z czegoś ze zredukowanym lub zmodyfikowanym środowiskiem, takim jak sudo lub env, lub użytkownik może po prostu użyć innej powłoki niż ty - wszystko, co może uszkodzić alias lub funkcję.
Jeśli masz coś wrażliwego na wydajność, potraktuj to jako wyjątkowy przypadek lub jeszcze lepiej, rozważ wyzwalacz do przepisania w bardziej funkcjonalnym języku skryptowym.
Jeśli mówimy o funkcjach, które będą używane tylko w innych skryptach, możesz również rozważyć zdefiniowanie standardowej powłoki i napisanie takiego skryptu biblioteki funkcji. pozyskałem wszystkie inne skrypty.
T.
źródło
Przykład sytuacji, w której najprawdopodobniej chcesz użyć aliasu.
Wiem, że to stary post, ale chciałbym zwrócić uwagę na sytuację, w której prawie musiałem użyć kombinacji aliasu ze skryptem i postanowiłem nie używać funkcji.
Mam
~/.bin/
wywoływany skrypt,setup
który wykonuje następujące czynności: 1Chodzi o to, że gdybym tylko uruchomił
setup <project-name>
, nie zdefiniowałbym tych zmiennych i w ogóle nie wszedłbym do katalogu. Rozwiązaniem, które uznałem za najlepsze, było dodanie tego skryptuPATH
i dodaniealias setup=". ~/.bin/setup"
go~/.bashrc
lub cokolwiek innego.Uwagi:
źródło
Kiedy pisać skrypt
Gdy możesz chcieć uruchomić polecenie z narzędzia innego niż powłoka.
Obejmuje to vim (dla mnie): mając napisane filtry i inne programy jako skrypty, mogę zrobić coś takiego jak
:%!my-filter
filtrowanie pliku przez program z mojego edytora.Gdyby
my-filter
była funkcja lub alias, nie byłoby to możliwe.źródło