Avatar of kabalera
kabalera
 asked on

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

PHPShell Scripting

Avatar of undefined
Last Comment
kabalera

8/22/2022 - Mon
Member_2_248744

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.
Mark Bullock

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
kabalera

ASKER
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
I started with Experts Exchange in 2004 and it's been a mainstay of my professional computing life since. It helped me launch a career as a programmer / Oracle data analyst
William Peck
Member_2_248744

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.
Mark Bullock

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

kabalera

ASKER
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
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
ASKER CERTIFIED SOLUTION
Member_2_248744

THIS SOLUTION ONLY AVAILABLE TO MEMBERS.
View this solution by signing up for a free trial.
Members can start a 7-Day free trial and enjoy unlimited access to the platform.
See Pricing Options
Start Free Trial
GET A PERSONALIZED SOLUTION
Ask your own question & get feedback from real experts
Find out why thousands trust the EE community with their toughest problems.
kabalera

ASKER
Thank you very much for your patience and your great explanation.