W tej chwili pracuję nad większym skryptem Bash (jest to mój projekt Open Source) i zaczyna się robić bałagan. Podzieliłem logikę na funkcje, używam zmiennych lokalnych, gdzie mogę i zadeklarowałem tylko garść zmiennych globalnych. Mimo to utrzymanie go jest dość trudne.
Pomyślałem o podzieleniu skryptu na wiele skryptów i umieszczenie ich w głównym skrypcie (podobnie jak w importach w innych językach).
Ale zastanawiam się, czy jest to realne podejście. Po pierwsze, pozyskiwanie wielu skryptów może znacznie spowolnić czas wykonywania skryptu, a po drugie utrudnia dystrybucję.
Czy to jest dobre podejście i czy inne projekty (Open Source) robią to w ten sam sposób?
Odpowiedzi:
Tak, jest to powszechna praktyka. Na przykład, w pierwszych dniach Unix Shellcode odpowiedzialne za kierowanie systemem za pomocą fazy rozruchu do pracy wieloużytkownikowej był pojedynczy plik
/etc/rc
. Obecnie proces rozruchu jest kontrolowany przez wiele skryptów powłoki, podzielonych według funkcji, z typowymi funkcjami i zmiennymi pozyskiwanymi w razie potrzeby z centralnych lokalizacji. Dystrybucje Linuksa, komputery Mac, BSD w różnym stopniu przyjęły to podejście.źródło
Czy shell jest w tym momencie właściwym narzędziem do pracy? Jako programista, który wpadł na problemy związane z przerastaniem kodu, mogę powiedzieć, że przepisanie nie powinno być brane pod uwagę, ale zamiast tego rozważenie rozdzielenia elementów na coś lepiej dopasowanego do skali, w której chcesz rozwinąć swoją aplikację - na przykład python, ruby lub nawet perl ?
Shell to język narzędziowy - to język skryptowy - dlatego trudno będzie go rozwinąć do takich rozmiarów.
źródło
Jeśli ułatwia to konserwację, możesz mieć jedno i drugie. Podziel go na logiczne części, abyś mógł go łatwo utrzymywać, a następnie napisz (np.) Plik Makefile, aby złożyć go z powrotem do dystrybucji. Możesz napisać kilka szybkich skryptów, aby skopiować funkcje z pliku dołączania do pliku wyjściowego zamiast
source
linia lub po prostu zrobić coś tak trywialnego (musisz to ponownie tabify, jakmake
wymaga kart):Następnie masz wersję „źródłową” (używaną do edycji) i wersję „binarną” (używaną do trywialnej instalacji).
źródło
Skrypt można zepsuć w miarę opisywania - prawie wszystko można zrobić. Powiedziałbym, że „dobrym podejściem” byłoby podzielenie twojego dużego skryptu na przedziały, dowiedzieć się, gdzie jego części można uruchomić jako osobny proces, komunikując się za pośrednictwem mechanizmów IPC.
Poza tym dla skryptu powłoki spakowałbym go jako pojedynczy plik. Jak mówisz, utrudnia to dystrybucję: albo musisz wiedzieć, gdzie znajdują się skrypty „biblioteczne” - nie ma ładnego standardu dla skryptów powłoki - albo polegać na tym, że użytkownik prawidłowo ustawi swoją ścieżkę.
Możesz rozpowszechniać program instalacyjny, który obsługuje to wszystko za Ciebie, rozpakowując pliki, umieszczając je we właściwym miejscu, informując użytkownika o dodaniu czegoś takiego
export PROGRAMDIR=$HOME/lib/PROGRAM
do pliku ~ / .bashrc. Wtedy główny program może zawieść, jeśli$PROGRAMDIR
nie jest ustawiony lub nie zawiera oczekiwanych plików.Nie martwiłbym się tak bardzo o obciążenie związane z ładowaniem innych skryptów. Narzutem jest po prostu otwarcie pliku; przetwarzanie tekstu jest takie samo, szczególnie jeśli są to definicje funkcji.
źródło
Powszechna praktyka czy nie, nie sądzę, aby pozyskiwanie czegokolwiek innego niż zestaw eksportu było dobrym pomysłem. Uważam, że wykonywanie kodu przez pozyskiwanie jest po prostu mylące i ogranicza ponowne użycie, ponieważ ustawienia środowiskowe i inne zmienne bardzo uzależniają kod źródłowy od kodu źródłowego.
Lepiej jest podzielić aplikację na mniejsze, samodzielne skrypty, a następnie wykonać je jako serię poleceń. Ułatwi to debugowanie, ponieważ można wykonać każdy samodzielny skrypt w interaktywnej powłoce, sprawdzając pliki, dzienniki itp. Między każdym wywołaniem polecenia. Twój pojedynczy, duży skrypt aplikacji zamienia się w prostszy skrypt sterujący, który uruchamia serię poleceń po zakończeniu debugowania.
Grupa mniejszych, samodzielnych skryptów napotyka na trudniejszy do zainstalowania problem.
źródło
Alternatywą dla pozyskiwania skryptów jest po prostu wywoływanie ich za pomocą argumentów. Jeśli już podzieliłeś większość swojej funkcjonalności na funkcje powłoki, prawdopodobnie jesteś już prawie w stanie to zrobić. Poniższy fragment Bash pozwala na użycie dowolnej funkcji zadeklarowanej w skrypcie jako podkomendy:
Powodem tego
source
jest unikanie zanieczyszczenia środowiska i opcji zanieczyszczenia.źródło
Oto mój przykład tego, jak duży skrypt bash można podzielić na wiele plików, a następnie wbudować w jeden wynikowy skrypt: https://github.com/zinovyev/bash-project
Używam
Makefile
do tego celu:źródło