W przypadku tego pytania rozważmy skrypt powłoki bash, choć to pytanie musi dotyczyć wszystkich typów skryptów powłoki.
Kiedy ktoś wykonuje skrypt powłoki, czy Linux ładuje cały skrypt naraz (może do pamięci), czy też czyta polecenia skryptowe jeden po drugim (wiersz po wierszu)?
Innymi słowy, jeśli wykonam skrypt powłoki i usunę go przed zakończeniem wykonywania, czy wykonanie zostanie zakończone, czy będzie kontynuowane w takim stanie?
linux
shell
shell-script
zarejestrowany użytkownik
źródło
źródło
Odpowiedzi:
Jeśli używasz
strace
, możesz zobaczyć, w jaki sposób skrypt powłoki jest wykonywany podczas jego uruchamiania.Przykład
Powiedz, że mam ten skrypt powłoki.
Uruchamianie za pomocą
strace
:Przejrzenie
strace.log
pliku ujawnia następujące informacje.Po odczytaniu plik jest następnie wykonywany:
Powyżej widać wyraźnie, że cały skrypt wydaje się być wczytywany jako pojedyncza jednostka, a następnie wykonywany po nim. Tak więc „pojawi się” przynajmniej w przypadku Basha, że wczyta plik, a następnie go wykona. Myślisz, że możesz edytować skrypt podczas jego działania?
UWAGA: Nie rób tego! Czytaj dalej, aby zrozumieć, dlaczego nie powinieneś zadzierać z uruchomionym plikiem skryptu.
Co z innymi tłumaczami?
Ale twoje pytanie jest nieco wyłączone. To nie Linux ładuje zawartość pliku, to interpreter ładuje zawartość, więc tak naprawdę to zależy od tego, jak interpreter zaimplementuje to, czy ładuje plik w całości, czy w blokach lub liniach na raz.
Dlaczego więc nie możemy edytować pliku?
Jeśli używasz znacznie większego skryptu, zauważysz jednak, że powyższy test jest nieco mylący. W rzeczywistości większość tłumaczy ładuje swoje pliki w blokach. Jest to dość standardowe w przypadku wielu narzędzi uniksowych, w których ładują bloki pliku, przetwarzają go, a następnie ładują kolejny blok. Możesz zobaczyć to zachowanie z tymi pytaniami i pytaniami U&L, które napisałem przed chwilą
grep
, zatytułowane: Ile tekstu zużywa grep / egrep za każdym razem? .Przykład
Załóżmy, że wykonujemy następujący skrypt powłoki.
Wynikające z tego pliku:
Który zawiera następujący typ treści:
Teraz, gdy uruchomisz to przy użyciu tej samej techniki powyżej z
strace
:Zauważysz, że plik jest wczytywany z przyrostem 8 KB, więc Bash i inne powłoki prawdopodobnie nie załadują pliku w całości, a raczej czytają je w blokach.
Referencje
źródło
Jest to bardziej zależne od powłoki niż systemu operacyjnego.
W zależności od wersji,
ksh
czytaj skrypt na żądanie w bloku 8k lub 64k bajtów.bash
czytaj skrypt wiersz po wierszu. Jednak biorąc pod uwagę fakt, że linie mogą mieć dowolną długość, odczytuje za każdym razem 8176 bajtów od początku następnego wiersza do analizy.Dotyczy to prostych konstrukcji, tj. Zestawu prostych poleceń.
Jeśli używane są polecenia strukturalne powłoki ( przypadek, w którym zaakceptowana odpowiedź nie jest brana pod uwagę ), takie jak
for/do/done
pętla,case/esac
przełącznik, dokument tutaj, podpowłoka ujęta w nawiasy, definicja funkcji itp. Oraz dowolna kombinacja powyższych, interpretatory powłoki odczytują do końca budowy, aby najpierw upewnić się, że nie wystąpił błąd składniowy.Jest to nieco nieefektywne, ponieważ ten sam kod może być wielokrotnie odczytywany wiele razy, ale jest łagodzony przez fakt, że ta zawartość jest zwykle buforowana.
Niezależnie od interpretera powłoki, modyfikowanie skryptu powłoki podczas wykonywania jest niemądre, ponieważ powłoka może ponownie odczytać dowolną część skryptu, co może prowadzić do nieoczekiwanych błędów składniowych, jeśli nie jest zsynchronizowany.
Zauważ też, że bash może ulec awarii z naruszeniem segmentacji, gdy nie jest w stanie zapisać zbyt dużej konstrukcji skryptu, ksh93 może bezbłędnie czytać.
źródło
Zależy to od sposobu działania interpretera uruchamiającego skrypt. Jądro musi jedynie zauważyć, że plik do uruchomienia zaczyna się
#!
, w zasadzie uruchamia resztę wiersza jako program i nadaje mu plik wykonywalny jako argument. Jeśli wymieniony tam interpreter odczytuje ten plik wiersz po wierszu (tak jak interaktywne powłoki robią z tym, co piszesz), to właśnie otrzymujesz (ale struktury pętli wieloliniowych są odczytywane i przechowywane do powtórzenia); jeśli interpreter zatopi plik do pamięci, przetwarza go (być może kompiluje go do pośredniej reprezentacji, takiej jak Perl i Pyton), plik jest w całości czytany przed wykonaniem.Jeśli w międzyczasie usuniesz plik, plik nie zostanie usunięty, dopóki interpreter go nie zamknie (jak zawsze pliki znikają po ostatnim odwołaniu, niezależnie od tego, czy jest to wpis do katalogu, czy proces utrzymujący go w pozycji otwartej).
źródło
Plik „x”:
Bieg:
IIRC plik nie jest usuwany, dopóki proces utrzymuje go otwarty. Usunięcie po prostu usuwa podany DIRENT.
źródło