I recently deployed PHP Server Monitor v3.5.2 on my server to keep track of my hosting status. However, right after setting it up, I noticed a very bizarre issue:
I purposely added a completely unreachable, invalid IP to test the Ping monitoring, but the system reported it as “Online” with a latency of 0ms!
I checked the system error logs, but they were completely clean—no error messages at all. A monitoring system that fails to alert you when a server goes down is virtually useless. To fix this fatal flaw, I began a deep dive to troubleshoot the issue.
🕵️♂️ The Diagnosis: Where did it go wrong?
Initially, I suspected the server’s PHP security settings (like disable_functions in php.ini) might be restricting the execution of system commands. If the exec() function is disabled, PHP wouldn’t be able to run the system’s ping command.
To test this theory, I wrote a simple PHP diagnostic script (test_ping.php) to check the underlying connection:
<?php
$test_ip = "192.168.255.255";
$cmd = "ping -c 1 -w 2 " . escapeshellarg($test_ip) . " 2>&1";
exec($cmd, $output, $return_var);
echo "Return Code: " . $return_var . "<br>";
print_r($output);
?>
The execution results were eye-opening:
- Return Code: 1 (which means failure)
- Actual Terminal Output: It clearly printed
2 packets transmitted, 0 received, 100% packet loss, time 1016ms.
This proved that the server environment and permissions were perfectly fine! The system successfully sent the packets and accurately recognized that the IP was unreachable (100% packet loss). The environment was not the culprit.
💡 The Root Cause: Outdated Regex vs. Modern Linux
With the environment ruled out, the root of the problem pointed directly to a bug within PHP Server Monitor v3.5.2 itself.
After digging into the official GitHub repository, I realized the software hasn’t seen a major active update since around 2021. The old codebase uses a very rigid method to determine ping status: it uses Regular Expressions (Regex) to parse the text output of the terminal. If it spots the keyword time anywhere in the output string, it blindly assumes “there’s a response time, so the host must be Online.”
In older Linux distributions, a failed ping (100% packet loss) usually wouldn’t print the time taken at the end of the output. However! In newer Linux distributions (like recent Debian versions), the ping command reliably prints out time 1016ms at the very end, even if every single packet is dropped.
Because of this simple phrase—time 1016ms—the outdated code in PHP Server Monitor gets completely confused. It ignores the glaring 100% packet loss right next to it and falsely reports the server as Online. This is also exactly why the “fix” available in the official development branch still fails on newer Linux systems.
🛠️ The Ultimate Solution: Rewriting the Core Logic
Since official maintenance has stalled, the most reliable way forward is to rewrite the validation logic ourselves. Instead of relying on the app to parse terminal text—which can constantly change depending on the Linux distribution—we should just grab the most honest metric the OS provides: the Return Code (0 means success, anything else means failure).
How to apply the fix:
- Access your PHP Server Monitor web directory via SSH or FTP.
- Locate and open this specific file:
src/psm/Util/Server/Updater/StatusUpdater.php - Search for the
protected function updatePingfunction inside the file (it should be roughly past the middle). - Replace the entire
updatePingfunction block with this updated, precise version:
protected function updatePing($max_runs, $run = 1) {
$starttime = microtime(true);
$ip = $this->server['ip'];
$os_is_windows = strtoupper(substr(PHP_OS, 0, 3)) === 'WIN';
if ($os_is_windows) {
// Windows Ping: -n 1 (1 packet), -w 2000 (2000ms timeout)
exec('ping -n 1 -w 2000 ' . escapeshellarg($ip), $output, $result);
$output_str = implode("", $output);
// Windows ping notoriously returns 0 on unreachable hosts. Verify with "TTL="
$status = ($result === 0 && stripos($output_str, 'TTL=') !== false) ? true : false;
} else {
// Linux/Unix Ping: -c 1 (1 packet), -w 2 (2s timeout), capture stderr
exec('ping -c 1 -w 2 ' . escapeshellarg($ip) . ' 2>&1', $output, $result);
// Core fix for Linux: Only trust the Return Code! (0 is success)
$status = ($result === 0) ? true : false;
}
// Record the response time
$this->rtime = (microtime(true) - $starttime);
// If it fails and we haven't reached max retries, try again
if(!$status && $run < $max_runs) {
return $this->updatePing($max_runs, $run + 1);
}
return $status;
}
Save the file and head back to your PHP Server Monitor dashboard. Test that invalid IP again, and the system will finally behave as it should, properly displaying a red “Offline” status!
📝 Conclusion
Sometimes, when running older open-source software on modern operating systems, official patches might not be enough to resolve bugs caused by OS-level changes. In situations like this, writing a simple script to test the underlying commands directly can help cut through the confusion and point you toward the most effective fix.
If you are using PHP Server Monitor and experiencing this “Fake Online” bug, give this fix a try!
Tags: PHP Server Monitor, Bug Fix, Server Monitoring, Ping, Linux