Ale ten czas szybko płynie. Dopiero co opisywałem Wam przepis na kompilację PHP 5.4 (2013), a za rogiem czeka już PHP 7.3.
Mimo upływu 5 lat dużo się nie zmieniło w samej konfiguracji kodu źródłowego i kompilacji. Podstawa to posiadanie w Linuksie gcc/g++ oraz pakietów -dev (głównie pliki nagłówkowe .h), dla rozszerzeń z których będziemy korzystać. Poniżej lista pakietów dla Debiana, które są przydatne:
1 |
apt-get install make gcc g++ libxml2-dev zlib1g-dev bzip2 libbz2-dev libcurl4-gnutls-dev libjpeg8-dev libpng-dev libfreetype6-dev libmcrypt-dev libmysqlclient-dev lemon libtidy-dev libxslt1-dev libpcre++-dev libssl-dev automake autoconf libsystemd-dev pkgconf |
Na pewno zapytacie po co to wszystko? W dawnych czasach nie wszystkie dodatki PHP były przygotowane w paczkach danej dystrybucji i po pewnym czasie trzeba było pobierać kod źródłowy, skonfigurować i skompilować i tak. Dlaczego nie zrobić tego od razu?
W tamtych czasach również kompilacja pomagała odpowiednio sprofilować PHP pod daną konfigurację (czy ktoś jeszcze korzysta z Gentoo?).
Obecnie główna przewaga takie podejścia, to posiadanie kilku różnych instanacji PHP w różnych wersjach na jednej maszynie (bo mamy różne projekty, różnych klientów etc). Jak również można sprofilować PHP pod konkretną jedną aplikację (prof-gen & prof-use).
Ja nadal zawsze kompilują PHP, wtedy w przypadku dysków HDD mamy ciut mniejsze obciążenia i większą swobodę działania. Jeśli już wykonałeś poprzedni krok wystarczy pobrać kod źródłowy wybranej przez nas wersji PHP (np. 7.2.12). Jeśli nie chcecie za każdym razie przeklikiwać się przez stronę https://php.net/downloads.php możecie użyć prostego skrypciku:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
#!/bin/bash if [ $# -eq 0 ]; then echo "Syntax : $0 php_version" echo "Example: $0 7.0.2" exit 1 fi VERSION=$1 SHORT=${VERSION%.*} SHORT=${SHORT//./} FILE="php-$VERSION.tar.gz" URL="http://pl1.php.net/get/$FILE/from/this/mirror" HTTP_CODE=`curl --silent --head --location --output /dev/null --write-out '%{http_code}' $URL` if [ $HTTP_CODE == 404 ] then echo "Cannot download php-$VERSION - not found." exit 1 fi wget $URL -O $FILE |
Wtedy gdy dostaniesz informację o nowej wersji wystarczy, że wydasz polecenie ./php_get 7.2.12. Jak już mamy paczkę .tar.gz na dysku musimy rozpakować źródła i w katalogu, który powstanie umieszczamy nasz przepis na kompilację.
Jak taki przepis wygląda? Wszystko zależy, z czego Wasze aplikacje PHP korzystają, a może jest to serwer, gdzie serwujecie rózne aplikacje i wymagacie różnych bibliotek. Mój uniwersalny przepis, z którego korzystam to:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
make distclean ./configure \ --enable-opcache \ --prefix /usr/local/php72 \ --enable-fpm \ --enable-cli \ --enable-inline-optimization \ --disable-rpath \ --disable-ipv6 \ --enable-mbstring \ --enable-mbregex \ --enable-zip \ --with-pdo-mysql=mysqlnd \ --with-mysqli=mysqlnd \ --with-gettext \ --with-curl \ --with-zlib \ --with-zlib-dir=/usr \ --with-gd \ --with-jpeg-dir=/usr \ --with-png-dir=/usr \ --with-freetype-dir \ --enable-exif \ --enable-shmop \ --with-xsl=shared \ --enable-soap=shared \ --enable-sockets \ --enable-pcntl=shared \ --with-bz2 \ --with-tidy \ --with-pcre-dir \ --with-openssl \ --with-imap-ssl \ --with-pear \ --enable-pcntl \ --with-fpm-systemd make -j2 make install |
Czasami różni się w zależności od potrzeb. W dużym skrócie – sprzątamy po poprzedniej kompilacji, konfiguruejmy nasz przepis oraz puszczamy machinę w ruch. Opcja -j2 oznacza, że kompilacja wykona się na 2 jobach. Potrwa to dobrych kilka minut.
I ostatecznie wszystko zainstaluje się zgodnie z przepisem, tj. w /usr/local/php72 (dzięki takiemu podejściu łatwo później posprzątać po poprzedniej wersji, np. php70).
Konfiguracja dla środowiska PHP jest czytana z lokalizacji /usr/local/php72/lib/php.ini (ja mam i tak w /etc/php72.ini, a we właściwym miejscu link symboliczny, ułatwia to tworzenie kopii zapasowych konfiguracj):
1 2 3 |
cp php-7.2.12/php.ini-production /etc/php72.ini ln -s /etc/php72.ini /usr/local/php72/etc/php.ini ln -s /usr/local/php72/etc/php.ini /usr/local/php72/lib/php.ini |
Początkowo tego pliku nie ma. Możemy go tam przenieść z kodów źródłowych ( php-7.2.12/php.ini-production). Nie jest to do końca optymalna konfiguracja, nie wiem dlaczego. Podstawowe zmiany, które powinniście zrobić to:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
;ustalemy odgórnie precyzje, używane m.in. dla json_encode serialize_precision = 17 ;nie chwalimy się wersją PHP expose_php = Off ;czytelniejszy format logów, i konkretna lokalizacja ;aby nie trzeba było szukać html_errors = Off error_log = /var/log/php72.log ;zwiększamy domyślny rozmiar pliku wgrywanego z POST post_max_size = 20M upload_max_filesize = 20M ;strefa czasowa najbardziej optymalna dla naszej aplikacji date.timezone = Europe/Warsaw ;konfigurujemy sposób wysyłania maili z mail() ;oraz dorzucamy osobne miejsce na logi sendmail_path = /usr/sbin/sendmail -t -i mail.add_x_header = On mail.log = /var/log/php-mail.log ;zakładam, że memcached macie już lokalnie zainstalowane ;jest to najwłaściwsza forma przechowywania sesji dla PHP ;oraz dodatkowe zabezpieczenia, które możecie pominąć session.save_handler = memcached session.save_path = "127.0.0.1:11211" session.cookie_lifetime = 604800 session.cookie_httponly = 1 session.gc_probability = 0 ;obecnie opcache jest domyślnie włączony, ale wolę mieć pewność ;dodatkowo zwiększam pamięć na źródła aplikacji ;(ZF,Symfony potrafią być ogromne) opcache.enable=1 opcache.enable_cli=1 opcache.memory_consumption=256 ;zwiększam ilość przechowywanych plików w opcache opcache.max_accelerated_files=50000 ;czas w sekundach co ile ma PHP sprawdzać plik na dysku ;czy przypadkiem nie jest w nowszej wersji ;produkcyjnie,przy 1 aplikacji można ustawić 0 (nigdy nie waliduj) opcache.revalidate_freq=120 opcache.fast_shutdown=1 opcache.validate_root=1 ;bardzo przydatne jest wskazanie miejsca certyfikowania w systemie curl.cainfo = /usr/lib/ssl/certs/ca-certificates.crt ;na koniec ładuje potrzebne mi rozszerzenia zend_extension=opcache.so extension=memcached.so |
W planach jest, aby w PHP 7.4 doszła opcja preload, która wstępnie załaduje wymagane biblioteki i frameworki do opcache. Dzięki temu pierwsze załadowanie strony przez Klienta będzie trwało równie krótko jak przy kolejnych odwiedzinach (bajtkod będzie już w pamięci serwera).
To co obecnie również potrzebujemy to wstępna konfiguracja PHP-FPM, który na dobre zadomowił się w PHP i obsługuje cały proces zarządzania procesami PHP (pięknie współgra z opcache). Kopiujemy plik i robimy odpowiednie wiązania symboliczne na przyszłość:
1 2 |
cp php-7.2.12/sapi/fpm/php-fpm.conf /etc/php-fpm72.conf ln -s /etc/php-fpm72.conf /usr/local/php72/etc/php-fpm.conf |
Domyślnie w pliku konfiguracyjnym php-fpm nie ma skonfigurowanego żadnego pool-a, jak również możemy rozbudować domyślną konfigurację. Ja zawsze bazuję na połączenia portowych. Nasz plik może przybrać taką postać:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
[global] pid = /usr/local/php72/var/run/php-fpm.pid error_log = /var/log/php72-fpm.log log_level = warning emergency_restart_threshold = 10 emergency_restart_interval = 1m process_control_timeout = 10s daemonize = yes rlimit_files = 1024 rlimit_core = 0 ;;;;;;;;;;;;;;;;;;;; ; Pool Definitions ; ;;;;;;;;;;;;;;;;;;;; [www] listen = 127.0.0.1:7200 listen.backlog = -1 listen.allowed_clients = 127.0.0.1 listen.owner = www-data listen.group = www-data listen.mode = 0666 user = www-data group = www-data pm = static pm.max_children = 5 pm.start_servers = 20 pm.min_spare_servers = 5 pm.max_spare_servers = 35 pm.max_requests = 500 request_terminate_timeout = 0s request_slowlog_timeout = 5s slowlog = /var/log/php72-slow.log catch_workers_output = yes |
Pozostaje nam już tylko kwestia podnoszenia (uruchamiania) PHP-FPM. Obecnie zamiast skryptów init.d używa się systemd. Zatem do dzieła:
1 2 3 4 |
cp php-7.2.12/sapi/fpm/php-fpm.service /lib/systemd/system/php-fpm72.service systemctl enable php-fpm72.service systemctl daemon-reload systemctl start php-fpm72 |
I od teraz możemy w naszym serwerze WWW (np. Apache lub nginx) korzystać z możliwości przetwarzania żądań PHP za pomocą portu 7200. Wystarczy w definicji naszego vhosta w nginx dodać następującą konfigurację dla plików z rozszerzeniem .php:
1 2 3 4 5 |
location ~ \.php$ { fastcgi_pass 127.0.0.1:7200; fastcgi_index index.php; include /etc/nginx/fastcgi_params; } |
Pamiętajcie, że ustawiliśmy rewalidację opcache na 120 sekund. W zależności od potrzeb (produkcja / dev) możemy ten czas dowolnie skonfigurować pod własne potrzeby. Opcache robi największą robotę w przyspieszeniu PHP 7 (a za nim przebudowa struktur danych w jądrze), więc warto poświęcić trochę czasu i dostosować powyższą konfigurację php.ini pod swoje potrzeby.