Monitor nie wybudza się z uśpienia

Pracuję na laptopie Dell Latitude E5450 z replikatorem portów Dell Advanced E-Port II oraz z dwoma monitorami Dell U2515H podłączonymi przez DisplayPort. Na co dzień taki zestaw spisuje się dobrze, ale przez długi czas trapiła mnie uciążliwa usterka. Mianowicie po zablokowaniu/uśpieniu laptopa, co powoduje wygaszenie wszystkich ekranów, a następnie odblokowaniu/wybudzeniu dodatkowe monitory pozostawały wygaszone. W systemie były widoczne, w ustawieniach ekranu były na swoich miejscach, ale nie wyświetlały obrazu.

Próbowałem różnych rozwiązań: połączenia przez HDMI, użycia sterowników NVidii zamiast nouveau, ale okazały się nieskuteczne. Doraźnym rozwiązaniem była zmiana rozdzielczości obrazu albo wzajemnego położenia ekranów.

Skuteczne rozwiązanie podpowiedział mi kolega z pracy. Jest nim przestawienie w menu monitora na użycie DisplayPort 1.2. Po wykonaniu tej operacji od kilku dni problem nie występuje.

Przed wykonaniem tej operacji należy upewnić się, że sprzęt i system obsługują DisplayPort. Kolega, który pracuje na identycznym zestawie, za moją radą przestawił monitor na DisplayPort 1.2 i monitor przestał wyświetlać obraz, w OSD nawet nie można było wybrać menu, w którym jest opcja przestawienia wersji DisplayPort. Żeby to odkręcić musieliśmy podpiąć jego monitor pod mój komputer.

Migracja repozytorium SVN do git

Młodsi stażem programiści pewnie tego nie pamiętają, ale kiedyś synonimem systemu kontroli wersji był Subversion. W dziewięciu na dziesięć przypadków podczas rozmowy kwalifikacyjnej należało się wykazać znajomością SVN-a.

Z tamtych czasów zostało mi kilka projektów w SVN-ie. Większość z nich już od dawna nie funkcjonuje, ale kilka wciąż żyje, np. acp czy ta strona. Raz na ruski rok coś w nich poprawiam, choć ze wstydem przyznaję, że robiłem to wprost na serwerze, bo przy wymianie domowego serwerka parę lat temu już nawet nie stawiałem serwera Subversion. Teraz jednak postanowiłem zrobić z tym porządek i przenieść kod do gita.

Czytaj dalej Migracja repozytorium SVN do git

Ansible i cache buster

Pamięć podręczna przeglądarki może napsuć krwi programistom zajmującym się frontem. Wielokrotnie byłem świadkiem podobnych dialogów:
– Frontend developerze, mówiłeś, że to naprawiłeś, a nie działa.
– Naciśnij Control i F5.
– Aaa, OK.
Żeby wymusić na przeglądarce pobranie nowej wersji plików (JavaScriptów, arkuszy stylów) można do nazwy pliku dodać query string z wartością zmienianą razem plikami czyli tzw. cache buster, na przykład:

<link rel="stylesheet" type="text/css" href="compiled.css?v=1.23">

Mniej więcej tak robiliśmy w aplikacji, z którą obecnie dużo pracuję. Występujące w przykładzie 1.23 to była wersja aplikacji. Wartość ta była pobierana z pliku konfiguracyjnego. To rozwiązanie miało przynajmniej dwie wady:

  1. Na środowiska testowe często wydajemy wielokrotnie kolejne poprawki do tej samej wersji aplikacji, przez co cache buster nie działał.
  2. Zdarzało nam się zapomnieć podbić wersję w pliku konfiguracyjnym, przez co cache buster nie działał także na produkcji.

Ponieważ do wydań używamy ansible’a postanowiliśmy zautomatyzować generowanie wartości dla cache bustera.

W pierwszym podejściu chciałem użyć daty i czasu wykonania skryptu np. w formacie RRMMDDGGMMSS, ale to rozwiązanie nie za dobrze działa w wypadku, gdy wydanie jest robione dla podzbioru serwerów (tzw. rolling update). Czas uruchomienia skryptu jest inny dla każdej grupy serwerów.

Lepszym rozwiązaniem moim zdaniem jest użycie ID commitu z gita. Zalety tego podejścia to:

  1. Wartość będzie identyczna na każdym serwerze, niezależnie od tego w której serii serwer był aktualizowany.
  2. Wartość jest generowana automatycznie, więc odpada czynnik ludzko-zapominalski.
  3. Wartość jest inna po każdej zmianie kodu w repozytorium, więc będzie różna również dla każdej poprawki w ramach jednej wersji aplikacji.

W roli ansible’a można to ograć następująco:

- name: "Get git short commit ID"
  command: git rev-parse --short HEAD
  args:
    chdir: "/tmp/build-directory"
  register: git_revparse

W powyższym przykładzie wartość chdir to katalog, w którym mamy kod aplikacji z repozytorium git. Po wykonaniu tego kroku w
w zmiennej git_revparse.stdout będzie znajdować ID commitu, które można przekazać np. do szablonu pliku konfiguracyjnego.

Obecnie linki do skryptów i styli wyglądają mniej więcej tak:

<link rel="stylesheet" type="text/css" href="compiled.css?v=c109ad9">

Skype na Debianie

Swego czasu Skype na Linuksie (w tym na Debianie) był bardzo ułomny, dostępna była wyłącznie wersja 32-bitowa, a instalacja była upierdliwa. Między innymi dlatego starałem się unikać Skype’a.

Niedawno zostałem zmuszony do przeproszenia się ze Skype’em i ku memu zaskoczeniu okazało się, że Skype for Linux dojrzał. Ze strony można pobrać pakiet DEB, a instalacja sprowadza się do zwyczajowego:

dpkg -i /home/joe/Pobrane/skypeforlinux-64.deb

Instalator dodaje repozytorium do listy źródeł apta, ale nie pobiera klucza, więc po wykonaniu aptitude update pojawi się błąd:

W: Błąd GPG: https://repo.skype.com/deb stable InRelease: Następujące podpisy nie mogły zostać zweryfikowane z powodu braku klucza publicznego: NO_PUBKEY 1F3045A5DF7587C3
E: The repository 'https://repo.skype.com/deb stable InRelease' is not signed.
E: Failed to download some files
W: Nie udało się pobrać https://repo.skype.com/deb/dists/stable/InRelease: Następujące podpisy nie mogły zostać zweryfikowane z powodu braku klucza publicznego: NO_PUBKEY 1F3045A5DF7587C3
E: Nie udało się pobrać niektórych plików indeksu, zostały one zignorowane lub użyto ich starszej wersji.

Żeby go naprawić wystarczy pobrać klucz GPG:

curl https://repo.skype.com/data/SKYPE-GPG-KEY | apt-key add -

Sama aplikacja (w wersji 5.3.0.1) zdaje się działać poprawnie i stabilnie, niestety wciąż brakuje w niej niektórych funkcji, np. Udostępniania ekranu podczas rozmowy konferencyjnej.

Problem z aktualizacją widżetu Jakdojade

Jakdojade to jedna z najczęściej używanych przeze mnie aplikacji na telefonie. Na jednym ekranie mam dwa widżety z przystankami, z których najczęściej korzystam. Niestety po wymianie telefonu (Xiaomi Redmi 3S) godziny odjazdów w widżetach przestały być aktualizowane.

Czasami chwilowo pomagało otworzenie obserwowanych przystanków w aplikacji, ale po kilk lub kilkunastu godzinach dane znowu były nieaktualne. Myślałem, że to może być problem z uprawnieniami aplikacji do korzystania z transferu danych, jednak to był błędny trop.

Skuteczne rozwiązanie także było związane z uprawnieniami, ale do innej czynności, a mianowicie autostartu. Po dodaniu aplikacji Jakdojade do autostartu godziny odjazdów w widżetach są regularnie aktualizowane.

Konfigurowanie identyfikatora sesji w PHP

Rok temu pisałem o łączeniu staromodnej aplikacji z Laravelem. Po zmianach w konfiguracji środowiska PHP wypłynął nowy problem, a mianowicie Laravelowi nie podobały się identyfikatory sesji generowane przez starą aplikację, więc w ich miejsce generował nowe tym samym skutecznie niwecząc dzielenie sesji.

Identyfikatory generowane przez starą aplikację wyglądały np. tak: mh3e2fj757ed8nnlukqf5ag0f3. Tymczasem Laravel (konkretnie wersja 5.1) za jedynie słuszne uznaje identyfikatory składające się z 40 znaków (cyfry i litery od a do f). Takie zachowanie zdefiniowane jest w metodzie \Illuminate\Session\Store::isValid():

public function isValidId($id)
{
   return is_string($id) && preg_match('/^[a-f0-9]{40}$/', $id);
}

Rozwiązaniem tego problemu jest takie skonfigurowanie sesji PHP-owych, by identyfikatory spełniały wymagania Laravela 5.1:

ini_set('session.hash_function', 'sha1');
ini_set('session.hash_bits_per_character', '4');

Problem z repozytorium pakietów Opery

Przy próbie wykonania aktualizacji listy pakietów aptitude zakomunikował mi rzecz następującą:

E: The repository 'https://deb.opera.com/opera-stable stable Release' does no longer have a Release file.

Najwyraźniej w repozytorium Opery zaszły jakieś zmiany. Zajrzałem na adres repozytorium i faktycznie we wskazanym katalogu pliku Release nie było, ale za to w podkatalogu opera znajdowały się wszystkie niezbędne pliki. Wobec tego otworzyłem plik /etc/apt/sources.list.d/opera-stable.list i poniższą linijkę:

deb https://deb.opera.com/opera-stable/ stable non-free #Opera Browser (final releases)

zamieniłem na taką:

deb https://deb.opera.com/opera-stable/opera testing non-free

Po tym zabiegu aktualizacja przebiegła bez problemów.

Dodam, że korzystam z Debiana w wersji testing (obecnie stretch) i dlatego podałem taką dystrybucję.

PrestaShop 1.6 na PHP 7.0

Zgodnie z planem przenoszę kolejne strony na PHP 7.0. W ten weekend przyszła kolej na eduNagrody.pl, który to sklepik stoi na PrestaShop 1.6. Wedle autorów wersja 1.6.1.4 przynosi kompatybilność z PHP 7. Moja instalacja ma raptem kilka dodatkowych modułów, więc założyłem, że z przesiadką nie będzie problemów.

Podobnie jak w przypadku WordPressa, przyspieszenie generowania stron przez PrestaShop jest odczuwalne. Testy przez ab pokazują mniej więcej dwukrotnie lepsze wyniki.

PHP 5.6

Server Software:        nginx/1.8.1
Server Hostname:        edunagrody.pl
Server Port:            443
SSL/TLS Protocol:       TLSv1/SSLv3,ECDHE-RSA-AES256-GCM-SHA384,2048,256

Document Path:          /
Document Length:        76033 bytes

Concurrency Level:      4
Time taken for tests:   9.500 seconds
Complete requests:      100
Failed requests:        0
Write errors:           0
Total transferred:      7664764 bytes
HTML transferred:       7603300 bytes
Requests per second:    10.53 [#/sec] (mean)
Time per request:       379.995 [ms] (mean)
Time per request:       94.999 [ms] (mean, across all concurrent requests)
Transfer rate:          787.92 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:       38   63  15.1     64      93
Processing:   194  312  60.4    309     456
Waiting:      157  276  61.5    281     420
Total:        237  375  62.4    375     521

Percentage of the requests served within a certain time (ms)
  50%    375
  66%    402
  75%    415
  80%    428
  90%    457
  95%    500
  98%    520
  99%    521
 100%    521 (longest request)

PHP 7.0

Server Software:        nginx/1.8.1
Server Hostname:        edunagrody.pl
Server Port:            443
SSL/TLS Protocol:       TLSv1/SSLv3,ECDHE-RSA-AES256-GCM-SHA384,2048,256

Document Path:          /
Document Length:        76033 bytes

Concurrency Level:      4
Time taken for tests:   4.415 seconds
Complete requests:      100
Failed requests:        0
Write errors:           0
Total transferred:      7664708 bytes
HTML transferred:       7603300 bytes
Requests per second:    22.65 [#/sec] (mean)
Time per request:       176.616 [ms] (mean)
Time per request:       44.154 [ms] (mean, across all concurrent requests)
Transfer rate:          1695.22 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:       38   44   7.1     42      78
Processing:    79  130  36.0    129     278
Waiting:       54  100  37.2     98     253
Total:        119  175  36.1    171     328

Percentage of the requests served within a certain time (ms)
  50%    171
  66%    182
  75%    188
  80%    194
  90%    212
  95%    227
  98%    295
  99%    328
 100%    328 (longest request)

PHP 7.0 na blogasku

Postanowiłem dać szansę PHP 7.0 na serwerze produkcyjnym, a konkretnie na WordPressie napędzającym tegoż blogaska. W końcu od premiery minęło jakieś dwa i pół miesiąca, w tym czasie bolączki wieku dziecięcego chyba powinny zostać wyeliminowane. Co więcej, próby na moich testowych maszynach wirtualnych nie wykazały żadnych problemów, za to pokazały wyraźne przyspieszenie.

Przesiadka jest łatwa i w pełni odwracalna, PHP 7.0 z dotdeb może działać równolegle do PHP 5.6 od Debiana, zatem wystarczy w konfiguracji vhosta zmienić ścieżkę do interpretera. Różnica w prędkości generowania stron jest wyraźnie odczuwalna organoleptycznie, ale jeśli do kogoś bardziej przemawiają liczby to poniżej wrzucam szybki test wykonany ab.

PHP 5.6

Server Hostname:        michal.durys.pl
Server Port:            80

Document Path:          /
Document Length:        65737 bytes

Concurrency Level:      4
Time taken for tests:   16.142 seconds
Complete requests:      100
Failed requests:        0
Write errors:           0
Total transferred:      6594000 bytes
HTML transferred:       6573700 bytes
Requests per second:    6.20 [#/sec] (mean)
Time per request:       645.680 [ms] (mean)
Time per request:       161.420 [ms] (mean, across all concurrent requests)
Transfer rate:          398.93 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:       11   11   0.6     11      17
Processing:   281  630 143.4    627    1083
Waiting:      111  287  77.4    288     674
Total:        292  641 143.5    638    1094

Percentage of the requests served within a certain time (ms)
  50%    638
  66%    706
  75%    767
  80%    780
  90%    804
  95%    824
  98%    879
  99%   1094
 100%   1094 (longest request)

PHP 7.0

Server Software:        nginx/1.8.1
Server Hostname:        michal.durys.pl
Server Port:            80

Document Path:          /
Document Length:        65737 bytes

Concurrency Level:      4
Time taken for tests:   6.343 seconds
Complete requests:      100
Failed requests:        0
Write errors:           0
Total transferred:      6594000 bytes
HTML transferred:       6573700 bytes
Requests per second:    15.77 [#/sec] (mean)
Time per request:       253.721 [ms] (mean)
Time per request:       63.430 [ms] (mean, across all concurrent requests)
Transfer rate:          1015.20 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:       11   11   0.2     11      12
Processing:    63  241  92.4    219     557
Waiting:       34  123  45.1    109     206
Total:         74  252  92.3    230     568

Percentage of the requests served within a certain time (ms)
  50%    230
  66%    288
  75%    307
  80%    320
  90%    365
  95%    411
  98%    501
  99%    568
 100%    568 (longest request)

Tak na oko, przyspieszenie jest blisko dwu i półkrotne, wszystko działa, w logach czysto, więc wygląda to obiecująca. Jeśli w najbliższych dniach nie wystąpią problemy dam szansę siódemce z Piwikiem, PrestaShop i Roundcube’em.

Wyłączenie funkcji buforowania PrestaShop

PrestaShop posiada przydatny moduł pod tytułem „Aktualizacja 1 kliknięciem”. Aby takową aktualizację uruchomić należy spełnić kilka warunków.

Aktualizacja 1 kliknięciem

O ile przełączyć sklep w tryb konserwacji można z poziomu rzeczonej listy, o tyle sprawnie, że „Funkcje buforowania PrestaShop są wyłączone” nie jest takie oczywiste. PrestaShop ma kilka ustawień, które związane są z buforowaniem czy też pamięcią podręczną, a w polskim tłumaczeniu żadna z nich nie nazywa się „funkcje buforowania”. Żeby spełnić ten warunek należy udać się do menu Zaawansowane / Wydajność, a następnie zjechać na dół strony do panelu zatytułowanego Cache. Tam należy przestawić suwaczek „Użyj pamięci podręcznej” w pozycję „NIE”.

Użyj pamięci podręcznej