🐘

php7

13 notes  •  PHP & Web Dev

Install libapache2-mod-php on Ubuntu/Debian

The libapache2-mod-php package provides the Apache PHP module. If the module is missing or broken, reinstall it using the steps below. A CentOS/RHEL equivalent is also included.

Prerequisites

  • Ubuntu/Debian with Apache installed, or CentOS/RHEL with the Remi repository enabled
  • Root or sudo access

Steps — Ubuntu/Debian

If you see ERROR: Module php7.0 does not exist! when running a2enmod php7.0, purge and reinstall the package:

sudo apt purge libapache2-mod-php7.0 libapache2-mod-php
sudo apt install libapache2-mod-php7.0 libapache2-mod-php

Then enable the module and restart Apache:

sudo a2enmod php7.0
sudo systemctl restart apache2

Steps — CentOS/RHEL (Remi repo)

yum install php70-php

Verify

php --version
apache2ctl -M | grep php

Notes

  • Replace 7.0 with the PHP version you need (e.g. 7.4, 8.1).
  • On Ubuntu, only one libapache2-mod-php* version should be active at a time.

Fix PHP Code Displaying as Plain Text in Apache/Nginx

When Apache serves .php files as plain text instead of executing them, the PHP module is either missing or not enabled. A related symptom is a Fatal error: Class 'DOMDocument' not found error, which means the php-xml extension is absent.

Prerequisites

  • Apache web server with root or sudo access
  • Ubuntu/Debian package manager (apt)

Steps

1. Install the Apache PHP module:

sudo apt-get install libapache2-mod-php

2. If you see Class 'DOMDocument' not found, install the XML extension:

sudo apt install php-xml

3. Restart Apache:

sudo systemctl restart apache2

Verify

Create a test file and request it from a browser:

echo "

Navigate to http://your-server/test.php. You should see the PHP info page, not raw PHP code. Remove the file afterwards.

Notes

  • If using PHP-FPM instead of mod_php, ensure the proxy_fcgi module is enabled and the PHP-FPM socket/port is correctly configured in the virtual host.
  • After changing Apache modules, always restart Apache for the changes to take effect.

Install PHP APCu Backwards Compatibility Extension

The apcu_bc (APCu Backwards Compatibility) extension re-adds the legacy apc_*() function aliases removed in PHP 7.0+. It must be loaded after the apcu extension.

Prerequisites

  • PHP 7.0, 7.1, 7.2, or 7.3 installed
  • APCu extension already installed (required before apcu_bc)
  • Build tools: gcc, make, autoconf, libc-dev, pkg-config

Steps — ServerPilot-managed servers

In the commands below, replace 7.X with your PHP version (e.g. 7.0, 7.1).

sudo apt-get -y install gcc make autoconf libc-dev pkg-config
sudo pecl7.X-sp install apcu_bc

Create the extension config file and restart PHP-FPM:

sudo bash -c "echo extension=apc.so > /etc/php7.X-sp/conf.d/z_apc.ini"
sudo service php7.X-fpm-sp restart

The file is named z_apc.ini to guarantee it loads after apcu.ini.

Steps — standard Ubuntu/Debian

sudo apt-get install php-dev
sudo pecl install apcu_bc

Edit /etc/php/7.X/mods-available/apcu.ini and ensure the load order is:

extension=apcu.so
extension=apc.so

Then restart PHP-FPM or Apache.

Steps — CentOS/RHEL (IUS repo)

sudo yum install php71u-pecl-apcu php71u-pecl-apcu-bc

Verify

php7.X-sp -i | grep -i "APC Compatibility"

Expected output: APC Compatibility => 1.0.3

Uninstall

sudo rm /etc/phpX.Y-sp/conf.d/z_apc.ini
sudo peclX.Y-sp uninstall apcu_bc
sudo service phpX.Y-fpm-sp restart

Notes

  • apcu_bc is only relevant for PHP 7.0+. On PHP 5.5/5.6 use APCu directly; on PHP 5.4 use APC.
  • Load order is critical: apc.so must always come after apcu.so.

Manage Multiple PHP Versions with deb.sury.org (Ondrej PPA)

The ppa:ondrej/php PPA allows multiple PHP versions (5.6, 7.0, 7.1, etc.) to coexist on the same Ubuntu/Debian system. This guide covers installation, calling a specific version, and switching the system default.

Prerequisites

  • Ubuntu/Debian with apt
  • Ondrej PPA added: sudo add-apt-repository ppa:ondrej/php && sudo apt update

Install multiple PHP CLI versions

sudo apt install php5.6-cli php7.0-cli php7.1-cli

Call a specific version

Each installed version is available at /usr/bin/php<version>:

php7.1 --version
php7.0 --version
php5.6 --version

View available alternatives

update-alternatives --query php

This lists all registered PHP binaries and which one /usr/bin/php currently points to.

Switch the system default

sudo update-alternatives --set php /usr/bin/php7.0

To fully migrate all PHP-related binaries to 7.0:

sudo update-alternatives --set php       /usr/bin/php7.0
sudo update-alternatives --set php-config /usr/bin/php-config7.0
sudo update-alternatives --set phpdbg    /usr/bin/phpdbg7.0
sudo update-alternatives --set phpize    /usr/bin/phpize7.0

Verify

php --version

Notes

  • Switching the CLI default does not change the PHP version used by Apache or PHP-FPM — those are configured separately.
  • Use update-alternatives --config php for an interactive selection menu.

Fix PHP-FPM Not Writing to Error Log

By default, PHP-FPM may send errors to a pool-specific log file rather than to the path configured in Nginx or Apache. Two settings in the pool configuration control this behaviour.

Prerequisites

  • PHP-FPM installed and running
  • Access to the FPM pool config file (typically /etc/php-fpm.d/www.conf on CentOS/RHEL or /etc/php/<version>/fpm/pool.d/www.conf on Debian/Ubuntu)

Steps

1. Open the pool config file:

sudo nano /etc/php-fpm.d/www.conf

2. Ensure catch_workers_output is enabled (uncomment if needed):

catch_workers_output = yes

3. To send errors to the web server error log rather than a dedicated PHP error file, comment out php_flag[display_errors]:

; php_flag[display_errors] = on

If you prefer errors to go to a dedicated file, set:

php_flag[display_errors] = off
php_value[error_log] = /var/log/php-fpm/www-error.log

4. Restart PHP-FPM:

sudo systemctl restart php-fpm

Verify

tail -f /var/log/php-fpm/www-error.log

Trigger a PHP error and confirm it appears in the log file.

Notes

  • Without catch_workers_output = yes, worker process stdout/stderr is discarded.
  • If using Nginx, errors routed via catch_workers_output appear in the Nginx error log as well.

Adjust PHP-FPM Child Processes for Nginx

When PHP-FPM logs warnings about running out of child processes or reaching pm.max_children, the pool configuration must be tuned to match the server's available memory and workload.

Prerequisites

  • Nginx + PHP-FPM stack running
  • Access to /etc/php-fpm.d/www.conf (or the relevant pool file)

Identify the warning

These log lines indicate the pool is undersized:

[pool www] seems busy (you may need to increase pm.start_servers, or pm.min/max_spare_servers), spawning 32 children, there are 8 idle, and 58 total children
[pool www] server reached pm.max_children setting (50), consider raising it

Measure per-process memory usage

ps -ylC php-fpm --sort:rss

The RSS column shows non-swapped physical memory in kilobytes per process.

For the average across all workers:

ps --no-headers -o "rss,cmd" -C php-fpm | awk '{ sum+=$1 } END { printf ("%d%s
", sum/NR/1024,"M") }'

Calculate pm.max_children

Use this formula:

pm.max_children = (RAM available to PHP-FPM in MB) / (avg process size in MB)

Example: 8 GB server, ~85 MB per process, 2 GB reserved for OS and other services:

(8192 - 2048) MB / 85 MB ≈ 72  →  set pm.max_children = 70

Steps

Edit /etc/php-fpm.d/www.conf:

pm = dynamic
pm.max_children = 70
pm.start_servers = 20
pm.min_spare_servers = 20
pm.max_spare_servers = 35
pm.max_requests = 500

Restart PHP-FPM:

sudo systemctl restart php-fpm

Verify

sudo systemctl status php-fpm
tail -f /var/log/php-fpm/error.log

Notes

  • The same approach applies to Apache: substitute httpd for php-fpm in the ps commands and tune MaxClients / MaxRequestWorkers.
  • Setting pm.max_children excessively high without enough RAM causes swap thrashing and degrades performance.
  • pm.max_requests = 500 recycles workers periodically, preventing memory leaks from accumulating.

PHP CLI Commands Reference

A quick reference for commonly used PHP command-line interface (CLI) commands useful for diagnostics, configuration inspection, and scripting.

Commands

Show PHP version:

php --version

Show loaded configuration files (php.ini paths):

php --ini

List all compiled-in modules and extensions:

php -m

Dump all configuration values (phpinfo output in text form):

php -i

Search phpinfo output for a specific setting:

php -i | grep -i "extension_dir"

Execute a PHP expression directly:

php -r 'echo PHP_VERSION . "
";'

Run a PHP script file:

php /path/to/script.php

Check a script for syntax errors:

php -l /path/to/script.php

Notes

  • On systems with multiple PHP versions, use the versioned binary (e.g. php7.4, php8.1) to target a specific version.
  • php --ini shows both the master php.ini and any additional .ini files parsed from the conf.d directory.

Install PHP 7 in Webmin (CentOS/RHEL)

Webmin on CentOS/RHEL does not include PHP 7 by default. This guide installs PHP 7.2 from the Remi repository and makes it available for Webmin-managed services.

Prerequisites

  • CentOS 7 / RHEL 7 with root access
  • Webmin installed
  • Internet access for package downloads

Steps

1. Install EPEL and Remi repositories:

yum install epel-release yum-utils -y
yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
yum install http://rpms.remirepo.net/enterprise/remi-release-7.rpm

2. Enable the PHP 7.2 Remi repo:

yum-config-manager --enable remi-php72

3. Install PHP 7.2 and common extensions:

yum install php php-common php-opcache php-cli php-gd php-curl php-mysql     php-mbstring php-xml php-xmlrpc php-json php-mysqlnd -y

4. Verify the installation:

php -v

5. (Optional) If the php command still points to an old version, create a symlink:

ln -s /usr/bin/php72 /usr/bin/php

Verify

php -v
php -m | grep -i opcache

Notes

  • To install PHP 7.2 under a different prefix (e.g. php72 namespace), install php72 php72-php-fpm etc. and use php72 -v.
  • After installing PHP, restart Webmin and any web server service (Apache/Nginx) for Webmin to detect the new version.
  • Adjust the repo name (e.g. remi-php74, remi-php80) to install a different PHP 7.x/8.x version.

Determine the Correct Number of PHP-FPM Child Processes

Running too few PHP-FPM worker processes causes request queuing, 502 errors, and the pm.max_children warning in the FPM log. This guide shows how to measure per-process memory and calculate the right values for your server.

Prerequisites

  • Nginx + PHP-FPM running
  • Access to /etc/php/fpm/pool.d/www.conf (Debian) or /etc/php-fpm.d/www.conf (CentOS)
  • A stable workload (results fluctuate on shared hosting with varied codebases)

Identify the problem

These warnings in the PHP-FPM log indicate insufficient workers:

[pool www] server reached pm.max_children setting (35), consider raising it
[pool www] seems busy (you may need to increase pm.start_servers, or pm.min/max_spare_servers)

Measure per-process memory

Option 1 — list all processes and their RSS:

ps -ylC php-fpm --sort:rss

The RSS column is non-swapped physical memory in kilobytes. Example output:

S   UID   PID  PPID  C PRI  NI   RSS    SZ WCHAN  TTY          TIME CMD
S     0 24439     1  0  80   0  6364 57236 -      ?        00:00:00 php-fpm
S    33 24701 24439  2  80   0 61588 63335 -      ?        00:04:07 php-fpm
S    33 25319 24439  2  80   0 61620 63314 -      ?        00:02:35 php-fpm

Here each worker uses approximately 60 MB.

Option 2 — compute the average directly:

ps --no-headers -o "rss,cmd" -C php-fpm | awk '{ sum+=$1 } END { printf ("%d%s
", sum/NR/1024,"Mb") }'

Calculate pm.max_children

pm.max_children = (RAM available to PHP-FPM in MB) / (avg worker size in MB)

Example: 4 GB server, MariaDB using ~1 GB, 0.5 GB headroom for OS:

(4096 - 1024 - 512) MB / 60 MB ≈ 42  →  set pm.max_children = 40

Steps — apply the settings

Edit the pool config:

pm = dynamic
pm.max_children = 40
pm.start_servers = 15
pm.min_spare_servers = 15
pm.max_spare_servers = 25
pm.max_requests = 500

Restart PHP-FPM:

sudo systemctl restart php-fpm

Verify

sudo systemctl status php-fpm
tail -f /var/log/php-fpm/error.log

Watch the log for a few minutes under normal traffic; the pm.max_children warning should stop appearing.

Notes

  • Never allocate 100% of RAM to PHP-FPM — always reserve memory for the OS, database, and other services.
  • For heavy frameworks (e.g. Magento 2), use at least 128 MB per worker in your calculation.
  • pm.max_requests = 500 recycles workers to prevent slow memory leaks.

Fix nginx: php-fpm.sock failed (11: Resource Temporarily Unavailable)

The error connect() to unix:///path/php-fpm.sock failed (11: Resource temporarily unavailable) appears in the Nginx error log when all PHP-FPM workers are busy and the backlog queue is full. The fix involves tuning PHP-FPM pool settings and Nginx configuration.

Prerequisites

  • Nginx + PHP-FPM installed
  • Root access to pool config and Nginx config

Symptoms

499 errors  — clients dropping connections (too slow)
502 errors  — upstream returned bad gateway
connect() to unix:///var/www/vhosts/system/example.com/php-fpm.sock failed (11: Resource temporarily unavailable) while connecting to upstream

Steps — tune PHP-FPM pool

Edit /etc/php-fpm.d/www.conf (or your pool file):

listen.backlog = 65535

pm = dynamic
pm.max_children = 50
pm.start_servers = 10
pm.min_spare_servers = 10
pm.max_spare_servers = 30
pm.max_requests = 500

Calculate pm.max_children based on available RAM and average worker size:

pm.max_children = ((total RAM in MB) - (MySQL and other services in MB)) / (avg worker size in MB)

Use ~80 MB per worker for lightweight frameworks; ~128 MB for heavy frameworks like Magento 2.

Steps — tune Nginx worker connections

Edit /etc/nginx/nginx.conf:

worker_processes auto;
worker_rlimit_nofile 65535;

events {
    worker_connections 4096;
    use epoll;
    multi_accept on;
}

http {
    fastcgi_buffers 8 128k;
    fastcgi_buffer_size 256k;
    fastcgi_read_timeout 300s;
    fastcgi_send_timeout 300s;
}

Apply changes

sudo nginx -t
sudo systemctl reload nginx
sudo systemctl restart php-fpm

Verify

tail -f /var/log/nginx/error.log

Run a load test and confirm the failed (11) errors no longer appear.

Notes

  • Setting pm.max_children to an extremely high value (e.g. 4000–5000) without sufficient RAM causes the server to swap heavily and crash. Raise it gradually while monitoring memory.
  • pm.max_requests = 0 (unlimited) combined with very high max_children leads to unbounded RAM growth. Always set a reasonable max_requests value.
  • The listen.backlog setting also requires the OS kernel parameter net.core.somaxconn to be at least as large.

Install and Configure the PHP APC/APCu Extension

In PHP 7, the legacy apc_*() functions (e.g. apc_fetch) were removed. Code that calls them will fail with Call to undefined function apc_fetch(). The solution is to install APCu plus the APCu backwards-compatibility (apcu_bc) extension, which re-adds the old function names as aliases.

Prerequisites

  • PHP 7.0 or newer
  • Root or sudo access
  • For PECL installs: php-dev / php-devel package

Steps — Ubuntu 14.x (PHP 7.0 from Ondrej PPA)

sudo add-apt-repository ppa:ondrej/php
sudo apt-get update
sudo apt-get install php7.0

sudo apt-get install php7.0-apcu
sudo apt-get install php7.0-apcu-bc

sudo systemctl restart apache2

Steps — Ubuntu 16.x / 18.x

sudo apt-get install php-apcu
sudo add-apt-repository "deb http://ftp.de.debian.org/debian sid main"
sudo apt-get update
sudo apt-get install php-apcu-bc

sudo systemctl restart apache2

Steps — via PECL (any distro)

sudo apt-get install php-dev
sudo pecl install apcu
sudo pecl install apcu_bc

Edit /etc/php/7.X/mods-available/apcu.ini and ensure the load order is correct:

extension=apcu.so
extension=apc.so

Note: apc.so must be listed after apcu.so.

Steps — CentOS/RHEL (IUS repo)

sudo yum install php71u-pecl-apcu php71u-pecl-apcu-bc

Verify

php -m | grep -i apcu
php -r "echo apcu_fetch('test_key', \$s);"

Notes

  • APC and APCu are different modules. APCu provides only the user-cache (apcu_*() functions); apcu_bc adds the old apc_*() aliases on top.
  • If you control the application code, prefer migrating calls from apc_fetch() to apcu_fetch() rather than relying on the compatibility shim.

Install APC in cPanel (Fix apc_fetch Extension Load Order)

On cPanel servers running PHP 7.0 via EasyApache 4, the apc_fetch() function fails if the apc.so extension is loaded before apcu.so. Both apcu and apcu_bc must be installed and loaded in the correct order.

Prerequisites

  • cPanel/WHM server with EasyApache 4
  • Root SSH access
  • PHP 7.0 configured for the target account

Steps

1. Verify both PECL packages are installed:

/usr/bin/ea-php70-pecl list

Expected output:

Package  Version  State
apcu     5.1.21   stable
apcu_bc  1.0.5    stable

2. Check the current extension load order:

cat /opt/cpanel/ea-php70/root/etc/php.d/zzzzzzz-pecl.ini

If apc.so appears before apcu.so, that is the cause of the error.

3. Fix the load order — apcu must come first:

cat > /opt/cpanel/ea-php70/root/etc/php.d/zzzzzzz-pecl.ini << 'EOF'
extension="apcu.so"
extension="apc.so"
EOF

4. Switch the cPanel account to PHP 7.0 (if not already set) and test the site.

Verify

/opt/cpanel/ea-php70/root/usr/bin/php -m | grep -i apc

Both apcu and apc should appear in the output.

Notes

  • The PECL ini file name (zzzzzzz-pecl.ini) is prefixed with zs to ensure it loads after all other extension ini files — do not rename it.
  • This fix applies per PHP version; repeat for other EA4 PHP versions if needed (e.g. ea-php74).

Access phpinfo() Page by IP Address

A minimal PHP script that displays the server's public IP address alongside the standard phpinfo() output. Useful for quickly confirming which server is responding behind a load balancer or CDN.

Prerequisites

  • PHP installed and served by Apache or Nginx
  • Write access to the web root

Steps

1. Create the diagnostic script in your web root:

sudo nano /var/www/html/info.php

Paste the following content:

<?php
$publicIP = file_get_contents('https://api.ipify.org');
echo "<p>Public IP address: " . htmlspecialchars(trim($publicIP)) . "</p>";
phpinfo();

2. Set appropriate permissions:

sudo chmod 644 /var/www/html/info.php

3. Access the page in a browser:

http://<your-server-ip>/info.php

Verify

The page should show the public IP at the top, followed by the full PHP configuration table.

Notes

  • Security: Remove or restrict access to this file immediately after use. It exposes PHP configuration details that could aid an attacker.
  • To restrict by IP, add this to the Apache virtual host or .htaccess: Require ip 203.0.113.0/24
  • Alternatively, run php -i | grep -i "server api" from the CLI to inspect config without exposing it over HTTP.