Czy ktoś zna jakieś zasoby, które mówią o najlepszych praktykach lub wzorcach projektowych dla skryptów powłoki (sh, bash itp.)?
design-patterns
bash
shell
user14437
źródło
źródło
Odpowiedzi:
Napisałem dość złożone skrypty powłoki i moja pierwsza sugestia brzmi „nie rób tego”. Powodem jest to, że dość łatwo jest popełnić mały błąd, który utrudnia skrypt, a nawet czyni go niebezpiecznym.
To powiedziawszy, nie mam innych zasobów, aby ci przekazać, ale moje osobiste doświadczenie. Oto, co zwykle robię, co jest przesadą, ale zwykle jest solidne, chociaż bardzo rozwlekłe.
Wezwanie
spraw, aby twój skrypt akceptował długie i krótkie opcje. bądź ostrożny, ponieważ istnieją dwa polecenia do analizowania opcji, getopt i getopts. Użyj getopt, gdy będziesz mieć mniej problemów.
Inną ważną kwestią jest to, że program powinien zawsze zwracać zero, jeśli zakończy się pomyślnie, niezerowe, jeśli coś poszło nie tak.
Wywołania funkcji
Możesz wywoływać funkcje w bashu, pamiętaj tylko, aby zdefiniować je przed wywołaniem. Funkcje są jak skrypty, mogą zwracać tylko wartości liczbowe. Oznacza to, że musisz wymyślić inną strategię zwracania wartości ciągów. Moja strategia polega na użyciu zmiennej o nazwie RESULT do przechowywania wyniku i zwracaniu 0, jeśli funkcja zakończyła się poprawnie. Możesz także zgłosić wyjątki, jeśli zwracasz wartość różną od zera, a następnie ustawić dwie „zmienne wyjątków” (moje: EXCEPTION i EXCEPTION_MSG), pierwsza zawiera typ wyjątku, a druga czytelną dla człowieka wiadomość.
Kiedy wywołujesz funkcję, parametry funkcji są przypisywane do specjalnych zmiennych $ 0, $ 1 itd. Proponuję nadać im bardziej znaczące nazwy. zadeklaruj zmienne wewnątrz funkcji jako lokalne:
Sytuacje podatne na błędy
W bash, chyba że zadeklarujesz inaczej, nieustawiona zmienna jest używana jako pusty łańcuch. Jest to bardzo niebezpieczne w przypadku literówki, ponieważ źle wpisana zmienna nie zostanie zgłoszona i zostanie oceniona jako pusta. posługiwać się
aby temu zapobiec. Uważaj jednak, ponieważ jeśli to zrobisz, program przerwie działanie za każdym razem, gdy oceniasz niezdefiniowaną zmienną. Z tego powodu jedynym sposobem sprawdzenia, czy zmienna nie jest zdefiniowana, jest:
Możesz zadeklarować zmienne jako tylko do odczytu:
Modularyzacja
Możesz osiągnąć modularyzację "podobną do Pythona", używając następującego kodu:
możesz następnie importować pliki z rozszerzeniem .shinc z następującą składnią
import „AModule / ModuleFile”
Które będą przeszukiwane w SHELL_LIBRARY_PATH. Ponieważ zawsze importujesz w globalnej przestrzeni nazw, pamiętaj, aby poprzedzać wszystkie funkcje i zmienne odpowiednim prefiksem, w przeciwnym razie ryzykujesz konfliktami nazw. Używam podwójnego podkreślenia jako kropki Pythona.
Ponadto umieść to jako pierwszą rzecz w swoim module
Programowanie obiektowe
W bashu nie możesz robić programowania obiektowego, chyba że zbudujesz dość złożony system alokacji obiektów (myślałem o tym. Jest to wykonalne, ale szalone). W praktyce możesz jednak wykonać „programowanie zorientowane na singleton”: masz jedną instancję każdego obiektu i tylko jedną.
Co robię, to: definiuję obiekt w module (patrz wpis modularyzacji). Następnie definiuję puste zmienne (analogiczne do zmiennych składowych), funkcję init (konstruktor) i funkcje składowe, jak w tym przykładowym kodzie
Wychwytywanie i obsługa sygnałów
Uważam, że jest to przydatne do wychwytywania i obsługi wyjątków.
Porady i wskazówki
Jeśli z jakiegoś powodu coś nie działa, spróbuj ponownie zamówić kod. Porządek jest ważny i nie zawsze intuicyjny.
nawet nie myśl o pracy z tcsh. nie obsługuje funkcji i ogólnie jest okropny.
Mam nadzieję, że to pomoże, chociaż pamiętaj. Jeśli musisz użyć rzeczy, które tutaj napisałem, oznacza to, że twój problem jest zbyt złożony, aby można go było rozwiązać za pomocą powłoki. używać innego języka. Musiałem go użyć ze względu na czynniki ludzkie i dziedzictwo.
źródło
getopt
vsgetopts
?getopts
jest bardziej przenośny i działa w każdej powłoce POSIX. Zwłaszcza, że pytanie dotyczy najlepszych praktyk powłoki, a nie tylko najlepszych praktyk basha, poparłbym zgodność z POSIX, aby obsługiwać wiele powłok, jeśli to możliwe.Zapoznaj się z Przewodnikiem po zaawansowanych skryptach Bash aby uzyskać wiele informacji na temat skryptów powłoki - nie tylko Bash.
Nie słuchaj, jak ludzie mówią ci, żebyś spojrzał na inne, prawdopodobnie bardziej złożone języki. Jeśli skrypt powłoki spełnia Twoje potrzeby, użyj tego. Chcesz funkcjonalności, a nie elegancji. Nowe języki zapewniają cenne nowe umiejętności w Twoim CV, ale to nie pomaga, jeśli masz pracę do wykonania i znasz już powłokę Shell.
Jak już wspomniano, nie ma wielu „najlepszych praktyk” ani „wzorców projektowych” dotyczących skryptów powłoki. Różne zastosowania mają różne wytyczne i odchylenia - jak każdy inny język programowania.
źródło
skrypt powłoki to język przeznaczony do manipulowania plikami i procesami. Chociaż jest do tego świetny, nie jest to język ogólnego przeznaczenia, więc zawsze staraj się sklejać logikę z istniejących narzędzi, zamiast odtwarzać nową logikę w skrypcie powłoki.
Oprócz tej ogólnej zasady zebrałem kilka typowych błędów w skryptach powłoki .
źródło
W tym roku (2008) na OSCON odbyła się świetna sesja poświęcona tylko temu tematowi: http://assets.en.oreilly.com/1/event/12/Shell%20Scripting%20Craftsmanship%20Presentation%201.pdf
źródło
Wiedz, kiedy go używać. W przypadku szybkich i brudnych poleceń sklejania jest w porządku. Jeśli potrzebujesz więcej niż kilka nietrywialnych decyzji, pętli, czegokolwiek, wybierz Python, Perl i modularyzację .
Największym problemem związanym z powłoką jest często to, że efekt końcowy wygląda jak wielka kula błota, 4000 linii uderzenia i rośnie ... i nie możesz się jej pozbyć, ponieważ teraz cały twój projekt od tego zależy. Oczywiście zaczęło się od 40 linii pięknego basha.
źródło
Łatwe: używaj Pythona zamiast skryptów powłoki. Otrzymujesz prawie 100-krotny wzrost czytelności, bez konieczności komplikowania czegokolwiek, czego nie potrzebujesz, i zachowując możliwość przekształcania części twojego skryptu w funkcje, obiekty, trwałe obiekty (zodb), rozproszone obiekty (pyro) prawie bez żadnych dodatkowy kod.
źródło
użyj set -e, aby nie pchać do przodu po błędach. Spróbuj uczynić go kompatybilnym bez polegania na bash, jeśli chcesz, aby działał na innym systemie niż Linux.
źródło
Aby znaleźć "najlepsze praktyki", spójrz, jak dystrybucje Linuksa (np. Debian) piszą swoje skrypty inicjujące (zwykle znajdują się w /etc/init.d)
Większość z nich nie zawiera "bash-izmów" i ma dobrą separację ustawień konfiguracyjnych, plików bibliotek i formatowania źródła.
Moim osobistym stylem jest napisanie głównego skryptu powłoki, który definiuje niektóre domyślne zmienne, a następnie próbuje załadować („źródło”) plik konfiguracyjny, który może zawierać nowe wartości.
Staram się unikać funkcji, ponieważ powodują one, że skrypt jest bardziej skomplikowany. (Perl został stworzony w tym celu.)
Aby upewnić się, że skrypt jest przenośny, przetestuj nie tylko z #! / Bin / sh, ale także użyj #! / Bin / ash, #! / Bin / dash itp. Wkrótce zauważysz specyficzny kod Bash.
źródło
Lub starszy cytat podobny do tego, co powiedział Joao:
„Użyj perla. Będziesz chciał znać bash, ale go nie używać”.
Niestety zapomniałem, kto to powiedział.
I tak, obecnie polecałbym Pythona zamiast Perla.
źródło