How to display system uptime in php?

+2 votes
asked Aug 11, 2016 by ethan-morris

Still a beginner so bear with me...
So I found this function for system uptime and have been fooling around with it as I learn about php and web development in general.
My goal is to have the output look like days:hours:mins:secs but there was no $seconds variable so I have added that line based on what else I had. Everything works great except the seconds just shows up as 0. I'm not quite sure what I am doing wrong or if this is even the best way to do this.

function Uptime() {

    $uptime = @file_get_contents( "/proc/uptime");

    $uptime = explode(" ",$uptime);
    $uptime = $uptime[0];
    $days = explode(".",(($uptime % 31556926) / 86400));
    $hours = explode(".",((($uptime % 31556926) % 86400) / 3600));
    $minutes = explode(".",(((($uptime % 31556926) % 86400) % 3600) / 60));
    $seconds = explode(".",((((($uptime % 31556926) % 86400) % 3600) / 60) / 60));

    $time = $days[0].":".$hours[0].":".$minutes[0].":".$seconds[0];

    return $time;

}

EDIT: I was able to get it working in a different way new function is below . I am also still curious if anyone can answer why the above method did not work as expected, and if the new method below is the best way to accomplish this.

function Uptime() {
    $ut = strtok( exec( "cat /proc/uptime" ), "." );
    $days = sprintf( "%2d", ($ut/(3600*24)) );
    $hours = sprintf( "%2d", ( ($ut % (3600*24)) / 3600) );
    $min = sprintf( "%2d", ($ut % (3600*24) % 3600)/60  );
    $sec = sprintf( "%2d", ($ut % (3600*24) % 3600)%60  );


    return array( $days, $hours, $min, $sec );
}
$ut = Uptime();
echo "Uptime: $ut[0]:$ut[1]:$ut[2]:$ut[3]";

EDIT 2: I believe this last method is the best based on the answer given by nwellnhof. I had to tweak a bit to get the output exactly as I wanted. Thanks guys.

function Uptime() {
        $str   = @file_get_contents('/proc/uptime');
        $num   = floatval($str);
        $secs  = $num % 60;
        $num   = (int)($num / 60);
        $mins  = $num % 60;
        $num   = (int)($num / 60);
        $hours = $num % 24;
        $num   = (int)($num / 24);
        $days  = $num;

        return array(
            "days"  => $days,
            "hours" => $hours,
            "mins"  => $mins,
            "secs"  => $secs
        );
    }

5 Answers

0 votes
answered Aug 13, 2016 by hek2mgl

uptime supports the -p command line option. You can use this simple piece of code:

echo shell_exec('uptime -p');
+1 vote
answered Aug 13, 2016 by nwellnhof

Reading directly from /proc/uptime is the most efficient solution on Linux. There are multiple ways to convert the output to days/hours/minutes/seconds. Try something like:

$str   = @file_get_contents('/proc/uptime');
$num   = floatval($str);
$secs  = fmod($num, 60); $num = (int)($num / 60);
$mins  = $num % 60;      $num = (int)($num / 60);
$hours = $num % 24;      $num = (int)($num / 24);
$days  = $num;

Or, with intdiv (PHP7):

$str   = @file_get_contents('/proc/uptime');
$num   = floatval($str);
$secs  = fmod($num, 60); $num = intdiv($num, 60);
$mins  = $num % 60;      $num = intdiv($num, 60);
$hours = $num % 24;      $num = intdiv($num, 24);
$days  = $num;
0 votes
answered Aug 13, 2016 by mweerden

If you just look at the pattern in your statements, you can see that the one for seconds is different. It has two divisions. Additionally, the numbers you are using represent the number of seconds per time unit. The number of seconds per second should be 1, not 60. In short:

$seconds = explode(".",((((($uptime % 31556926) % 86400) % 3600) / 60) / 60));

Should be:

$seconds = explode(".",((((($uptime % 31556926) % 86400) % 3600) % 60) / 1));

Now this whole way of doing things is a bit weird. For example, (x % (n*m)) % m is just x % m.

A nicer way would be to do:

$uptime  = (int) $uptime;
$seconds =  $uptime               % 60;
$minutes = ($uptime /  60       ) % 60;
$hours   = ($uptime / (60*60)   ) % 24;
$days    =  $uptime / (60*60*24); # % 365, if you want
0 votes
answered Feb 27, 2017 by scott

variation of your initial example as a class:

class Uptime {
    private $uptime;

    private $modVals = array(31556926, 86400, 3600, 60, 60);

    public function __construct() {
        $this->read_uptime();
    }

    /**
     * actually trigger a read of the system clock and cache the value
     * @return string
     */
    private function read_uptime() {
        $uptime_raw = @file_get_contents("/proc/uptime");
        $this->uptime = floatval($uptime_raw);
        return $this->uptime;
    }

    private function get_uptime_cached() {
        if(is_null($this->uptime)) $this->read_uptime(); // only read if not yet stored or empty
        return $this->uptime;
    }

    /**
     * recursively run mods on time value up to given depth
     * @param int $d
     * @return int
     **/
    private function doModDep($d) {
        $start = $this->get_uptime_cached();
        for($i=0;$i<$d;$i++) {
            $start = $start % $this->modVals[$i];
        }
        return intval($start / $this->modVals[$d]);
    }

    public function getDays()
    {
        return $this->doModDep(1);
    }

    public function getHours() {
        return $this->doModDep(2);
    }

    public function getMinutes()
    {
        return $this->doModDep(3);
    }

    public function getSeconds()
    {
        return $this->doModDep(4);
    }

    public function getTime($cached=false) {
        if($cached != false) $this->read_uptime(); // resample cached system clock value
        return sprintf("%03d:%02d:%02d:%02d", $this->getDays(), $this->getHours(), $this->getMinutes(), $this->getSeconds());
    }
}
0 votes
answered Jul 10, 2017 by kenorb

On Unix/BSD, using /proc is not reliable since it is not mounted by default, on some Linux distributions it can be unmounted also, so it's better to parse using either uptime or sysctl command, e.g.

sysctl

<?php
preg_match('/sec = (\d+)/', shell_exec('sysctl -n kern.boottime'), $secs)
echo $secs[1];

or:

$s = explode( " ", exec("/sbin/sysctl -n kern.boottime") );
$a = str_replace( ",", "", $s[3]);
$uptime = time() - $a;  

or as per example taken from m0n0wall:

<?php
exec("/sbin/sysctl -n kern.boottime", $boottime);
preg_match("/sec = (\d+)/", $boottime[0], $matches);
$boottime = $matches[1];
$uptime = time() - $boottime;

if ($uptime > 60)
    $uptime += 30;
$updays = (int)($uptime / 86400);
$uptime %= 86400;
$uphours = (int)($uptime / 3600);
$uptime %= 3600;
$upmins = (int)($uptime / 60);

$uptimestr = "";
if ($updays > 1)
    $uptimestr .= "$updays days, ";
else if ($updays > 0)
    $uptimestr .= "1 day, ";
$uptimestr .= sprintf("%02d:%02d", $uphours, $upmins);
echo htmlspecialchars($uptimestr);

uptime

Example taken from 4webhelp:

<?php
$data = shell_exec('uptime');
$uptime = explode(' up ', $data);
$uptime = explode(',', $uptime[1]);
$uptime = $uptime[0].', '.$uptime[1];
echo ('Current server uptime: '.$uptime.'

or (tested on FreeBSD):

$uptime = exec("uptime");
$uptime = split(" ",$uptime);
$days = $uptime[3]; # NetBSD: $days = $uptime[4];
$time = split(",",$uptime[5]); # NetBSD: $time = split(",",$uptime[7]);
if (sizeof($hourmin = split(":",$time[0])) < 2){ ;
  $hours = "0";
  $mins = $hourmin[0];
} else {
  $hourmin=split(":",$time[0]);
  $hours = $hourmin[0];
  $mins = $hourmin[1];
}
$calcuptime =  "Uptime: ".$days." days ".$hours." hours ".$mins." mins" ;
echo $calcuptime;

Here is version which works for Windows:

<?php
$uptime = `c:\windows\system32\uptime2.bat $server`;
$uptime = explode(": ", $uptime);
$uptime = explode(", ", $uptime[1]);

$uptime_days = preg_replace($pattern, '', $uptime[0]);
$uptime_hours = preg_replace($pattern, '', $uptime[1]);
$uptime_minutes = preg_replace($pattern, '', $uptime[2]);
$uptime_seconds = preg_replace($pattern, '', $uptime[3]);

echo '<b>Uptime:</b><br><br>';

echo 'Days: '.$uptime_days.'<br>';
echo 'Hours: '.$uptime_hours.'<br>';
echo 'Minutes: '.$uptime_minutes.'<br>';
echo 'Seconds: '.$uptime_seconds.'<br>';
Welcome to Q&A, where you can ask questions and receive answers from other members of the community.
Website Online Counter

...