Strona 1 z 1

bash - przerwanie pętli i zakończenie skryptu

: 25 kwietnia 2011, 20:52
autor: ksysinek
Witam.
Napisałem ostatnio dość pomocny mi skrypt, który wygląda mniej więcej tak:

Kod: Zaznacz cały

czynność1
while [warunek ] ;; do
     n x czynność2
done
czynność3
Jej pełne wykonanie zajmuje ok 23 dni. Nie mogę mieć tak długo włączonego komputera a gdy zabije po prostu skrypt bez wykonywania czynności3 to tworzą się pewne komplikację. Czy jest możliwość, aby skrypt po odebraniu sygnału o wyłączaniu komputera albo wydaniu polecenia:

Kod: Zaznacz cały

kill -9 $pid_skryptu
z innego terminala, skrypt wyszedł z pętli i wykonał czynność3? Znalazłem w Internecie takie coś ale nie za bardzo wiem, jak to wykorzystać.

: 03 maja 2011, 21:23
autor: kudlat9

Kod: Zaznacz cały

kill -9 $pid_skryptu
Dla takiego czegoś nic za bardzo nie zadziała. Sygnał zabijający nie może być przechwycony przez żaden proces w systemie. Dlaczego kończysz proces w ten sposób? Zabicie sygnału to powinna być ostateczność. Powinieneś używać po prostu:

Kod: Zaznacz cały

kill $pid_skryptu
Czyli domyślny sygnał SIGTERM, dzięki czemu mógłbyś przechwycić go, przechwycić za pomocą funkcji trap. Poczytaj:

Kod: Zaznacz cały

man bash
A polecenia zabijającego proces SIGKILL używaj w ostateczności.

Pozdrawiam
kudlaty

: 03 maja 2011, 23:28
autor: ksysinek
To już chyba z przyzwyczajenia. Po prostu ktoś mi pierwszy raz pokazał, ze należy wstawić tam dziewiątkę i tak robiłem. Równie dobrze mogę traktować zwykłym poleceniem zabicia procesu i nauczyć skrypt reagować na SIGTERM. Tylko czy to zadziała gdy root wyda polecenie restartu systemu bądź ktoś wciśnie wyłącznik na obudowie?

: 04 maja 2011, 09:25
autor: kudlat9
Zadziała, system podczas wyłączania wysyła do procesów sygnał TERM - chyba, że proces nie reaguje przez dłuższą chwile to wysyła SIGKILL dlatego procedura obsługi sygnału TERM musi być szybka (zapisanie danych i wyjście). Nie wiem jakie akcje wykonujesz w tej czynnosc2, ale pamiętaj, że podczas gdy twoja procedura będzie wykonywana w systemie może już nie istnieć dużo usług, ponieważ będą już zatrzymane przez system.

Najlepszym rozwiązaniem jest napisanie skryptu, który będzie wykonywany na samym początku podczas zamykania systemu, który będzie wysyłał odpowiedni sygnał do twojego procesu.

Musisz go umieścić w:

Kod: Zaznacz cały

/etc/init.d
i powiązać go z odpowiednim poziomem uruchomienia w:

Kod: Zaznacz cały

/etc/rc[twoj_poziom].d/

Oczywiście z odpowiednim prefiksem S (priorytet).

Poczytaj:

Kod: Zaznacz cały

man update-rc.d

: 04 maja 2011, 11:43
autor: Bastian
kudlat9, w porządku, ale co w przypadku twardego resetu?

: 04 maja 2011, 14:12
autor: kudlat9
Bastian pisze:kudlat9, w porządku, ale co w przypadku twardego resetu?

To pytanie jest bezsensu, jak system ma poprawnie pozamykać procesy skoro znienacka odetniesz mu prąd? Dla takich przypadków jednym ratunkiem jest napisanie oprogramowania tak, aby był w stanie wznowić operacje po nieoczekiwanych restartach (np. wykorzystując mechanizmy transakcji).

: 04 maja 2011, 17:03
autor: Bastian
Pytanie nie jest bezsensu, bo autor wątku pytał o taką możliwość. W drugiej części Twojej wypowiedzi udzieliłeś poniekąd odpowiedzi.

: 11 maja 2011, 19:35
autor: DaVidoSS
Użyj aplikacji strace:

Kod: Zaznacz cały

        strace -e trace=process >proces<
lub trap :

Kod: Zaznacz cały

trap "/usr/bin/program; exit 255" SIGINT SIGTERM

: 11 maja 2011, 23:43
autor: ksysinek
Zapoznałem się już z funkcją trap jednak ze wprowadzenia zmian w skrypcie zrezygnowałem. Bastian źle mnie zrozumiał. Oczywiście chodziło mi o wciśnięcie przycisku "miękkiego wyłączania" bo jak każdy zdaje sobie sprawę, ze przed gwałtownym odcięciem zasilania nic mnie nie uchroni. Poprawne wyjście ze skryptu wymaga działającego połączenia internetowego i zajmuje ok. minuty.

: 12 maja 2011, 12:18
autor: Bastian
Ewentualnie, skrypt mógłby po włączeniu komputera sprawdzać, czy czynność 3 została wykonana w ostatnim cyklu i jeśli nie, to zacząć swoją pracę od jej wykonania, a dopiero potem wchodziłby w pętlę.