Czy mogę zmodyfikować plik skryptu bash (.sh), gdy jest uruchomiony?

28

Załóżmy, że mam skrypt script.sh, którego wykonanie zajmuje trochę czasu. I wykonać ją ./script.sh. Gdy jest uruchomiony w oknie terminala, modyfikuję plik script.sh. Czy będzie to miało jakiś wpływ na już uruchomiony proces?

Po zmodyfikowaniu go wykonuję zmodyfikowany plik, więc mam teraz dwa uruchomione procesy. Czy to w porządku?

becko
źródło
2
podobny do unix.stackexchange.com/q/121013/55673 w U&L
Zarejestrowany użytkownik

Odpowiedzi:

36

Wprowadzając zmiany w skrypcie, dokonujesz zmian na dysku (dysk twardy - pamięć stała); po uruchomieniu skryptu skrypt jest ładowany do pamięci (RAM).

Tak więc zmiany, które wprowadzisz w skrypcie, nie wpłyną na uruchomiony skrypt, uruchomi on wersję wykonaną przed wprowadzeniem tych zmian.

Jednak po ponownym uruchomieniu zmienionego skryptu bez kończenia poprzednio działającej instancji pojawią się dwie instancje skryptu - jedna ze zmianami i stara.

Ostrzegamy, że zasoby używane i modyfikowane przez skrypt będą powodować konflikty. Na przykład, jeśli modyfikujesz plik za pomocą skryptu, skrypt, który zostanie uruchomiony później, nie będzie mógł otworzyć tego pliku do zapisu i nie wykona się poprawnie.

Aktualizacja: Dziękujemy Zarejestrowanemu Użytkownikowi za wskazanie lepszej odpowiedzi na Unix.stackexchange.com.

W zależności od wielkości skryptu i danego kompilatora / interpretera skrypt jest ładowany częściowo / całkowicie. Jeśli więc skrypt nie zostanie całkowicie załadowany, zmiany wprowadzone w skrypcie zostaną odzwierciedlone w działającej instancji po załadowaniu części skryptu do pamięci.

Dlatego nie jest zalecane zmienianie skryptu na dysku, który jest obecnie uruchomiony w celu uzyskania nieprzewidzianych danych wyjściowych: Najpierw zatrzymaj działającą instancję, a następnie zmodyfikuj skrypt, a następnie ponownie uruchom skrypt.

Praca w
źródło
11
Nie jest to idealna odpowiedź, przeczytaj unix.stackexchange.com/q/121013/55673
Zarejestrowany użytkownik
@registereduser: o tak, to pytanie przypomniało mi o moich lekcjach systemu operacyjnego.
Zedytuję
Myślę, że w przypadku krótkich skryptów nie powinno być problemu.
becko
1
Kiedy próbowałem tego z bash v3.2.48 (patrz tutaj ), nie buforował on poza końcem wiersza (i nie powiodło się, gdy zmodyfikowałem skrypt podczas jego wykonywania). Właśnie przetestowałem ponownie wersję bash v4.3.0, która zbuforowała cały (krótki) skrypt. Więc ... nie liczyłbym na żadne konkretne zachowanie.
Gordon Davisson,
1
@RegisteredUser Nie ze wszystkimi wersjami bash - patrz przykład, który podlinkowałem.
Gordon Davisson,
4

Dodam coś, co moim zdaniem nie zostało powiedziane w innych odpowiedziach. Wiele zależy od sposobu edycji pliku. Wydaje mi się, że działanie echo "stuff" >filez powłoki (inna instancja) rzeczywiście nadpisze plik. Ale jeśli na przykład edytujesz plik, emacsa następnie zapiszesz, tak się nie stanie. Zamiast tego edytor zmienia nazwę starego pliku na nazwę kopii zapasowej (być może faktycznie usuwa poprzednią kopię zapasową), a następnie zapisuje zmodyfikowaną zawartość bufora jako nowy plik o (teraz za darmo) starej nazwie . Ponieważ powłoka (lub inny interpreter) czytająca skrypt prawie na pewno otworzy plik tylko raz, jest on następnie niezależny od miejsca, w którym znajduje się nazwa pliku, po prostu kontynuuje odczytywanie pliku dysku fizycznego (identyfikowanego przez numer i-węzła), który był powiązany z nazwą pliku w momencie otwierania. Więc nawet jeśli czyta skrypt w blokach (co byłoby najłatwiejszym rozwiązaniem, jeśli używasz buforowanego tekstu we / wy), nadal czytałby wiersze ze starej instancji pliku, co prawdopodobnie nie zmieni się podczas edycji.

Marc van Leeuwen
źródło
+1 Używam Sublime Text jako mojego edytora. Czy wiesz, czy on również zmienia nazwę pliku, na przykład emacs?
becko
1
Myślę, że większość redaktorów użyłaby schematu zmiany nazwy (nawet gdyby nie zachowywał wersji kopii zapasowej), aby uniknąć ryzyka, że ​​jeśli awaria wystąpi podczas procesu zapisu, nie pozostanie nienaruszona wersja tekstu. Możesz sprawdzić za pomocą „ls -i” (który pokazuje numery i-węzłów), jakie jest zachowanie twojego edytora.
Marc van Leeuwen,
1

należy to zaktualizować, powyższe odpowiedzi są teraz tylko częściowo poprawne:

w przypadku bieżącej wersji bash modyfikacja skryptu na dysku podczas działania spowoduje, że bash „spróbuje” załadować zmiany do pamięci i przyjąć je w działającym skrypcie. jeśli zmiany nastąpią po aktualnie wykonywanej linii, nowe linie zostaną załadowane i wykonane. ale jest to zgadywanie przez bash i może to zrobić dobrze lub źle.

lepszym sposobem na to jest następująca sekwencja czynności: 1) załaduj skrypt do pamięci 2) usuń skrypt z dysku 3) napisz nowy skrypt na dysku, usuwając najpierw wersję dysku, wersja pamięci traci do niej linki tak, że gdy podasz nową wersję w kroku 3, nie zostanie podjęta próba bash załadowania nowej zawartości do wersji pamięci.

kość słoniowa
źródło
0

Odpowiedź @ jobin jest ogólnie poprawna, ale dodam kilka innych odpowiedzi, które mogą być do rzeczy, w zależności od tego, co chcesz zrobić.

Jeśli chcesz zmienić skrypt i chcesz wiedzieć, że jest bezpieczny, to chcesz napisać do nowego pliku, a nie do istniejącego. Nowy plik może być zlokalizowany tam, gdzie był stary. Napisz nową wersję do nowego pliku, a następnie użyj, mvaby przenieść ją na miejsce nad starą wersją . Zastąpiony plik nadal istnieje, po prostu nie jest powiązany z katalogiem. Uruchomiony skrypt może dalej go używać, a kiedy ten skrypt zamyka uchwyt pliku, system wie, że może bezpiecznie wyczyścić plik (natychmiast lub później).

Jeśli chcesz zachować zachowanie skryptu w locie, masz trudniejszy problem. Oczekuję, że będziesz musiał wbudować go w kod skryptu. Skrypty Bash mogą obsługiwać sygnały (np. Mogą przechwycić coś podobnego kill -USR1 [pid]), a skrypt może następnie odpowiedzieć poprzez ponowne załadowanie kodu. Może więc możesz uzyskać funkcjonalność zbliżoną do tego, czego chcesz, ale nie wiedząc, czego szukasz, nie widzę dobrego powodu, aby to zrobić, i podejrzewam, że jeśli chcesz zrobić coś tak złożonego, prawdopodobnie chcesz bardziej wyrafinowanego język programowania, aby to zrobić.

Jeśli chcesz zhakować zachowanie działającego skryptu, który nie został napisany z myślą o tym, nie masz szczęścia. Wahałbym się przed nazwaniem jakiegokolwiek zadania programistycznego niemożliwym, ale gdybyś miał zasoby i umiejętności do tego rodzaju zadania, prawdopodobnie nie zapytałbyś tutaj.

Mc0e
źródło