You updated PHP on a cPanel server — yum update finished, rpm -q shows the new build, the command line agrees — but a website keeps reporting the old version in phpinfo(). First confirm the packages really did update (rpm -q and php -v should show the new build); if they do not, that is a different problem. Once they have, a common cause of the lingering old version is that a long-running PHP worker is still executing the old binary from memory and will keep doing so until it is recycled — but a version mismatch has other causes too, so this guide confirms the stale worker before you act on it.
In short: a PHP package update replaces the files on disk, but it does not, on its own, recycle the PHP workers (lsphp under LiteSpeed/LSAPI, or php-fpm) that a site already has running — so do not assume the update restarted them. Linux keeps the old executable mapped in memory even after the file is replaced, so the worker serves the old version and the kernel marks its /proc/PID/exe with (deleted). Recycle the affected worker — or, when several are affected, its handler — and the new version is served. Before you do, rule out the ordinary causes of a version mismatch (the wrong version assigned in MultiPHP Manager, a separate PHP install, or a cached phpinfo), because not every mismatch is a stale worker.
Table of Contents
Quick check (one command)
Read-only and safe to run as root. List your PHP web workers — both lsphp (LSAPI) and php-fpm — then ask the kernel what binary one is really running. A path ending in (deleted) is a stale worker:
ps -eo pid,user,etime,comm | grep -E '[l]sphp|php-fpm' # lsphp (LSAPI) and php-fpm workers
readlink /proc/PID/exe # ...ends in " (deleted)" = stale worker
Use the symptoms below to point yourself at the likely cause before reading further. A (deleted) executable confirms the running file was replaced on disk; it does not on its own prove the version is older, so always confirm the version actually served.
| Symptom | Most likely cause | First check |
|---|---|---|
rpm -q / php -v show the new version, but one site shows the old one | a worker still running the replaced binary | readlink /proc/PID/exe ends in (deleted) |
| CLI and cron are correct; only the website is wrong | a persistent web worker not yet recycled | the worker started before you ran the update |
| Every site shows the wrong version | wrong version assigned, or a stale PHP-FPM master | MultiPHP Manager; the php-fpm master’s /proc/PID/exe |
| Version never changes, even after a restart | a different PHP stack, or a handler misassignment | which /opt path the domain’s handler uses (EA-PHP vs Alt-PHP) |
The six places a PHP version can come from
“PHP is 8.3.36” is never a single fact on a cPanel/CloudLinux server. Before chasing a mismatch, be clear about which version you are reading, because the fix is different for each:
| Where you look | How you read it | What it is |
|---|---|---|
| Installed package | rpm -q ea-php83-php-cli | the version written to disk by the package manager |
| PHP CLI | /opt/cpanel/ea-php83/root/usr/bin/php -v | what cron jobs and WP-CLI run — a separate binary from the web one |
| LSAPI binary | /opt/cpanel/ea-php83/root/usr/bin/lsphp -v | the on-disk LiteSpeed PHP binary the web server launches |
| PHP-FPM runtime | the running php-fpm workers | the version FPM pools are actually serving |
| Served to visitors | phpinfo() on the site, or a response header | what the live site runs right now — the only number visitors see |
| Assigned version | WHM › MultiPHP Manager | which PHP version each domain is set to use |
Two more distinctions matter on these servers. EasyApache (EA-PHP) under /opt/cpanel/ea-phpNN/ is the stack cPanel serves most sites with; CloudLinux Alt-PHP under /opt/alt/phpNN/ is a separate set of binaries exposed through the PHP Selector. A domain can be updated in one stack while you are checking the other. And the package version (on disk) is not the running version: a worker that started before the update keeps running until it is recycled. That gap is what this guide is about.
Confirm it is a stale worker
Work from the package down to the running process. First confirm the update really landed on disk:
rpm -q ea-php83-php-cli ea-php83-php-common ea-php83-php-litespeed
/opt/cpanel/ea-php83/root/usr/bin/lsphp -v
If those show the new version (for example PHP 8.3.36) but a site still reports the old one, look at the running web workers. Under LiteSpeed/LSAPI that is lsphp:
ps -eo pid,ppid,user,lstart,etime,args | grep '[l]sphp'
Note the start time. A worker that started before you ran the update is the suspect. Now ask the kernel what binary that process is really executing — replace PID with the process ID from the line above:
readlink /proc/PID/exe
The tell-tale answer is a path with (deleted) after it:
/opt/cpanel/ea-php83/root/usr/bin/lsphp (deleted)
That is the whole diagnosis: the file on disk was replaced by the update, but this process is still running the old copy that the kernel is keeping alive in memory, which it flags as (deleted). Reading /proc/PID/exe is the one check that distinguishes a stale worker from every other cause — the package, the CLI and the on-disk binary can all look correct while a worker serves the old code. The companion script below does this check across every worker for you.
What readlink /proc/PID/exe shows | What it means | What to do |
|---|---|---|
a path ending in (deleted) | confirmed: the worker runs a binary that was replaced on disk | recycle that worker, or restart the web server (see below) |
| a normal path, but the on-disk binary is newer than the worker’s start time | unverified: the binary changed after the worker started (could be an in-place rebuild, not a version change) | confirm the version actually served, then recycle only if it is genuinely old |
| a normal, current path | this worker is already on the current binary | look elsewhere — see “Rule out the other causes” below |
Why an update does not change the running version
A package update (yum update, dnf update, EasyApache, or a CloudLinux alt-php update) does one thing: it replaces files on disk. It does not, by itself, stop and restart the PHP workers a site already has running. LSAPI keeps lsphp workers alive between requests for speed; PHP-FPM keeps a pool of workers under a master process. Those long-lived processes were launched from the old binary, and Linux keeps that executable mapped in memory for as long as the process lives — even after the file itself is replaced or unlinked. So the worker goes on serving the old version, and phpinfo() reports it, until the worker is recycled and a fresh one launches from the new binary on disk.
This is why rpm -q and php -v (which start a brand-new short-lived process every time you run them) immediately show the new version, while the web worker — which is persistent — does not. It is normal operating-system behaviour, not corruption.
Rule out the other causes first
A stale worker is the most common reason, but it is not the only one. If /proc/PID/exe does not show (deleted) and the binary is current, check these before recycling anything:
- The domain is assigned a different version. WHM › MultiPHP Manager (or the user’s PHP Selector) may have the site set to another version entirely. You could be updating 8.3 while the domain runs 8.2.
- Two PHP stacks. You updated EA-PHP under
/opt/cpanel/ea-phpNN/, but the site runs CloudLinux Alt-PHP under/opt/alt/phpNN/(or the reverse). Check which stack the domain’s handler points at. - A PHP-FPM pool. If the domain uses PHP-FPM rather than LSAPI, it is the
php-fpmmaster and its pool workers that must be recycled, and the master is restarted as a service — a per-worker kill will not help it. - A cached
phpinfoor page cache. If you are reading the version from a cached page (LiteSpeed Cache, a CDN, or a savedinfo.php), you may be looking at an old snapshot. Load an uncachedphpinfo()or send a no-cache request. - OPcache. OPcache stores compiled bytecode, not the PHP version, so it does not change the reported version — but it can make code changes look like they did not apply, which is sometimes mistaken for a version problem.
Only once you have confirmed the right version is installed and assigned, and a worker is genuinely running a replaced binary, is recycling the answer.
Fix it safely
The right fix depends on the handler, so match it to what you found. If the stale process is a PHP-FPM master, the fix is to restart that version’s FPM service — recycling an individual worker will not help, because the pool’s workers are forked from the master:
systemctl restart ea-php83-php-fpm # the affected version's FPM service
For a stale lsphp (LSAPI) or an FPM pool worker, use one of the two options below. Both interrupt any request that worker is mid-way through, so pick the one that fits.
Option A — recycle just the affected worker
The least disruptive option, once you have positively identified the stale process and its owner. Send it SIGTERM so it can finish its current request where the handler allows, and the web server (or the PHP-FPM master) launches a fresh worker from the new binary on the next request:
kill -TERM PID
SIGTERM is not guaranteed to be graceful for every handler configuration, so a request in flight may still be cut off. Never run killall lsphp on a shared server — that drops every account’s in-flight requests at once. For the detail of terminating one user’s workers safely, including processes stuck in uninterruptible state, see our guide on stuck lsphp processes.
Option B — restart the web server
Restarting the web server recycles its PHP workers in one step. This is the simplest fix when several workers or several sites are affected, and it is what resolved the real case this guide is based on — a single Apache restart (mod_lsapi on CloudLinux), after which every site reported the new version:
systemctl restart httpd # Apache / mod_lsapi - recycles its lsphp workers
A web-server restart briefly disrupts every site on the server, so run it in a maintenance window. It is not always required — a targeted recycle (Option A) is often enough. One important caveat: restarting the web server does not reliably recycle every kind of PHP process, so match the method to the handler:
- An independently managed PHP-FPM master is restarted through its own service, not by the web server:
systemctl restart ea-php83-php-fpm. - LiteSpeed running PHP in detached (external) mode — the usual configuration on LiteSpeed Enterprise and OpenLiteSpeed — keeps its
lsphpprocesses alive across a server restart by design, so a plainsystemctl restart lswscan leave the stale workers running. Recycle PHP the way LiteSpeed documents instead: use Restart PHP in the LiteSpeed WebAdmin console, or drop LiteSpeed’s per-account restart marker (it is picked up on the next request) — or simply recycle the specific PID with Option A:touch /home/ACCOUNT/.lsphp_restart.txt # LiteSpeed recycles that account's detached lsphp
Do not reboot the whole server just to refresh PHP workers; that is never necessary for this problem.
Verify the fix
Do not assume the recycle worked — confirm it. The version visitors see is the one that matters:
- Check the version the site actually serves — that is the number that matters. A full, public
phpinfo()exposes a lot of server detail, so prefer a minimal version check that you restrict and then remove: a one-line file that prints only the PHP version, protected by an IP allow-rule or simply deleted the moment you have read it. A response header such asX-Powered-Byis convenient but can be disabled, stripped by the server, or cached, so treat it only as a hint:# minimal and temporary - delete it as soon as you have read the version: echo '<?php echo PHP_VERSION;' > /home/ACCOUNT/public_html/zz-ver.php curl -s "https://THE-DOMAIN/zz-ver.php?nocache=$(date +%s)"; rm -f /home/ACCOUNT/public_html/zz-ver.php # X-Powered-By is a hint only - it may be off, removed or cached: curl -sI "https://THE-DOMAIN/?nocache=$(date +%s)" | grep -i x-powered-by - Re-run the process check and confirm a new worker has started (a newer start time) and that
readlink /proc/PID/exeno longer ends in(deleted):ps -eo pid,lstart,args | grep '[l]sphp' readlink /proc/NEW_PID/exe - If the site uses a page cache or CDN, purge it so visitors are served fresh output.
Still not resolved, or would rather not touch a production server during business hours? If the version will not change after you have ruled out the causes above, our server management and emergency troubleshooting service can diagnose and fix it for you, in a maintenance window, without guesswork.
Check every server automatically
Checking /proc/PID/exe by hand across dozens of workers is tedious and easy to get wrong. Our free, read-only cPanel PHP stale-worker check does it for you: it lists installed EA-PHP and Alt-PHP versions, finds every running lsphp and php-fpm worker, inspects each one’s executable, and reports which workers are running a replaced binary — separating a confirmed stale worker (marked (deleted)) from an unverified mismatch. It is audit-only: it never terminates a process or restarts a service. Given one confirmed-stale PID, --repair prints the exact recycle command for you to run and watch rather than acting itself — automated termination is withheld by design, so recycling a worker is always a deliberate step you take. To list the top of a server’s PHP picture at a glance, see also the cPanel PHP version audit.
Frequently asked questions
Does yum update or dnf update restart PHP?
yum update or dnf update restart PHP?Not on its own. It replaces the PHP files on disk, but existing lsphp or php-fpm workers keep running the old binary from memory until they are recycled. Recycling the specific worker is reliable; a web-server restart recycles Apache/mod_lsapi workers, but a LiteSpeed server restart may not recycle lsphp run in detached mode (see Fix it safely). That is why the package shows the new version while a site still reports the old one.
What does (deleted) next to the executable mean?
(deleted) next to the executable mean?The kernel adds (deleted) to /proc/PID/exe when the file a running process was launched from has been replaced or removed on disk. The process keeps running the in-memory copy. After a PHP update it usually means the worker is running the pre-update binary — but it can also appear after an in-place package rebuild that did not change the version, so confirm the served version before assuming it is wrong.
Is restarting Apache safe?
A restart is a normal operation, but it briefly interrupts every site on the server while workers recycle, so do it in a maintenance window. If only one account is affected, recycling that account’s workers is less disruptive. Rebooting the whole server is never necessary just to refresh PHP.
Will killing an lsphp process break the site?
lsphp process break the site?Killing one worker only interrupts whatever request it was serving at that instant; LiteSpeed launches a fresh worker on the next request. The danger is killall lsphp on a shared host, which drops every account’s requests at once. Target one PID at a time, and never force-kill (SIGKILL) a process stuck in uninterruptible (D) state without understanding why it is stuck.
Does this affect PHP-FPM too?
Yes. A PHP-FPM pool’s workers are forked from a master process; if the master is still running the replaced binary, the whole pool serves the old version. The fix is to restart that version’s FPM service (for example systemctl restart ea-php83-php-fpm), not to kill a single pool worker.
Based on a real cPanel & WHM 11.138 server on AlmaLinux 9 (Apache + CloudLinux LSAPI), October 2026: PHP packages updated from 8.3.35 to 8.3.36, but a site kept reporting 8.3.35 because an lsphp worker that started before the update was still running the replaced binary (shown by /proc/PID/exe ending in (deleted)). An Apache restart resolved it. The diagnostic commands and the companion script were verified against controlled fixtures, and the script’s audit was then run on a live cPanel server (EA-PHP plus CloudLinux alt-php, many PHP-FPM masters) where its output matched the running processes. Adapt PHP paths and process IDs to your own server.