W Perl istnieją specjalne bloki (BEGIN, CHECK, INIT, END), które pozwalają zarządzać czasem wykonania kodu:
BEGIN { ... } — wykonuje się natychmiast podczas kompilacji pliku (przed głównym kodem i przed załadowaniem modułów);CHECK { ... } — wykonuje się po kompilacji wszystkich plików, ale przed ich wykonaniem (nie we wszystkich wersjach Perl jest obsługiwane);INIT { ... } — wykonuje się przed rozpoczęciem wykonywania głównego kodu ("czas wykonania");END { ... } — wykonuje się po zakończeniu programu, przy wyjściu ze skryptu.Kolejność wykonania:
BEGINCHECKINITENDPrzykład:
BEGIN { print "BEGIN executed "; } CHECK { print "CHECK executed "; } INIT { print "INIT executed "; } print "Main code executed "; END { print "END executed "; }
Czy blok BEGIN wewnątrz modułu może wpłynąć na globalny stan programu, jeśli ten moduł jest dołączony za pomocą require, a nie use?
Odpowiedź i przykład:
Bloki BEGIN wykonują się przy kompilacji, dlatego nie zostaną wykonane, jeśli moduł jest dołączony za pomocą require (w czasie wykonywania, a nie przy kompilacji), a nie za pomocą use (wykonuje się w czasie kompilacji pliku dołączającego). Może to prowadzić do nieprzewidywalnego zachowania, jeśli inicjalizacja jest oparta na BEGIN.
Historia 1: W jednym projekcie użyto
BEGINdo inicjalizacji zmiennych środowiskowych, a moduł był dołączany za pomocąrequire— w rezultacie zmienne nie zostały ustawione, co wprowadziło chaos w ładowaniu konfiguracji na produkcji.
Historia 2: Przy użyciu bloku
ENDdo zamykania deskryptora pliku nie uwzględniono niejawnych zatrzymań procesu; czasami blokENDnie działał z powodu awaryjnego zakończenia pracy interpretera Perl, co prowadziło do utraty danych w logach.
Historia 3: Bloki
CHECKbyły jedynym miejscem uruchamiania testów dotyczących ważności środowiska. Użytkownik uruchomił skrypt w starej wersji Perl, gdzie nie było blokuCHECK, a kontrole po prostu się nie odbywały — krytyczne awarie ujawniały się dopiero w produkcji.