Mail RBL checker (Python)

Tak się zdarzyło w ostatnim czasie, że w paru miejscach pojawiły się problemy z dostarczaniem maili. Prawdopodobna przyczyna niedocierania poczty była ta sama – obecność IP serwera pocztowego na RBL. Przypomniały mi się stare czasy i walka z wypisywaniem IP z RBL oraz różne metody zapobiegania dostawania się na RBLe.

Zanim jednak zaczniemy cokolwiek robić, trzeba wiedzieć, że jesteśmy na RBLu, czyli monitorować obecność IP serwera pocztowego na RBL. Do szybkich, ręcznych, doraźnych sprawdzeń pojedynczych IP polecam stronę Multi-RBL Check, nie rozwiązuje to jednak tematu ciągłego, automatycznego monitoringu obecności IP na RBLach, np. przy pomocy Zabbiksa.

Sam monitoring jest trywialny – wystarczy odpytywać przy pomocy DNS, warto to jednak jakoś „opakować”. Napisałem to ze dwa razy w życiu (IIRC oba w Perlu), napiszę więc i trzeci, tym razem w Pythonie. Oczywiście podobnych rozwiązań na GitHubie jest wiele, ale w każdym coś mi nie pasowało – albo język, albo rozbudowane zależności, albo sposób przekazywnia informacji. To ostatnie to w sumie detal, łatwo można przefiltrować informacje przy pomocy grep lub awk.

W każdym razie, wczoraj opublikowałem mail-rbl-monitor. Zdecydowanie nie jest skończony, a struktura wynika z przygotowania pod przyszłe funkcje. Znaczy sprawdzanie listy IP pobieranej z pliku.

Wkrótce temat pokrewny, ale nieco trudniejszy – monitoring reputacji IP serwerów pocztowych.

Ilość rowerów Nextbike na stacjach – reaktywacja

Dawno temu pisałem o monitoringu rowerów Nextbike na stacjach. Moja strona podająca aktualną ilość rowerów miejskich na stacjach Nextbike działała do kwietnia tego roku, po czym przestała odświeżać dane. Jest to o tyle niefajne dla mnie, że appka androidowa Nextbike i jej wyszukiwanie rowerów to jakaś kpina i zdecydowanie łatwiej i szybciej znajdowałem potrzebne dane u siebie. Albo po prostu I don’t like the bugs but the bugs like me, czyli znowu mam pecha i u mnie nie działa. W ogóle o appkach na Androida, zwłaszcza polskich wypadałoby już popełnić osobny wpis…

Poczyniłem szybki debug i okazało się, że Nextbike zapytany o konkretne miasto zwraca od niedawna błędny XML, zawierający zawsze także dane dla Indii. Zgłosiłem błąd mailem, co wiązało się z zabawną sytuacją, bo po pierwsze zostałem przez centralę wzięty za pracownika (chyba raczej stażystę) firmy Nextbike i odesłany do innego pracownika, który może założyć ticket w systemie. Padło też pytanie, a skądże to ja mam namiar na ten URL (przypominam, mający official w nazwie). No cóż, URL lata w wielu miejscach w sieci…

W każdym razie błąd został zgłoszony, a dane się nie pokazywały. Próbowałem na szybko zreanimować skrypt w Perlu, ale albo zmian było więcej, albo nie do końca umiem korzystać z tej biblioteki. W każdym razie poległem, a na dłuższe grzebanie w Perlu nie miałem ochoty. Przy okazji niegdyś poukładany kod wydał mi się już nie taki fajny i w sumie można by go przepisać…

Wczoraj zrobiłem przymiarkę do napisania tego w Pythonie. Okazało się, że bez problemu jestem w stanie parsować XML. Przy okazji zrezygnowałem z pobierania danych dla każdego miasta oddzielnie – miast jest na tyle dużo, że szybciej jest pobrać plik XML raz. Skoro zapowiadało się tak fajnie, to od razu postanowiłem przerzucić konfigurację z hasha w programie do pliku YAML. A skoro szło tak fajnie, to zmieniłem „template”, zaszyty w printach w skrypcie, na Jinja2, przy okazji mając pierwszy praktyczny kontakt z tym rozwiązaniem, bo wcześniej „korzystałem” z niego tylko w template’ach dla bloga opartego o Pelican. Bardzo fajne, rozbudowane bardziej, niż przypuszczałem i jednak rządzące się swoimi prawami. W każdym razie mniej oczywiste niż mi się wydawało do tej pory.

Skoro szło tak dobrze, to dorzuciłem pięć kolejnych miast (Pszczyna, Zgierz, Kędzierzyn-Koźle, Kołobrzeg i Tychy), bo tyle pojawiło się od kwietnia. Oczywiście już nie do skryptu, tylko do prostego w utrzymaniu pliku z konfiguracją. 🙂 Całość zapakowana w virtualenv oczywiście, dla przenośności.

Ze skryptu nie jestem w 100% zadowolony – pewnie można go jeszcze uprościć, ale… może kiedy indziej, tym bardziej, że mógłbym jeszcze uzupełnić dane o geolokalizacji i pewnie gdzieniegdzie zostało błędne kodowanie znaków. Póki co, strona z ilością rowerów znowu działa. Ciekawostka – wszystkie pliki (skrypt, konfig, dane o wymaganych modułach) mają tyle samo linii co oryginalny Perl (TBH żadne nie było specjalnie sprzątane czy optymalizowane pod kątem wielkości), a jest o niebo czytelniej i prościej.

Python

Tak się składa, że ostatnio podstawowym językiem programowania, którego używam, jest Python. W związku z tym kilka przemyśleń na jego temat i na temat rozpoczynania zabawy z nim. Disclaimer: do Pythona podchodziłem już kiedyś, jeśli muszę coś napisać, to domyślnie korzystam z Perla (niekoniecznie pięknego, często poganiającego polecenia systemowe, ale działającego), a historycznie bawiłem się Pascalem, C i oczywiście miałem kontakt z Bashem i PHP (do ostatniego oficjalnie się nie przyznaję).

Po pierwsze, istnieją czytelne reguły, np. PEP 8, którego wszyscy używają[1] czy PEP 20. Są też narzędzia, które ułatwiają zachowanie zasad dotyczących formatowania kodu, aby był zgodny z wytycznymi. Nie sposób tu nie wspomnieć o edytorze Atom, którego kiedyś włączyłem i wydał mi się straszną kobyłą, ale w połączeniu z pluginami działa naprawdę dobrze. Na tyle na ile mogę stwierdzić przy tak małym doświadczeniu. W każdym razie ma wszystko, do czego używałem kate. I sporo więcej. Vim nigdy mi nie podszedł na tyle, bym go używał w bardziej zaawansowany sposób. Do szybkich poprawek zawsze było albo nano, albo właśnie vim, ale tryb tekstowy to nie jest to, co preferuję przy pracy nad dłuższym kodem.

Po drugie, dostępnych jest dużo materiałów do nauki Pythona. Także bezpłatnych. Samych książek/kursów jest kilkanaście (choćby oficjalny The Hitchhiker’s Guide to Python), istnieją też gry, które uczą programować w Pythonie (choćby Codecombat, którym kiedyś się bawiłem, o którym miała być notka, ale które ostatecznie mnie nie wciągnęło, a pomysł na notkę jakoś się rozmył). Mi do gustu przypadł jednak interaktywny kurs Learn Python na Androida. Jednak jeśli coś piszę i są interaktywne testy, a nie tylko czytam, to zapamiętuję więcej. Oczywiście nawet jeśli zapamiętam to do poziomu „potrafię użyć w programie” jest jeszcze kawałek, ale przynajmniej rozumiem przykłady i gotowy kod.

Po trzecie, istnieje sporo gotowych modułów, które ułatwiają pisanie, ale nawet gdyby nie istniały, to kod można „pożyczać” z innych skryptów przy pomocy import. I można mieć różne wersje bibliotek za sprawą środowisk wirtualnych. Z jednej strony fajne, z drugiej tworzy bałagan. Do developerki przydatne i zgodne z modną ostatnio ideą konteneryzacji. Ogólnie nauczyłem się z tym żyć, ale odruchu, żeby wszystko robić w virutalenv jeszcze nie mam.

Skoro mowa o bałaganie, to pora na wady, a tych jest zaskakująco wiele. Po pierwsze, Python 2 nadal żyje, ma się dobrze i można go spotkać na wolności. Taka umowna wada i na razie nie bardzo przeszkadza. Niemniej, nie każdy kod napisany w Pythonie 3 daje się wykorzystać w wersji drugiej.

Inna trochę dziwna na początku rzecz, to struktury danych. Jest tablica (list, w Perlu array), jest tablica asocjacyjna (dict, w Perlu hash), ale są też tuple (niemodyfikowalne listy) i sety (nieuporządkowane zbiory unikatowych wartości). Nie żebym nie widział zalet, ale żeby aż wydzielać to? Zwł. sety (normalnie to po prostu się hasha tworzy, klucze są nieuporządkowane i unikatowe)…

To co się najbardziej rzuca w oczy: wcięcia. Są wymagane i rzutują na kod. Najprostszy przykład to:

for i in range (3):
    print ("wartosc: ")
    print (i)

Usunięcie wcięcia w ostatnim wierszu totalnie zmieni sposób działania programu. Drażni szczególnie na początku, gdy chcemy coś na szybko przetestować i np. coś wklejamy – trzeba poprawić i dokładnie sprawdzić wcięcia, inaczej mogą być kwiatki jak wyżej.

Kolejna rzecz, która irytuje, to wciskanie filozofii w stylu zen. Na siłę i niekoniecznie zgodnie z prawdą. Weźmy mój ulubiony przykład:

There should be one– and preferably only one –obvious way to do it.

No to teraz bierzemy na tapetę set. Można go utworzyć przez

mojset = set([1, 2, 3])

Ale od wersji 2.7 można użyć do tworzenia równoważnej formy

mojset = {1, 2, 3}

Nie ma problemu? No to jak utworzyć pustego seta? Gdyby ktoś wpadł na całkiem logiczny pomysł użycia

mojset = {}

to niech wie, że nie pustego seta stworzył, a pustego dicta i za chwilę dostanie błędem po oczach. BTDT, dobry kwadrans dumania, czemu to nie działa i dopiero wezwana pomoc uratowała sytuację, bo nie wiem ile bym jeszcze nad tym dumał.

Także one way my ass, skoro Tim Toady wita nas już na samym wstępie, przy tworzeniu jednego z podstawowych typów danych.

Możliwe, że dla ludzi, którzy zaczynają programowanie od Pythona, wady nie są tak zauważalne czy irytujące.

Niemniej, oddaję sprawiedliwość – w Pythonie pisze się przyjemnie i w praktyce jest to łatwiejsze, niż wygląda na pierwszy rzut oka. Wystarczy przejrzeć jakiś tutorial. Zdarzało mi się pisać rozszerzenia do istniejących skryptów po kilku dniach styczności z językiem i nie było większych problemów. Więc faktycznie, może być czytelnie, prosto i wygodnie. Oczywiście mogło być tak, że na ładne skrypty trafiłem. 😉

Z Perlem oczywiście nie kończę, bo do pewnych rzeczy nadaje się IMHO lepiej, trochę gratów mam w nim napisanych, ale wersji 6 raczej już nie zacznę.

[1] A przynajmniej prawie wszyscy. A przynajmniej starają się. Prawie wszyscy.

UPDATE: Wspomniany kurs Learn Python skończyłem i szczerze polecam. Świetna podstawka, traktująca szeroko o różnych zagadnieniach, przy czym, jednak, te praktyczne części są lepsze, a teoretyczne kuleją. Jest w sumie o wszystkim najważniejszym, z programowaniem obiektowym i regexpami włącznie. Zapomniałem też wspomnieć o ipython – bardzo fajny do szybkiego sprawdzenia jakichś drobiazgów.

Swoją drogą, dziwi mnie to wciskanie regexpów do nauki programowania. To jest IMHO osobna działka zupełnie i nijak się nie klei z resztą.

Przy okazji kolejny kamyczek do ogródka w Pythonie jest inaczej: tym razem chodzi o re.match, które działa totalnie nieintuicyjnie, choć przyznaję, że w sposób zgodny z dokumentacją. Otóż ww. funkcja dopasowuje wyrażenie tylko na początku stringa. Czyli ma takie niejawne, hardcodowane ^ – i albo .* na początku, albo korzystamy z re.search, żeby było normalnie. One way my ass, ponownie. Szczęśliwie wyszło to na Learn Python, nie w praktyce. Nie wiem co za piękny umysł to wymyślił i w imię czego…

Porządki z telefonem

Nie przepadam za smartfonami do dzwonienia. Zdecydowanie lepiej w tej roli sprawdza się wg mnie dumbphone typu Nokia 3110c (z dostępem do netu od biedy, zresztą). No ale koniec końców trzeba było po parunastu latach zmigrować – tu operatorzy powinni się zastanowić nad tworzeniem grafów powiązań userów i co oznacza naprawdę przeniesienie danego numeru do innej sieci. W każdym razie wylądowałem w Virgin Mobile. Przy tej okazji ściągawka wybranych krótkich kodów w Virgin Mobile. Z fajnych rzeczy – mają pakiety Freemium, które nieźle nadają się do nawigacji samochodowej (300MB internetu) i pozwalają bez stresu sprawdzić w praktyce zasięg, jakość rozmów itp. Znaczy przynajmniej kiedyś, nie wiem jak to wygląda teraz, jak jest obowiązek rejestracji kart SIM…

W każdym razie największym wyzwaniem okazała się synchronizacja kontaktów. Coś miałem w starej Nokii na telefonie, większość na karcie SIM, poza tym nowy telefon też zdążył dorobić się osobnej bazy kontaktów. Wpadłem na pomysł sczytania wszystkiego na komputer (od razu backup by się zrobił…), przejrzenia, posortowania i wczytania na telefon. Na szczęście nie bawiłem się w sczytywanie z Nokii 3110c, choć kiedyś to opisywałem, tylko stwierdziłem, że zrobię eksport do pliku, następnie przełożę kartę SIM i zrobię kolejny eksport. Trochę z dmuchaniem na zimne, bo jeszcze musiałem skopiować kontakty z telefonu na kartę, a pewności nie miałem, czy telefon realizuje to przez złączenie, czy nadpisanie.

Przy okazji – nie wiem kto projektował eksport kontaktów na kartę w Androidzie, ale… skopał. Znacznie prościej wysłać mailem, niż zapisywać na kartę, bo eksport następuje – jak informuje telefon – do uroczo intuicyjnej lokalizacji /mnt/sdcard/System/PIM/PIM00001.vcf. Nielinuksiarzy pewnie wystraszy już pewnie /mnt, a po przełożeniu karty do komputera można się lekko naszukać. No bo po co zrobić ten eksport w głównym katalogu karty SD… U mnie skończyło się kolejnym eksportem, żeby doczytać komunikat o lokalizacji.

Okazało się, że kontakty zarówno na Nokii, jak i Androidzie są łączone, ale… powtarzające się kontakty tworzą duplikaty. Nawet jeśli są identyczne. Bardzo user friendly. W każdym razie zerknąłem na strukturę pliku z eksportem z Androida (vCard) i stwierdziłem, że szybciej będzie mi zrobić skrypt, który usunie duplikaty, niż szukać czegoś, co się tym zajmie. I tak powstał vCardUniq.

Skrypt robi tylko jedną rzecz – czyta ze STDIN vcardy, eliminuje identyczne (muszą być obecne i zgadzać się wszystkie dane, by były identyczne) i wypluwa na STDOUT wynik, który można wczytać do telefonu. Może się komuś przyda…

Aero2 – powiadamianie o konieczności wpisania CAPTCHA

Kolejny wyjazd na urlop i znowu dostęp do internetu sponsoruje Aero2. Oczywiście w wariancie z kompresowanym tunelem i proxy cache’ującym. Pewnie gdyby nie to rozwiązanie, to po prostu kupiłbym pakiet w Aero2, bo są naprawdę tanie, a jak testowałem przy okazji awarii netu u mojego ISP – śmiga to bardzo dobrze. Tak czy inaczej, gołe Aero2 jest nieprzyzwoicie wolne do WWW, po włączeniu ww. proxy śmiga na tyle dobrze, że stwierdziłem, że nie ma sensu kupować, tym bardziej, że nie pamiętam, czy aktywują od razu itp., a po włączeniu rozwiązania z tunelem wszystko działało. Przy czym najwięcej czasu przy włączaniu zajęło odszukanie wpisu z opisem.

W związku z użyciem ww. proxy WWW pojawia się jeden problem: nie działa przekierowanie i podstawowa przeglądarka nie wyświetla w takiej konfiguracji pytania o captchę. Zresztą, nawet gdyby przekierowanie działało, to mało ono pomaga przy czynnym korzystaniu z internetu, tj. nie przy biernym przeglądaniu, ale np. podczas pisania komentarza na jakiegoś bloga. Co prawda dzięki dodatkowi Lazarus do przeglądarki (polecam!) treść komentarza nie zginie nawet jeśli funkcja cofnij w przeglądarce nie działa i nastąpi przekierowanie, ale postanowiłem sobie sprawę ułatwić, przez napisanie prostego skryptu w Perlu, który sprawdzi dostępność zdefiniowanych hostów, a przy braku dostępności zadanej ilości wyświetli wyskakujące powiadomienie (xmessage). Przy czym sprawdza dość często (co 15 sekund), a jak brak łączności, to przerwa jest dłuższa.

Wyszło trochę ciekawiej, niż się spodziewałem. Wiadomo, że mocną stroną Perla są moduły, więc postanowiłem oprzeć się na dedykowanym module. Po pierwsze, okazało się, że Net::Ping domyślnie korzysta z TCP, nie ICMP, którego planowałem użyć, ale wydało się nawet lepsze. Niestety tylko do czasu, gdy okazało się, że przy podaniu hostów w formie domen i sprawdzaniu portu 80, za sprawą mechanizmu przekierowania Aero2 strona nadal jest dostępna. Tyle, że jest to strona mówiąca o konieczności wpisania captcha.

Rozwiązania są trzy. Pierwsze, to sprawdzanie zawartości strony, tj. czy nie pojawił się tekst mówiący o konieczności wpisania kodu captcha. Po pierwsze komplikuje to budowę skryptu, po drugie, zmniejsza jego uniwersalność (będzie działał tylko dla Aero2), po trzecie, możliwe, że przestanie działać przy jakiejś zmianie komunikatu. Drugie rozwiązanie, to podanie IP zamiast nazw domenowych. Przy takim rozwiązaniu przekierowanie dokonywane przez Aero2 nie będzie miało wpływu. Mniej czytelne i… zwyczajnie nie wpadłem w pierwszej chwili.

Zamiast tego postanowiłem skorzystać z wersji najoczywistszej i pierwotnie zamierzonej: wykorzystać jednak ICMP do sprawdzania osiągalności hostów. I tu największa niespodzianka: Net::Ping (ogólnie Perl) do wykorzystania ICMP wymaga uprawnień roota. Zdziwiłem się, ale po prostu tak jest i nie jest to feature Perla, a systemu – zwykli użytkownicy nie mają dostępu do tworzenia socketów. Z tego co znalazłem w sieci, polecane/najprostsze rozwiązanie na obejście tego to… wykorzystanie systemowego polecenia ping, do którego zwykle użytkownicy mają dostęp (SUID). Tak też uczyniłem.

Efekty można zobaczyć na mojej ulubionej sieci społecznościowej (hrhrhr), czyli w repo aero2-watch na GitHubie. Grupa potencjalnych użytkowników bardzo wąska (Linux + Aero2), ale może się komuś przyda…

Gdyby ktoś się zastanawiał, czemu klepię skrypty/siedzę na necie na urlopie to: lubię i zawsze to robię, poza tym, do porannej kawy jak znalazł; robię też inne, typowo urlopowe rzeczy; napisanie ~50 linii w Perlu trwa znacznie krócej, niż napisanie tego wpisu.

Automatyczne pobieranie kontaktu abuse dla domeny lub adresu IP

Zawsze miałem problem z szukaniem właściwego kontaktu abuse. No może problem to za dużo powiedziane, ale szukanie ręcznie, w hurtowych ilościach to nie jest nic ciekawego. Poza tym, jeśli chcemy zgłaszać automatycznie, to szukanie ręcznie odpada. A w danych whois były cuda, więc parsowanie tego byłoby wyzwaniem… Stosunkowo niedawno RIPE zrobiło jako taki porządek i pojawiły się pola abuse-c, ale już wcześniej znalazłem abusix i ich projekt Abuse Contact DB. Pozwala na wygodne odpytywanie o kontakty abuse przy pomocy DNS, więc szybko, prosto i wygodnie.

Trochę, żeby ułatwić życie kolegom, a trochę, żeby automatycznie zgłaszać nadużycia (np. próby włamań po SSH) ze swoich hostów, popełniłem funkcję w Perlu[1], która zwraca pierwszy email z listy, na podstawie ww. bazy. W międzyczasie zająłem się czym innym, znalazłem serwis, który rozwiązał temat automatycznego raportowania prób włamania. Temat więc trochę umarł. Przynajmniej do wczoraj/przedwczoraj, kiedy znalazłem ten wpis i dowiedziałem się, że najprawdopodobniej nikt nie powiadomił firm hostujących, plus zwykła ciekawość: a gdzie te skompromitowane hosty leżą? Z potrzeby chwili i własnej ciekawości skleciłem skrypt, który bierze domenę (czyli adres strony), sprawdza jego IP (dokładniej: rekord A) i ustala stosowny adres email do kontaktu z abuse.

Wynik działania dla domen .pl jest tu, a wynik działania dla całej listy tu. Skrypt jest zdecydowanie do poprawienia i rozwoju: w tej chwili nie zwraca nic przy braku kompletu danych, czyli brak obsługi błędów, jest wolny, bo działa sekwencyjnie, nie jest to czysty Perl, nie obsługuje IP (ani IPv6 czyli rekordów AAAA), grupowania domen/IP po kontakcie abuse (żeby nie słać wielu maili na ten sam adres) i wysyłki maili, ale leci na GitHuba. W ramach motywatora. 😉 Może kiedyś przyda się komuś, kto znajdzie jakiś malware…

TIL: istnieje oficjalne narzędzie w Pythonie, obsługujące bazę danych abuse; działa zarówno dla IPv4 jak i IPv6 (ale nie obsługuje domen). Generalnie robi to, co moja pierwotna funkcja w Perlu, tylko trochę lepiej. Mam wrażenie, że jak wtedy patrzyłem na tę stronę, to go nie było…

PS Z różnych źródeł wiem, że większe polskie hostingi są już powiadomione, nie ma potrzeby wysyłania maili. 😉 Warto natomiast zobaczyć, czy nie ma na liście strony własnej/znajomych – problem leży tak naprawdę po stronie użytkownika hostingu i  jego niezaktualizowanej aplikacji, więc tylko on może go tak naprawdę rozwiązać.

[1] Teraz widzę, że funkcja nie jest w czystym Perlu, tylko wywołuje zewnętrzny program host, poprawię wkrótce.

Tłumaczenia

Ponieważ tłumaczenia są jedną z form pomocy wolnemu oprogramowaniu (i okolicom), dostępną nawet ludziom średnio się znającym na samym programowaniu, to jakiś czas temu zacząłem udzielać się przy tłumaczeniach. Nie ukrywam – sporo czytam, trochę piszę, a część tłumaczeń przyprawiała o zgrzytanie zębów. Nie żebym był zadowolony z własnych, ale…

Początkowo był to PDDP rozkręcony IIRC przez Fenia. Niewiele pamietam, poza tym, że było i coś tam się otarłem. Potem zdryfowałem bardzie w kierunku meta i ideologii, czyli tekstów na gnu.org. Zaczęliśmy sporą grupą, ale szybko wykruszyło się do paru osób. Niedługo później zapał zgasł, zostało nas paru niedobitków. I jakoś tak się ciągnęło, aż zupełnie umarło – ostatnia wymiana maili z rok temu, ostatni commit pewnie z dwa lata temu…

W międzyczasie jakieś luźne, nieregularne i anonimowe tłumaczenia w ramach Debian Description Translation Project, bo dotarło do mnie, że jak ktoś nie zna języka angielskiego, to z Linuksem słabo sobie poradzi, więc tłumaczenie wszystkiego nie ma sensu. Za to opisów pakietów – jak najbardziej.

Tłumaczenie było całkiem przyjemnym doświadczeniem. Zalet jest sporo: uważna lektura tekstów źródłowych, większa ilość czytanych artykułów, kontakt z językiem i jego szlifowanie. Poza tym, ma się trochę do czynienia z systemami kontroli wersji, narzędziami, formatami i procedurami ułatwiającymi tłumaczenia, co przydaje się później przy różnych okazjach, od programowania, przez adminkę i projektowanie rozwiązań IT.

Jest to też okazja do zaobserwowania pewnych archaizmów i formalizmów w praktyce. Na przykład tłumacze GNU używają jako systemu kontroli wersji CVS. Nie żeby nie wystarczał, ale jednak Git jest wygodniejszy i lepszy. NIH? Przyzwyczajenie?

Z kolei inni nie korzystają z plików PO/POT (poedit FTW!), tylko stosują własne formaty/rozwiązania i tłumaczą na żywca HTML. Cóż, można i tak (nie żebym lubił, ale da się).

Wpis wyniknął z tego, że znalazłem (w końcu!) fajny opis pewnego zagadnienia związanego z Perlem, zobaczyłem, że stronę można tłumaczyć, a nie ma wersji polskiej… Spodobał mi się samouczek Perla i uznałem, że przyda się ludziom i… zacząłem tłumaczyć. Repo jest na GitHubie, można forkować i podsyłać pull requesty. AKA zachęcam.

Tak, mam świadomość, że strona nie jest zupełnie niekomercyjna. Jakoś mi to nie przeszkadza. Dość zwarta, nieźle napisana, tłumaczyć zamierzam tylko część dostępną dla wszystkich. Planów żadnych nie ma, raczej – jak zapowiedziałem autorowi – best effort. Niemniej, z różnych względów tempo ostatnio siadło, więc wpis ma być motywatorem. Nie żebym liczył, że zadziała, za dobrze się znam.

Inne: odkryłem GitHub na nowo, w sumie bardzo social network, tylko w troszkę innej kulturze. Odkryłem też na nowo/systematyzuję Perla. Zupełnie niezwiązane: zauważyłem, że próbuję za dużo srok za ogon łapać. To się nie może udać, ale ponieważ to tylko hobby, a nie praca, to nic się nie stanie, jak ten czy inny projekt zahibernuje na jakiś czas, czy wręcz totalnie zdechnie.

Wattmeter – nowy projecik

Dawno temu kupiłem sobie watomierz. Wykonałem też pracowicie kilkanaście pomiarów energii, różnych urządzeń w różnych konfiguracjach, których wyniki wylądowały w pliku na dysku i… nikomu się nie przydają. Od dawna chciałem podzielić się wynikami, tym bardziej, że są ciekawe i przynajmniej zastanawiające.

Z drugiej strony kupiłem sobie domenę i… nic na niej nie było uruchomionego. No i od dawna chciałem pobawić się statycznym generatorem bloga (jednym z bardzo wielu), czyli Chronicle. Najbardziej przeszkadzały mi dwie rzeczy: brak sensownych, gotowych szablonów i brak możliwości komentowania.

Odpaliłem as is, szablon tylko minimalnie zmodyfikowany i na pewno będzie wymagał poprawek. Komentowanie niby jest w nowej wersji Chronicle, ale uruchomiłem też w bardzo okrojonej i minimalnej wersji starej. Pewnie będę musiał poeksperymentować albo i pogrzebać w kodzie, chwilowo nie mam ochoty (bardziej niż czasu). Chyba przez ten upał.

Język angielski z paru powodów. Po pierwsze, Chronicle słabo wspiera polski, po drugie, przyda się większemu gronu, po trzecie, raczej zrozumiałe jest. Po czwarte, trochę poćwiczę angielski (są błędy i źle mi się czyta moje stare teksty, ale zwykle nie poprawiam, bo w mało uczęszczanym miejscu).

Zabawna obserwacja: bardzo fajnie pisze mi się w czystym HTML. Składanie bloga z szablonów (których są cztery sztuki: index, czyli główna strona, entry, czyli pojedynczy wpis, month, czyli widok miesiąca oraz tags, dla pojedynczego tagu) i bardzo prostych – póki co – CSS też mi się podoba. Mocno przypomina Joggera, którego niedawno użyłem i wydał mi się strasznym ogórem, ale… ma to swój urok. Główne zalety Chronicle to 100% kontroli i szybkość działania strony (w końcu statyczna…).

Druga obserwacja, niezupełnie związana z tym projektem, ale związana z Google, Blogspot, WordPress i ogólnie blogami: czym tak naprawdę jest blog? Blog to zbiór stron z atrybutami author, date, title, body, comments (comment author, comment date). Pewnie jeszcze tags.

To nie jest wersja docelowa, to się będzie zmieniało, ale już teraz prezentuję projekcik ile to zużywa energii, czyli watomierz w akcji. Sugestie i uwagi tradycyjnie mile widziane. Wiem, wiem, nie wszystkie widoki się walidują.

PUM działa

Doprowadziłem PUMa do takiej postaci, że daje się używać i generuje w miarę strawny i używalny HTML. Przykładowy wynik działania. Oczywiście wszystko jest na GitHubie, który mnie drażni ostatnio, bo pisze (w związku z zupełnie innym projektem, notka leży w szkicach, których coraz więcej, upał taki, że nawet pisać się nie chce), że Can’t automatically merge. Don’t worry, you can still create the pull request. No niby mogę, ale autor upstreamu umiarkowanie nalega na wyprostowanie (się nie dziwię), a ja szczerze mówiąc nie widzę, co mu przeszkadza w automatycznym merge. Pewnie jakbym wiedział, to łatwiej byłoby mi pomóc gitowi ogarnąć się… W każdym razie będę doszkalał się z gita.

Wynikami nie ma się co sugerować zbytnio – sporo hostów zostało dodanych bardzo niedawno, stąd 100%. Jest też rozbieżność pomiędzy wynikami dla All time i jednego roku. Nie bug w skrypcie, tylko tak zwraca dane polecany niedawno Uptime Robot. Zgłosiłem buga i (szybka!) odpowiedź trochę martwi:

The Free Plan can return uptime ratios back to 1 month due to the limit of the logs kept. The Pro Plan supports back to 1 year.

And, the alltimeuptimeratio variable in the API currently returns 1-month uptime (and it’ll be removed from the APIv2).

Mój nos mówi mi, że idzie monetyzacja i z fajnej, darmowej usługi może być wkrótce coś niezbyt fajnego/używalnego. Ale może to tylko moje czarnowidztwo.

Poza tym, po niedawnej awarii (jak ktoś nie zna serwisu downdetector.pl do określania, czy jest awaria u dostawcy, to dość entuzjastycznie polecam) u mojego ISP wylądowałem za NAT (jak wielu innych abonentów). Po telefonie przywrócony publiczny IP, ale od tego czasu dla hosta w domu Uptime Robot pokazuje dziwne rzeczy – host znika, pojawia się, znowu znika… Podejrzewałem jakiś autosuspend w momencie, gdy żadne urządzenie nie jest aktywne, ale raczej nie o to chodzi. IP się nie zmienia, więc nawet w przypadku problemów z odświeżaniem dyndns nie powinno rzutować (ale nie wykluczę…). Problemy z routingiem? Może się zbiorę, ustalę IP z którego Uptime Robot monitoruje i zdiagnozuję… Póki co po prostu pauza, aby się śmieci nie generowały.

UPDATE Odnośnie problemów z git – stupid me, czyli niewiedza w temacie gita i podchodzenie do problemu od zadniej strony. Swoją drogą, namierzenie/szukanie rozwiązaniach po objawach mogłoby trwać długo… Przyczyna to złe forkowanie. Na szczęście GitHub ma świetną pomoc. Robienie forka repo git, następnie synchronizacja forka i wszystko działa.

Urlop

No i urlop się kończy, więc można podsumować. Znowu nad morzem (Bałtyk). To znowu to stwierdzenie faktu, nie oznaka nudy. Doceniłem, że jeździmy na ubocze i w sumie poza sezonem. Wszystko za sprawą jednodniowego wypadu do Międzyzdrojów. Zaczęło się od żubrów, które jak co roku odwiedzamy. Mieliśmy pójść na molo, ale zaskoczył nas deszcz, więc innego dnia zrobiliśmy powtórkę.

Ilość „atrakcji” przytłacza i przygnębia. Podobnie jak ilość ludzi. Spędy wszędzie, ruszyć się nie można (zwł. jak się jest dzieckiem), a to jeszcze nie sezon. Wycieczki starców i dzieci, porykiwania wychowawców. Ja rozumiem, że nie było tego dnia idealnej pogody na plażę, ale za taki „wypoczynek” to ja dziękuję. Niemniej, molo fajne i zdecydowanie warto. Hint: masa płatnych parkingów i strefa koło plaży, ale jak ktoś ma ochotę na dziesięciominutowy spacer, to znajdzie i darmowe parkingi – wystarczy kierować się w stronę „od morza” (ot, wyszedł ze mnie Poznaniak).

Są też i lepsze – na oko – atrakcje, dzieciaki pewnie by szalały, ale po pierwsze, były już nieco padnięte, po drugie, nie przyjechaliśmy do Międzyzdrojów na dłużej, a raptem na jeden dzień, więc nie trzeba było się posiłkować atrakcjami a’la wesołe miasteczko. Poza tym, namioty czy tam pawilony handlowe. Ale jestem niemal pewny, że księgarnia z książkami „od 1 zł”, gdzie zrobiliśmy większe zakupy książkowe to był namiot handlowy, nie pawilon, po prostu. W każdym razie Międzyzdroje zaliczone, na parę lat starczy. 😉

Skoro już przy książkach jesteśmy – trochę „poczytałem”. Cudzysłów, bo nie tylko tradycyjne lektury, w końcu przekonałem się bardziej do audiobooków. I uznałem, że będę je traktował na równi z książkami (czyli będą tak samo oceniane). Miałem wątpliwości, bo i „czytam” inaczej (np. tramwaj czy pociąg), i raczej tematyka inna, i lektor potrafi wpłynąć na odbiór, ale w sumie uznałem, że nie ma co na siłę robić rozróżnienia, skoro to czytana książka. Trochę nadrobiłem czytelnictwo na urlopie.

Ciekawą obserwacją są też ceny atrakcji. Np. gofrów. W Dziwnówku IIRC 2,5 zł za gofra gołego lub z cukrem pudrem. Z bitą śmietaną – 7 zł. Międzyzdroje – standardowo goły 3,5 zł, cukier puder podnosi cenę do 4 zł. Bita śmietana to nadal 7 zł. I więcej. Wersje na wypasie – 10 zł i więcej. Trochę dużo jak za – nie ukrywajmy – bardziej odpowiednik ciastka, niż posiłku.

No, ale większość czasu siedzieliśmy w ciszy, spokoju i odosobnieniu. Pusta plaża, te klimaty. W końcu się zebrałem i zacząłem trochę biegać. Nieopodal szlak biegowy, więc jakoś skusiło AKA zmotywowało. Zresztą był taki plan, nawet buty wziąłem. Już drugiego dnia odkryłem wiązanie z tzw. heel lock, czyli do czego jest dodatkowa dziurka w bucie. Nie wiem, czy coś daje, ale nie wadzi w niczym i jest OK, więc będę używał.

Oczywiście bieganie bez GPS się nie liczy (się nabijam, oczywiście; wiem, że to choroba i się, bo zawsze biegałem po prostu dla przyjemności biegania, ale się skusiłem…), więc telefon w garść, soft do zapamiętywania trasy włączony i bieg. Z pozytywów – pobawiłem się Perlem, GPS i skryptami. Jest szansa, że powstanie coś wolnego/otwartego do wrzucania wyników na stronkę w strawnej formie.

Poza tym, znalazłem rozwiązanie jednego drobiazgu, który mnie męczył w Perlu, co oznacza, że może niedługo światło dzienne ujrzy jeszcze jeden projekcik. Trochę rozwinąłem mojego Perl Uptime Monitor – umie wygenerować bardzo podstawowy HTML. Z największych okołoperlowych rzeczy – wróciłem do tłumaczeń. Tym razem nie GNU, tylko właśnie niezły- jak mi się wydaje – serwis o Perlu. Chwilowo się nie chwalę (choć jak ktoś poszuka, to znajdzie, co robię). Mam postanowienie wrzucania więcej na GitHub.

Ogólnie – brakowało mi urlopu. Klasyczne oderwanie i podładowanie baterii. Pora wrócić do pracy.

PUM

Jakiś czas temu zacząłem korzystać z Uptime Monitor. Przyznaję, że jestem zadowolony, do pełni szczęścia brakowało mi czegoś, co wystawi moje uptime’y na WWW. Tzn. jest sporo fajnych narzędzi, rysujących ładnie i live, tzn. z autoodświeżaniem, ale… nie byłem przekonany do pomysłu publikacji kluczy API. Tym bardziej, że w niektórych przypadkach udostępnienie klucza wiąże się z z podaniem danych hosta, loginu i hasła do htpasswd itp.

Wolałbym mieć możliwość ukrycia nazwy/IP i ogólnie nie podawania zbyt wielu informacji, zwł. klucza API. Zauważyłem też, że nie ma (a przynajmniej nie znalazłem) nic do obsługi Uptime Monitora w Perlu. Stwierdziłem, że generowanie statycznego HTML (docelowo) z crona jest zupełnie wystarczające, a ew. autoodświeżanie prosto można załatwić JSem czy IIRC nawet polem META w HTML (koła nie odkrywam, „konkurencja” też tak robi.

I w ten sposób powstał PUM czyli Perl Uptime Monitor. 😉 Jest możliwość nadpisania nazwy, jest możliwość generowania uptime dla danego okresu (ilość dni wstecz). Brakuje opakowania wyniku w HTML (wyniki na STDOUT póki co…), ale to wkrótce… W sumie nie ma problemu z pobraniem danych do wykresu czasu odpowiedz, ale nie planuję póki co. Zachęcam do forkowania i zgłaszania pull requestów, ew. pomysłów w komentarzach.

All your GSM numbers are belong to us!

Zaczęło się od wpisu Montera o skopanej wysyłce MMS do wielu osób. Long story short: jeśli wiadomość MMS jest wysyłana do kilku osób, to odbiorcy widzą wszystkie numery, na które została wysłana. Analogicznie jak przy wielu odbiorcach w polu To lub Cc w przypadku email (zamiast Bcc).

Telefon komórkowy

Źródło: http://www.publicdomainpictures.net/view-image.php?image=692

Moja teza jest jednak taka, że zjawisko, choć złe, nie jest aż tak tragiczne, na jakie wygląda. Odbiorca dostaje co prawda listę numerów z książki adresowej, ale nie wie do kogo należą i czy w ogóle działają. Może jedynie porównać tę listę ze znanymi sobie numerami i ustalić, jakich mają wspólnych znajomych. Albo zrobić brute force i dzwonić wszędzie (hell yeah, automaty tak robią podobno…).

Całe zdarzenie jest dla mnie porównywalne z listą PINów wszystkich ludzi na świecie (tak, wasz też tam jest, mój zresztą też), jeśli chodzi o naruszenie prywatności czy bezpieczeństwa. Postanowiłem więc zrobić listę wszystkich polskich numerów komórkowych. W trakcie tworzenia, już po pierwszym prefiksie zwątpiłem – plik miał około 100 MB surowych danych, do tego tagi HTML…

Zatem zamiast ryby – wędka i zestaw DIY do stworzenia listy wszystkich polskich numerów GSM. Na podstawie listy polskich prefiksów GSM przypisanych operatorom i odrobiny magii w Perlu, każdy może sobie wygenerować taką listę.

Blox nie lubi nawiasów ostrych, więc wklejka na zewnętrznym serwisie:

Całość działa tak długo, dopóki Wikipedia nie zmieni formatu publikowania artykułów. Klepnięte na kolanie, nieoptymalizowane w żaden sposób. U mnie wygenerowanie wszystkich numerów ww. skryptem trwa od dwóch do czterech minut. Have fun!

PS Wygląda, że w Polsce może być 110300000 numerów telefonów komórkowych. Nie odliczam niewykorzystanych prefiksów itp.

Testowanie szybkości kluczy Zabbix agenta

Było tak, że jeden z kluczy w Zabbiksie działał wolno. Nawet: bardzo wolno. Ile czasu może się wykonywać proste sprawdzenie wersji programu typu chef-client -v, nawet na umiarkowanie dobitym systemie? Zainteresowani znajdą odpowiedź na końcu wpisu[1], dość powiedzieć, że czasami załączał się timeout po stronie zabbix agent. Problem został rozwiązany w sposób najdoskonalszy, czyli poprzez zrzucanie wartości z crona do pliku, i czytanie jej z pliku, ale niesmak pozostał. Poza niesmakiem, pozostało pytanie które jeszcze klucze są nieoptymalne?

Ponieważ na ten moment Zabbix nie daje możliwości sprawdzenia statystyk czasu zapytań dla poszczególnych kluczy, wykonałem małą protezę w postaci skryptu w Perlu, który odpyta danego hosta o wszystkie klucze kilka(naście) razy i policzy dla nich statystyki. Wklejka poniżej.

 

Skrypt przyjmuje dokładnie jeden parametr – hosta na którym będzie przeprowadzać test. Poza tym, wymaga wszystkich kluczy dla danego hosta, które ma testować, w pliku określonym w zmiennej $file. Na końcu wyświetli łączny czas wykonania zdefiniowanej ilości zapytań dla każdego klucza wyrażony w sekundach oraz sam klucz. Czytaj: pewnie chcesz przepuścić wynik przez sort -n. 😉

Parę rzeczy, które wyszły w trakcie pisania tego skryptu lub których się nauczyłem (w sumie gdyby nie one, to nie powstałby ten wpis):

Pętla sprawdzające N razy wszystkie klucze po kolei jest dokładniejsza od pętli, która sprawdza kolejno wszystkie klucze N razy każdy. Chodzi o rozkład obciążanie na maszynie, w tym drugim przypadku jest większa szansa, że któryś klucz trafi w nietypowe obciążenie maszyny.

Dokumentacja do modułu Time::HiRes jest… taka sobie. Można to zrobić prościej, jak wyżej. Początkowo kombinowałem ze sprintf oraz clock_gettime(CLOCK_REALTIME);

Może zastanawiać, skąd mnożenie przez 1000000. Otóż chodzi o bug z zapisem liczb zmiennoprzecinkowych (kojarzyłem to raczej z ośmiobitowców i dzielenia, nie wiem czy słusznie…):

perl -e '$a=1415907504.646884; $b=1415907504.603042; $d=$a-$b; print $d,$/'

vs.

perl -e '$a=1415907504.646884*1000000; $b=1415907504.603042*1000000; $d=($a-$b)/1000000; print $d,$/'

Że tak zacytuję real programmers use integer. 😉

Na koniec niezła wiadomość: jest szansa, że w przyszłości Zabbix będzie miał coś w stylu MySQLowego slowloga, czyli nie będzie trzeba robić testów na poszczególnych hostach, tylko będzie wbudowane narzędzie do wykrywania wolnych zapytań. Można głosować na ten feature. 😉

Specjalne podziękowania za uwagi i wyjaśnienia dla Tona z #perl @ IRCnet (thanks Ton!).

I wracając do pytania o nieoptymalne klucze z początku wpisu – tylko nieszczęsny chef-client okazał się być czarną owcą. Pozostałe klucze, choć czasem wymagają uruchomienia Perla lub kilku poleceń w Bashu, wykonywały się w zdecydowanie przyzwoitym czasie, grubo poniżej sekundy.

[1] Wykonuje się nawet cbanq cvęganśpvr frxhaq (rot13)! Bo na tyle ustawiony był timeout…

Smssender 0.9

Odezwał się użytkownik (ha! ktoś jednak tego używa! ;-)), że Mobitex przestał działać i zwraca status 104. Z racji niezbyt wczesnej pory lub po prostu zmęczenia[1], poszukałem pomocy nie u tego dostawcy, co trzeba. Ale albo statusy są zbieżne, albo dobry człowiek sprawdził we właściwej dokumentacji. Status 104, czyli brak zdefiniowanego From. Faktycznie, nie obsługiwałem tego. Tzn. była sobie zmienna w skrypcie, którą można było w skrypcie wyedytować. Niezbyt to piękne, więc w wersji 0.9 dodałem obsługę From w pliku konfiguracyjnym.

[1] Ślady zmęczenia widoczne w githubie, tak to jest jak się siada wieczorem do skryptu nietykanego od ponad roku.