PHP Script for gathering process resource usage data from the local system and create bar graph

Hello Experts,

Firstly i would like to say that i am a novice php enthusiast.

I am currently trying to write a script that gathers the process resources of my local system in order to produce a bar graph of the 6 most memory-hungry processes on my system.

I have managed to make my shell command execute inside the php script, however i do not know how to incorporate the output of my shell command into my values variabe, so that the graph can be generated.

Would you be able to suggest how this could be done?
Here is the script as it is so far, i am missing something that i just cannot resolve.
<?php
//Execute command via shell and return the complete output as a string

$output = shell_exec('ps ax -o rss,command | sort -nr | head -n 6');
echo "<pre>$output</pre>";

// This array of values is just here for the example.

    $values = array("23","32","35","57","12",
                    "3","36","54","32","15",
                    "43","24","30");

// Get the total number of columns we are going to plot

    $columns  = count($values);

// Get the height and width of the final image

    $width = 300;
    $height = 200;

// Set the amount of space between each column

    $padding = 5;

// Get the width of 1 column

    $column_width = $width / $columns ;

// Generate the image variables

    $im        = imagecreate($width,$height);
    $gray      = imagecolorallocate ($im,0xcc,0xcc,0xcc);
    $gray_lite = imagecolorallocate ($im,0xee,0xee,0xee);
    $gray_dark = imagecolorallocate ($im,0x7f,0x7f,0x7f);
    $white     = imagecolorallocate ($im,0xff,0xff,0xff);
    
// Fill in the background of the image

    imagefilledrectangle($im,0,0,$width,$height,$white);
    
    $maxv = 0;

// Calculate the maximum value we are going to plot

    for($i=0;$i<$columns;$i++)$maxv = max($values[$i],$maxv);

// Now plot each column
        
    for($i=0;$i<$columns;$i++)
    {
        $column_height = ($height / 100) * (( $values[$i] / $maxv) *100);

        $x1 = $i*$column_width;
        $y1 = $height-$column_height;
        $x2 = (($i+1)*$column_width)-$padding;
        $y2 = $height;

        imagefilledrectangle($im,$x1,$y1,$x2,$y2,$gray);

// This part is just for 3D effect

        imageline($im,$x1,$y1,$x1,$y2,$gray_lite);
        imageline($im,$x1,$y2,$x2,$y2,$gray_lite);
        imageline($im,$x2,$y1,$x2,$y2,$gray_dark);

    }

// Send the PNG header information. Replace for JPEG or GIF or whatever

    header ("Content-type: image/png");
    imagepng($im);
?>

Open in new window

kabaleraAsked:
Who is Participating?
 
Slick812Commented:
OK - you ask - "How do i display the name of the process in function of the amount of RAM that it is consuming on the graph"

I kinda thought you would ask this, as a blank - unidentified - group of grey graph bars are about as useful as a programmer that does not know how to program.

I have shown you how to use the  php  explode( ) to separate Text-Delimited values into a php Array.  Since you need to learn, I will explain a little more, I looked at the "Example Text" you gave with first line as -
              320092 /usr/lib/firefox/firefox

I could see that the "Delimiter" for each primary text data segment was a text "New Line" character "\n" for php
as there is a segment of text distinct information on a different line in the text block, so use -
            explode("\n", $mainText );

Next, I could see that you set (or it was auto) to have the "Space" character as the "Delimiter" for each secondary text data segment, so I could use this -
            explode(' ', $subText );

if you look at Each Line, you can see that the "Number" is the first segment before any "Space" character, so I used this -
      $arySp[0]
to get ONLY the Number such as "193372",

you should be able to look at a line of this output, and figure out which element or data segment of the $arySp[ ]  array has the "process name" in it separated by spaces, the second line has Only two elements, so the process must be in the second element as -
      $arySp[1]
to get ONLY the Process path such as "/usr/lib/firefox/firefox",
since you likely just want to get the name and not the path as  firefox , compiz , X , dropbox , you could use the -
       explode('/',  $arySp[1] );
and use the last element of the resultant array to get just the name.

Please consider and try to do code that gets the name for you.

But I believe that using a Vertical Bar graphing, such as to get in your PNG, will be a problem for your display, IF you try and write ID names like "firefox" or "dropbox" horizontally on it, there's just no room for that, you could Expand the horizontal spacing, You could try and write them vertically like -
f
i
r
e
f
o
x

but as far as I know, in the php GD there is no auto vertical text write, so you would need to do math to calculate the position for Each letter and write them one by one.
    OR
change to a horizontal Bar graph display, and just write the names over each bar.
0
 
Slick812Commented:
greetings  kabalera,,
I have not used the linux bash command "ps", so I do not comment about that, But it  will output a screen, that uses a "text delimited" format,  It looks as though you use a "custom" formatting, with a "sort", but I have no idea what the "head -6" does.,
I think the "ps" uses "new line", "spaces" and "commas", as it's text "output"  delimiters. .
If you can get your -
    echo "<pre>$output</pre>";
to look like -
     "52,71,4,17,11"
or like -
     "52 71 4 17 11"
then you can use the PHP explode( ) -
    $values = explode( ',', $output );
or
    $values = explode( ' ', $output );

to get the $output string into an array.

ask questions if you need more information.
0
 
Mark BullockQA Engineer IIICommented:
You can redirect the output of your shell command into a file, then read that file in your php program.
ps ax -o rss,command | sort -nr | head -n 6 > /tmp/ps.txt
0
Cloud Class® Course: Microsoft Azure 2017

Azure has a changed a lot since it was originally introduce by adding new services and features. Do you know everything you need to about Azure? This course will teach you about the Azure App Service, monitoring and application insights, DevOps, and Team Services.

 
kabaleraAuthor Commented:
Hi Mark and Slick,

Thank you both for your comments.

@Slick : the head -6 command is to obtain the 6 most memory hungry processes from my local system.

here is the output of my ps command
320092 /usr/lib/firefox/firefox
229944 compiz
194588 compiz
193372 /usr/bin/X -core :1 -seat seat0 -auth /var/run/lightdm/root/:1 -nolisten tcp vt8 -novtswitch
159284 /home/kabalera/.dropbox-dist/dropbox-lnx.x86_64-3.2.9/dropbox
105004 /usr/bin/X -core :0 -seat seat0 -auth /var/run/lightdm/root/:0 -nolisten tcp vt7 -novtswitch

Open in new window


I have then inserted the output of this textfile like you have suggested Mark into my php code like this.
<?php

//Execute command via shell and return the complete output as a string

        $output = shell_exec('ps ax -o rss,command | sort -nr | head -n 6 > /tmp/memgraph.txt');


// Values of my output inserted into my php code, is this correct? .

    $values = explode("/", $output);


// Get the total number of columns we are going to plot

    $columns  = count($values);

// Get the height and width of the final image

    $width = 300;
    $height = 200;

// Set the amount of space between each column

    $padding = 5;

// Get the width of 1 column

    $column_width = $width / $columns ;

// Generate the image variables

    $im = imagecreate($width,$height);
    $gray = imagecolorallocate ($im,0xcc,0xcc,0xcc);
    $gray_lite = imagecolorallocate ($im,0xee,0xee,0xee);
    $gray_dark = imagecolorallocate ($im,0x7f,0x7f,0x7f);
    $white     = imagecolorallocate ($im,0xff,0xff,0xff);
    
// Fill in the background of the image

    imagefilledrectangle($im,0,0,$width,$height,$white);
    
    $maxv = 6;

// Calculate the maximum value we are going to plot

    for($i=0;$i<$columns;$i++)$maxv = max($values[$i],$maxv);
// plot each column

    for($i=0;$i<$columns;$i++)
    {
        $column_height = ( $values[$i] / $maxv) *100;

        $x1 = $i*$column_width;
        $y1 = $height-$column_height;
        $x2 = (($i+1)*$column_width)-$padding;
        $y2 = $height;

        imagefilledrectangle($im,$x1,$y1,$x2,$y2,$gray);

// This part is just for 3D effect

        imageline($im,$x1,$y1,$x1,$y2,$gray_lite);
        imageline($im,$x1,$y2,$x2,$y2,$gray_lite);
        imageline($im,$x2,$y1,$x2,$y2,$gray_dark);

    }

// Send the PNG header information. Replace for JPEG or GIF or whatever

    header ("Content-type: image/png");
    imagepng($im);
?>

Open in new window


When i run the code i get this?

kabalera@siftworkstation:~$ php memgraph2.php
�PNG

IHDR,�/�4�
             PLTE���������,R-	pHYs���+OIDATh���1
                                                              ���;v@�;q�\.���r^��IEND�B`�kabalera@siftworkstation:~$ ��r��_�f`

Open in new window


Please help me out here guys.
Cheers
Kab
0
 
Slick812Commented:
OK, I am completely confused buy your text parsing of the output with -
     $values = explode("/", $output);
Where did I say anything about using  "/"   ? ?
Not only that, you keep the same custom format for ps

I tried to tell you, If you only need the numbers from ps, than get ONLY NUMBERS .
You also do not seem to realize that IF you correctly parse the "numbers" out of the $output string, then they are still strings, not integers, you need to covert them to integers if you are going to do mathematics with them.

If your output is like this -

320092 /usr/lib/firefox/firefox
229944 compiz
194588 compiz
193372 /usr/bin/X -core :1 -seat seat0 -auth /var/run/lightdm/root/:1 -nolisten tcp vt8 -novtswitch
159284 /home/kabalera/.dropbox-dist/dropbox-lnx.x86_64-3.2.9/dropbox
105004 /usr/bin/X -core :0 -seat seat0 -auth /var/run/lightdm/root/:0 -nolisten tcp vt7 -novtswitch

then you Can NOT do a simple single explode( ) to parse the numbers out of this string.

I do not think that you will understand the steps it takes, so I did this code, where I just do the parsing -
I do not do the linux bash command for ps  , , I just use the text string you display for the ps output.
<!DOCTYPE HTML>
<html lang="en"><head>
<title>parse to png</title></head><body bgcolor="#e3f7ff"><h3>parse to png</h3>
<?php
error_reporting(E_ALL);
ini_set("display_errors", 1);
$output = '320092 /usr/lib/firefox/firefox
229944 compiz
194588 compiz
193372 /usr/bin/X -core :1 -seat seat0 -auth /var/run/lightdm/root/:1 -nolisten tcp vt8 -novtswitch
159284 /home/kabalera/.dropbox-dist/dropbox-lnx.x86_64-3.2.9/dropbox
105004 /usr/bin/X -core :0 -seat seat0 -auth /var/run/lightdm/root/:0 -nolisten tcp vt7 -novtswitch';

$values = explode("\n", $output);
$columns = count($values);
$nums = array();
echo 'Values Count for new line is '.$columns.';  '.$values[1].';  '.$values[2].'<br />';
for($i=0;$i<$columns;$i++){$arySp = explode(" ", $values[$i]); $nums[] = (int) $arySp[0];}
$columns = count($nums);
echo 'Nums Count for spaces is '.$columns.';  '.$nums[0].'<br />';

$columns = count($nums);
$width = 300;
$height = 200;
$padding = 5;
$column_width = $width / $columns ;

$im = imagecreate($width,$height);
$gray = imagecolorallocate ($im,0xca,0xca,0xca);
$gray_lite = imagecolorallocate ($im,0xdd,0xdd,0xdd);
$gray_dark = imagecolorallocate ($im,0x5f,0x5f,0x5f);
$white = imagecolorallocate ($im,0xff,0xff,0xff);

imagefilledrectangle($im,0,0,$width,$height,$white);

$maxv = 6;
for($i=0;$i<$columns;$i++)$maxv = max($values[$i],$maxv);// Calculate the maximum

for($i=0;$i<$columns;$i++){
  $column_height = ( $values[$i] / $maxv) *198;
  $x1 = $i*$column_width;
  $y1 = $height-$column_height;
  $x2 = (($i+1)*$column_width)-$padding;
  $y2 = $height;
  imagefilledrectangle($im,$x1,$y1,$x2,$y2,$gray);

  imageline($im,$x1,$y1,$x1,$y2,$gray_lite);
  imageline($im,$x1,$y2,$x2,$y2,$gray_lite);
  imageline($im,$x2,$y1,$x2,$y2,$gray_dark);
  }

imagepng($im,'graf.png',9);
imagedestroy($im);
?>
<hr>
<img src="graf.png" alt="graph png"/>

</body></html>

Open in new window

This is a TEST Page in order to set up and TEST the parsing, AND see if the Image PNG building is giving expected graph.  IT CAN NOT BE USED WITH YOUR -
       header ("Content-type: image/png");
       imagepng($im);


BUT, once every thing is working, and test is over, you place only the relavent code in a php page with your -
       header ("Content-type: image/png");
       imagepng($im);

to deliver the png image, instead of the test web page.
0
 
Mark BullockQA Engineer IIICommented:
I don't see the code reading /tmp/memgraph.txt

Read the file, something like the following.  I don't know how you want to parse it.
$myfile = fopen("/tmp/memgraph.txt", "r") or die("Error opening file.");
while (!feof($myfile)) {
  $myline = fgets($myfile);
  echo $myline;
}
fclose($myfile);

Open in new window

0
 
kabaleraAuthor Commented:
Hi Mark, Hi Slick,

Thanks for the input.

@Slick, for the graph, i know i stuffed up with the  "/" i thought that it would parse the output of my file, obviously not.

Like i said before i am a novice in PHP but keen to learn. How do i display the name of the process in function of the amount of RAM that it is consuming on the graph?

Cheers.
Kab
0
 
kabaleraAuthor Commented:
Thank you very much for your patience and your great explanation.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.