Czy możesz edytować skrypt powłoki, gdy jest uruchomiony, i mieć wpływ na zmiany działającego skryptu?
Ciekawi mnie konkretny przypadek skryptu csh, który mam, który uruchamia kilka różnych smaków kompilacji i działa przez całą noc. Jeśli coś przyjdzie mi do głowy w trakcie operacji, chciałbym wejść i dodać dodatkowe polecenia lub zakomentować te, które nie zostały wykonane.
Jeśli nie jest to możliwe, czy istnieje mechanizm powłoki lub wsadowy, który pozwoliłby mi to zrobić?
Oczywiście próbowałem, ale miną godziny, zanim zobaczę, czy zadziałało, czy nie, i jestem ciekaw, co się dzieje, a co nie dzieje się za kulisami.
Odpowiedzi:
Skrypty nie działają w ten sposób; wykonywana kopia jest niezależna od edytowanego pliku źródłowego. Gdy skrypt zostanie uruchomiony następnym razem, będzie oparty na ostatnio zapisanej wersji pliku źródłowego.
Rozsądne może być podzielenie tego skryptu na wiele plików i uruchomienie ich osobno. Skróci to czas wykonywania do awarii. (tj. podziel wsad na jeden skrypt kompilacji, uruchamiając każdy z nich osobno, aby zobaczyć, który z nich powoduje problem).
źródło
Ma to wpływ, przynajmniej uderza w moje otoczenie, ale w bardzo nieprzyjemny sposób . Zobacz te kody. Po pierwsze
a.sh
:#!/bin/sh echo "First echo" read y echo "$y" echo "That's all."
b.sh
:#!/bin/sh echo "First echo" read y echo "Inserted" echo "$y" # echo "That's all."
Zrobić
$ cp a.sh run.sh $ ./run.sh $ # open another terminal $ cp b.sh run.sh # while 'read' is in effect $ # Then type "hello."
W moim przypadku wynik jest zawsze:
(Oczywiście znacznie lepiej jest to zautomatyzować, ale powyższy przykład jest czytelny).
[edytuj] To jest nieprzewidywalne, a więc niebezpieczne. Najlepiej jest obejście , jak opisano tutaj umieścić wszystko w nawias, a przed nawiasem zamykającym, umieścić „exit” . Przeczytaj dobrze połączoną odpowiedź, aby uniknąć pułapek.
[dodano] Dokładne zachowanie zależy od jednej dodatkowej nowej linii i być może także od twojego uniksowego stylu, systemu plików itp. Jeśli po prostu chcesz zobaczyć jakieś wpływy, po prostu dodaj "echo foo / bar" do b.sh przed i / lub po wiersz „czytaj”.
źródło
b.sh
, dodając 10 linii echo foo / bar / baz. Istota odpowiedzi udzielonych przez dave4220 i mnie jest taka, że efekt nie jest łatwy do przewidzenia. (BTW rzeczownik "schorzenie" oznacza "miłość" =)Spróbuj tego ... utwórz plik o nazwie
bash-is-odd.sh
:#!/bin/bash echo "echo yes i do odd things" >> bash-is-odd.sh
To pokazuje, że bash rzeczywiście interpretuje skrypt „na bieżąco”. Rzeczywiście, edycja długo działającego skryptu ma nieprzewidywalne rezultaty, wstawianie losowych znaków itp. Dlaczego? Ponieważ bash czyta od ostatniej pozycji bajtu, więc edycja zmienia położenie aktualnie odczytywanego znaku.
Jednym słowem, Bash jest bardzo, bardzo niebezpieczny z powodu tej „funkcji”. svn i
rsync
gdy są używane ze skryptami bash są szczególnie kłopotliwe, ponieważ domyślnie „scalają” wyniki ... edycja na miejscu.rsync
ma tryb, który to naprawia. svn i git nie.Przedstawiam rozwiązanie. Utwórz plik o nazwie
/bin/bashx
:#!/bin/bash source "$1"
Teraz używaj
#!/bin/bashx
na swoich skryptach i zawsze uruchamiaj je za pomocąbashx
zamiastbash
. To rozwiązuje problem - możesz bezpieczniersync
używać swoich skryptów.Alternatywne (in-line) rozwiązanie zaproponowane / przetestowane przez @ AF7:
{ # your script } exit $?
Nawiasy kręcone chronią przed edycją, a wyjście przed wyrostkami. Oczywiście wszystkim byłoby znacznie lepiej, gdyby bash był wyposażony w opcję, taką jak
-w
(cały plik) lub coś, co robiło to.źródło
Podziel skrypt na funkcje i za każdym razem, gdy zostanie wywołana funkcja,
source
z osobnego pliku. Następnie możesz edytować pliki w dowolnym momencie, a uruchomiony skrypt przyjmie zmiany następnym razem, gdy zostanie pobrany.foo() { source foo.sh } foo
źródło
Dobre pytanie! Mam nadzieję, że ten prosty skrypt pomoże
#!/bin/sh echo "Waiting..." echo "echo \"Success! Edits to a .sh while it executes do affect the executing script! I added this line to myself during execution\" " >> ${0} sleep 5 echo "When I was run, this was the last line"
Wydaje się, że pod Linuksem zmiany dokonane w wykonywanym pliku .sh są wprowadzane przez skrypt wykonawczy, jeśli można pisać wystarczająco szybko!
źródło
Interesująca uwaga na marginesie - jeśli uruchamiasz skrypt w Pythonie, to się nie zmienia. (Jest to prawdopodobnie rażąco oczywiste dla każdego, kto rozumie, jak powłoka uruchamia skrypty Pythona, ale pomyślał, że może to być przydatne przypomnienie dla kogoś, kto szuka tej funkcji).
Ja stworzyłem:
#!/usr/bin/env python3 import time print('Starts') time.sleep(10) print('Finishes unchanged')
Następnie w innej powłoce, gdy ten śpi, edytuj ostatnią linię. Po zakończeniu wyświetla niezmienioną linię, prawdopodobnie dlatego, że działa
.pyc
? To samo dzieje się na Ubuntu i macOS.źródło
Nie mam zainstalowanego csh, ale
#!/bin/sh echo Waiting... sleep 60 echo Change didn't happen
Uruchom to, szybko edytuj ostatnią linię do przeczytania
echo Change happened
Wyjście jest
Waiting... /home/dave/tmp/change.sh: 4: Syntax error: Unterminated quoted string
Hrmph.
Wydaje mi się, że zmiany w skryptach powłoki nie przynoszą efektu, dopóki nie zostaną ponownie uruchomione.
źródło
Change didn'ned
.Jeśli to wszystko jest w jednym skrypcie, to nie, to nie zadziała. Jeśli jednak skonfigurujesz go jako skrypt sterownika wywołujący skrypty podrzędne, możesz być w stanie zmienić skrypt podrzędny przed jego wywołaniem lub przed ponownym wywołaniem, jeśli wykonujesz pętlę, iw takim przypadku wierzę, że te zmiany zostanie odzwierciedlone w wykonaniu.
źródło
Słyszę nie ... ale co z pewnym pośrednim:
BatchRunner.sh
Command1.sh Command2.sh
Command1.sh
Command2.sh
Wtedy powinieneś być w stanie edytować zawartość każdego pliku poleceń, zanim BatchRunner przejdzie do niego, prawda?
LUB
Bardziej przejrzysta wersja miałaby wyglądać BatchRunner do pojedynczego pliku, w którym uruchamiałby kolejno po jednej linii na raz. Wtedy powinieneś móc edytować ten drugi plik, gdy pierwszy jest uruchomiony, prawda?
źródło
Zamiast tego użyj Zsh do tworzenia skryptów.
ODPOWIEDŹ, Zsh nie wykazuje tego frustrującego zachowania.
źródło
zwykle rzadko edytuje się skrypt podczas jego działania. Wszystko, co musisz zrobić, to poddać kontroli swoje operacje. Użyj instrukcji if / else, aby sprawdzić warunki. Jeśli coś się nie powiedzie, zrób to, w przeciwnym razie zrób to. To jest droga do zrobienia.
źródło