Właśnie wskakuję do unixa z innego świata i chciałem wiedzieć, czy
while true
do
/someperlscript.pl
done
Sam skrypt perla wewnętrznie ma moduł obserwatora folderów / plików, który jest wykonywany, gdy pliki są zmieniane w lokalizacji docelowej.
Czy to ( while true
) dobry pomysł? Jeśli nie, jakie jest preferowane solidne podejście?
TIA
EDYCJA: Ponieważ wydaje się, że wzbudziło to spore zainteresowanie, oto kompletny scenariusz. Sam skrypt perla obserwuje katalog za pomocą obserwatora plików. Po otrzymaniu nowych plików (przychodzą przez rsync), pobiera nowy i przetwarza go. Teraz przychodzące pliki mogą być uszkodzone (nie pytaj ... pochodzące z raspberry pi), a czasem proces może nie być w stanie sobie z tym poradzić. Nie wiem dokładnie dlaczego, ponieważ nie jesteśmy jeszcze świadomi wszystkich scenariuszy.
ALE - jeśli z jakiegoś powodu proces się nie powiedzie, chcemy, aby był uruchomiony i zajął się następnym plikiem, ponieważ następny plik jest całkowicie niezwiązany z poprzednim, który mógł spowodować błąd.
Zwykle używałbym jakiegoś typu catch all i owijałem wokół niego cały kod, aby NIGDY się nie zawiesił. Ale Perl nie był pewien.
Z tego, co zrozumiałem, dobrym rozwiązaniem jest użycie czegoś w rodzaju superwizora.
inotify
interfejs API, aby uniknąć zajętej pętli czekającej na zmianę plików w katalogu docelowym.Odpowiedzi:
To zależy od szybkości powrotu skryptu perla. Jeśli szybko wraca, możesz wstawić krótką pauzę między wykonaniami, aby uniknąć obciążenia procesora, np .:
Zapobiegnie to także skokowi procesora, jeśli skrypt nie zostanie znaleziony lub natychmiast się zawiesi.
Pętla może być lepiej zaimplementowana w samym skrypcie perl, aby uniknąć tych problemów.
Edytować:
Ponieważ napisałeś, że jedynym celem pętli jest ponowne uruchomienie skryptu perl w przypadku awarii, lepszym rozwiązaniem byłoby zaimplementowanie go jako usługi monitorowanej, ale dokładny sposób wykonania zależy od systemu operacyjnego. Np .: Solaris smf, Linux systemd lub restart oparty na cronie.
źródło
while sleep 1; do ...
aby zapisać prawdziwe połączenie.until ! sleep 1; do ...; done
nadal zapisze to wbudowane wywołanie podczas natychmiastowego uruchamiania skryptu.sleep 1& /someperlscript.pl; wait
.until
instrukcji, pomyliłem ją z hipotetycznądo/until
pętlą, która nie istnieje w powłoce.Pozostałe odpowiedzi dotyczące używania
inotify
są poprawne, ale nie stanowią odpowiedzi na to pytanie.Osoba nadzorująca proces, taka jak
supervisord
,upstart
lubrunit
, została zaprojektowana właśnie w celu obejrzenia i ponownego uruchomienia usługi, jeśli ulegnie awarii.Twoja dystrybucja prawdopodobnie ma wbudowanego nadzorcę procesu.
źródło
while true
jest w porządku jako uniwersalna konstrukcja „na zawsze”. Jak mówią inne odpowiedzi, ciało pętli nie powinno być puste, ani stać się puste na mocy niedziałającego polecenia wewnątrz pętli.Jeśli używasz Linuksa, możesz chcieć użyć polecenia podobnego
inotifywait
, cowhile
znacznie upraszcza pętlę:Tutaj
inotifywait
polecenie usiądzie i zaczeka na zdarzenie systemu plików (w tym przykładzie, gdy pliki w katalogu są zapisywane). W tym momencie kończy się powodzeniem i wykonuje się ciało pętli. Następnie wraca do oczekiwania. Ponieważinotifywait
polecenie czeka, aż coś się wydarzy w katalogu, jest znacznie wydajniejsze niż ciągłe odpytywanie katalogu.źródło
Przenieś while while do skryptu perl (zgodnie z sugestią @roaima)
źródło
Jeśli twój skrypt w Perlu ma być cały czas uruchomiony, po co korzystać z konstrukcji while? Gdy perl nie powiedzie się z powodu poważnego problemu, nowy skrypt perla uruchomiony przez chwilę może ulec awarii równie mocno. Znowu i znowu i tak dalej.
jeśli naprawdę chcesz, aby twój perl zaczął od nowa, rozważ crontab i skrypt, który najpierw sprawdza, czy działają instancje. W ten sposób skrypt zostanie uruchomiony nawet po ponownym uruchomieniu.
źródło
Zasadniczo nie ma problemu z używaniem,
while true
ponieważ jest to niewielki test, który jest wykonywany dopiero po zakończeniu skryptu perl. Pamiętaj, że w zależności od używanego wariantu Linux / Unix skrypt może zostać zakończony podczas wylogowywania. W takim przypadku rozważ użycie pętli w skrypcie i wywołaj ją za pomocąnohup
i umieść w tle, tjnohup myscript &
Jeśli skrypt Perla kończy się zbyt często i powoduje obciążenie procesora, obciążenie to odpowiada skryptowi perl, a nie
while true
.Zobacz także
man nohup
szczegóły.źródło
Jeśli chcesz zarządzać procesem, możesz zajrzeć do menedżera procesów.
W wielu najnowszych systemach możesz używać systemd do monitorowania procesów (co jest jedną z zalet systemd nad klasycznymi skryptami inicjującymi). Jeśli twoja dystrybucja nie używa systemd, możesz użyć daemontools lub monit .
źródło
mon
jest prostą alternatywą, jeśli ogromna ilość monitorów i systemowych przeszkadza ci tak samo, jak mnie.while
Pętla nie jest to dobry pomysł. Tam nie ma ucieczki - po prostu działa wiecznie - statycznie . Dowolna liczba rzeczy może się zmienić w środowisku i nie będzie to miało wpływu - i może być źle.Na przykład, jeśli plik wykonywalny powłoki odpowiedzialny za tę
while
pętlę zostanie zaktualizowany, jądro nie będzie w stanie zwolnić miejsca na dysku dla starej wersji, dopóki skrypt nie zostanie zamknięty, ponieważ musi on utrzymywać deskryptor tak długo, jak długo działa. Dotyczy to wszystkich plików, które powłoka mogłaby otworzyć z jakiegokolwiek powodu, aby uruchomić pętlę - wszystkie będą utrzymywane przez tęwhile
pętlę tak długo, jak długo będzie działać - na zawsze.A jeśli, nie daj Boże, w dowolnym miejscu powłoki działa przeciek pamięci - nawet przez najdłuższą chwilę - po prostu nadal będzie przeciekać - statycznie . Zbuduje się niezaznaczone, a jedynym sposobem na to jest zabicie go z użyciem siły, a następnie uruchomienie go od nowa, aby zrobić to samo później.
To naprawdę nie jest sposób, w jaki powinieneś konfigurować proces w tle - przynajmniej, moim zdaniem, nie. Zamiast tego, jak myślę, powinien istnieć punkt zerowania - odświeżenie skryptu i jego stanu. Najłatwiej to zrobić za pomocą
exec
. Możesz zastąpić bieżący proces nowym - zachowując ten sam PID - ale nadal uruchamiając nowy proces.Na przykład, jeśli
perl
skrypt powinien zwrócić wartość true po tym, jak pomyślnie obsłużył modyfikację pliku w pewnym monitorowanym katalogu:...czy jakoś tak. Coś, co pozwala podstawowym maszynom znajdującym się za pętlą odświeżyć się co jakiś czas.
źródło
Głosowałem za kilkoma z tych odpowiedzi, ale instynktownie mam najcieplejsze uczucia do odpowiedzi @ WalterA. Tak było, dopóki nie stworzyłem własnej odpowiedzi ...
Osobiście staram się aktualizować skrypt Perla, aby zapisywał opisowy wpis dziennika o awarii i wysyłał ostrzeżenie do administratora.
Jeśli skrypt Perla ma nadal działać, czekając na zdarzenia zmian z systemu plików, dlaczego nie działa?
Jeśli to nie zawiedzie, dlaczego martwisz się o zawinięcie go w skrypt, aby uruchomić go ponownie w nieskończoność?
Jeśli wystąpi problem z konfiguracją lub zepsuta zależność, która powoduje przerwanie działania skryptu Perl, ponowne uruchomienie go w kółko prawdopodobnie nie spowoduje, że nagle zacznie działać.
Znasz definicję szaleństwa, prawda? (robienie tego samego w kółko, spodziewając się innego rezultatu). Tylko mówię. ;-)
źródło