Linux : Get total cpu usage by httpd - php

I need to display the total Percentage of CPU utilized by httpd processes on a server in a php report.
I am calling following from exec :
ps -e -o %mem,%cpu,cmd | grep httpd | awk ' {memory+=$1;cpu+=$2} END {printf("%05.2f ",memory);printf("%05.2f\n",cpu)}'
But the above command's reported CPU usage and the one reported by top command are not matching.
I need to report --> If CPU is busy at 40%, 10% of httpd processes, 20% of mysqld processes, 10% of perl processes, then I need to report the 10% of httpd. (Assuming that there are no other processes).
I saw this : get apache total cpu usage in (linux)
But I understand that ps command returns the percentage of CPU consumed by a process out of the total percentage of CPU consumed. I understand that it is getting messy, so the below example should help.
If httpd is consuming 10% of CPU which is busy at 60% then the actual contribution of httpd to make CPU busy was ((100/60)*10) = 16.66 %. Is this correct? What else are the best way to get cpu usage by a group of processes by the same name.

try this in ssh
ps aux | grep "httpd" | awk '{sum1 +=$3}; END {print sum1}'
output is:
10.5
and this for sum of memory
ps aux | grep "httpd" | awk '{sum1 +=$4}; END {print sum1}'

I'm not 100% sure on what you're asking, but if I'm right, this answer might help you:
<?php
exec('ps -aux', $processes);
foreach($processes as $process){
$cols = split(' ', ereg_replace(' +', ' ', $process));
if (strpos($cols[2], '.') > -1){
$cpuUsage += floatval($cols[2]);
}
}
print($cpuUsage);
?>
and after searching many forms also found the another way:
after searching on forums and trying many methods but I have not tried it:
$stat1 = file('/proc/stat');
sleep(1);
$stat2 = file('/proc/stat');
$info1 = explode(" ", preg_replace("!cpu +!", "", $stat1[0]));
$info2 = explode(" ", preg_replace("!cpu +!", "", $stat2[0]));
$dif = array();
$dif['user'] = $info2[0] - $info1[0];
$dif['nice'] = $info2[1] - $info1[1];
$dif['sys'] = $info2[2] - $info1[2];
$dif['idle'] = $info2[3] - $info1[3];
$total = array_sum($dif);
$cpu = array();
foreach($dif as $x=>$y) $cpu[$x] = round($y / $total * 100, 1);

This works for me on OSX:
<?php
exec('ps -e -o %mem,%cpu,command | grep httpd', $output);
$proc_data = [];
foreach($output as $key => $value) {
// Make sure it's only path httpd and not the grep included
if (strstr($value, '/httpd')) {
$info = explode(' ', trim($value), 5);
unset($info[1]);
unset($info[2]);
$proc_data[] = array_merge($info);
}
}
echo '<pre>';
print_r($proc_data);
echo '</pre>';
// Caclulate total CPU percentages
$total_cpu = 0;
foreach ($proc_data as $key => $value) {
$total_cpu += $value[1];
}
echo $total_cpu;
?>
This is the Terminal output for the bash:
MacBook-Pro:~ user$ ps -e -o %mem,%cpu,command | grep httpd
0,2 0,0 /Applications/MAMP/Library/bin/httpd -k start
0,0 0,0 /Applications/MAMP/Library/bin/httpd -k start
0,1 0,0 /Applications/MAMP/Library/bin/httpd -k start
0,0 0,0 /Applications/MAMP/Library/bin/httpd -k start
0,1 0,0 /Applications/MAMP/Library/bin/httpd -k start
0,0 0,0 /Applications/MAMP/Library/bin/httpd -k start
0,0 0,0 /Applications/MAMP/Library/bin/httpd -k start
0,0 0,0 /Applications/MAMP/Library/bin/httpd -k start
0,0 0,0 /Applications/MAMP/Library/bin/httpd -k start
0,0 0,0 /Applications/MAMP/Library/bin/httpd -k start
0,0 0,0 /Applications/MAMP/Library/bin/httpd -k start
0,0 9,0 /Applications/MAMP/Library/bin/httpd -k start
0,0 0,0 grep httpd
I noticed ps -e -o %mem,%cpu,cmd has to be command, but it might be an OSX-only thing tho. Hope you can work with this.
Good luck!

Related

how to get the status of the particular process by the shell_exec()?

I want to know the status of the process by passing the name in the command and execute it with the function shell_exec().
I have tried this:
`
$checkProcessStatus = "ps aux | grep <ProcessName>";
$status = shell_exec($checkProcessStatus);
dd($status);
`
I got this result:
`
user 17072 0.0 0.2 166216 33332 pts/3 S+ 11:31 0:00 <ProcessName> artis
user 20397 0.0 0.0 14232 868 pts/3 S+ 11:52 0:00 grep <ProcessName>
`
I want only the Status Like "Running" OR "Sleeping".
Here is the working code:
<?php
$command = 'ps aux';
$result = shell_exec($command);
//split for rows
$processes = explode("\n", $result);
//delete head row
array_shift($processes);
//analyze
foreach ($processes as $rawProcess) {
//beware, command line column may include spaces, that why last group is (.+)
preg_match('/(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(.+)/', $rawProcess,$matches);
//preg match doesn't find anything
if (empty($matches)) {
continue;
}
//is sleeping status
if (strpos($matches[8], 'S') === 0) {
echo $rawProcess;
echo "\n";
continue;
}
//is running status
if (strpos($matches[8], 'R') === 0) {
echo $rawProcess;
echo "\n";
continue;
}
//is not sleeping and not running status
}
You can use $matches[N] for any column.
By the way you can use awk to grep data by status
ps aux | awk 'substr($8,1,1) == "S" || substr($8,1,1) == "R"'
P.S.
Status mean:
D uninterruptible sleep (usually IO)
R running or runnable (on run queue)
S interruptible sleep (waiting for an event to complete)
T stopped by job control signal
t stopped by debugger during the tracing
W paging (not valid since the 2.6.xx kernel)
X dead (should never be seen)
Z defunct ("zombie") process, terminated but not reaped by its parent
Status addition mean
< high-priority (not nice to other users)
N low-priority (nice to other users)
L has pages locked into memory (for real-time and custom IO)
s is a session leader
l is multi-threaded (using CLONE_THREAD, like NPTL pthreads do)
+ is in the foreground process group

send output of a shell command launched from script to a log file

I have a php page that creates a shell script that the same php page starts after creating it, inside I have one of many commands that I want to send the process to a log that does not work while others actually work....
<php
$scriptfile = script.sh;
$logfile = process.log;
$imgfile = image.ppm;
//this one works, it sends the output to the log file
$cmd ="Scripts/convert.sh file.doc > $logfile \\\n";
file_put_contents($scriptfile, $cmd, FILE_APPEND | LOCK_EX);
//this one does not work, it does not send the output to the log file and stops the process
$cmd = "&& for i in $(seq --format=%003.f 0 $(( $(ls -1 | wc -l) -1 )) ); do echo doing OCR on page \$i; tesseract $imgfile-\$i.ppm $imgfile-\$i -l eng; done >> $logfile";
file_put_contents($scriptfile, $cmd, FILE_APPEND | LOCK_EX);
$cmd = "/bin/sh $scriptfile > /dev/null 2>&1 &";
shell_exec($cmd);
?>
I have tried the not working command from the shell and it does send the output to the log file, either this way:
for i in $(seq --format=%003.f 0 $(( $(ls -1 | wc -l) -1 )) ); do echo doing OCR on page $i; tesseract image-$i.ppm image-\$i -l eng; done >> process.log
or this way:
for i in $(seq --format=%003.f 0 $(( $(ls -1 | wc -l) -1 )) ); do echo doing OCR on page $i >> process.log; tesseract image-$i.ppm image-\$i -l eng; done
And here you have the way the shell script looks like after being created by php:
#! /bin/sh
Scripts/convert.sh file.doc >> process.log \
&& for i in $(seq --format=%003.f 0 $(( $(ls -1 | wc -l) -1 )) ); do echo doing OCR on page $i; tesseract image-000.ppm image-$i -l eng; done >> process.log
So my question is, what can be wrong, I've tried many different things already but no success unfortunately, any help or advice will be very welcomed!! thanks from now!!

Need a way to selectively kill sleeping php processes

I have a website that periodically gets a large number of sleeping php processes. My hosting service sets a limit of 20 concurrent running processes. If it goes over the limit my site goes down with a 503 error.
It is a rare occurrence and doesn't seem to have any correlation to the number of people visiting my site.
As a safeguard I would like to have a cron job with a php script that would kill php processes that have been sleeping for over 10 min.
I have a php function that will kill all sleeping MySql processes that have been sleeping for more than 10 min;
public function kill_sleeping_mysql_processes()
{
$result = $this->db->query("SHOW FULL PROCESSLIST");
foreach($result->result_array() as $row)
{
if ($row['Command'] == "Sleep" && $row['Time'] > 600)
{
$this->db->query("KILL {$row['Id']}")
}
}
}
The question is how can do I do the same with php processes?
I can get a read out of php processes with this code.
exec("ps aux | less", $output);
and I can kill specific php processes with this code if I have the pid;
$pid = 11054;
exec("kill -9 $pid");
But how can I selectively kill php processes that have been sleeping more than 10 min?
I cobbled something together. It is not elegant and is a bit of a hack but it seems to work, although I am going to test it further before putting in a cron job.
public function kill_dormant_php_processes()
{
$output_array = array();
exec("ps aux | grep -v grep", $ps_output);
array_shift($ps_output);
if (count($ps_output) > 0)
{
$i = 0;
foreach ($ps_output as $ps)
{
$ps = preg_split('/ +/', $ps);
$output_array[$i]->pid = $ps[1];
$output_array[$i]->stat = $ps[7];
$output_array[$i]->time = $ps[9];
$i++;
}
}
if( ! empty($output_array))
{
foreach ($output_array as $row)
{
if( $row->stat == 'S' && date('H:i', strtotime($row->time)) > date('H:i', strtotime('00:01')))
{
exec("kill -9 $row->pid");
}
}
}
}
I am sure there must be a better way to do it.
Could someone explain why 00:01 in the read out seems to translate to 6 min?
freedom 6933 6.0 0.1 57040 13040 ? S 16:55 0:01 /usr/local/bin/php53.cgi -c .:/home/freedom/:/etc index.php
As an alternative to the PHP script shared here, you can use the killall command with an "older than" time filter (using the -o option) to kill all those processes.
This command for example will kill all php-cgi processes that have been running for more than 30 minutes:
killall -o 30m /usr/bin/php-cgi

linux printing via lp, how I can print more than one copy?

I need to print a (custom) number of copies on a DYMO-450 labelprinter, using a apache based local linux server, running php, wkhtmltopdf, xvfb and stuff...
If have trouble with giving a number of copies to the print job. Normally it shout be done with
lp -d PRINTER DOCUMENT -n2 // or possibly -n 2
for 2 copies.
But the DYMO doesn't.
Currently I am am using this workaround, which does the job, but I am waiting up to 3 seconds between each printed label:
$printcmd = '';
for ( $p=0; $p < $_REQ['copies'] ; $p++ ) {
if ($p>0) $printcmd .= '&& ';
$printcmd .= 'lp -d ' . $cfg['labelprinter'] . ' ' . $pdf_file . ' > print.log 2>&1';
}
system($printcmd . ' &');
But this doesn't suck at all.
Any suggestions ?
The (late) answer is, adding -o Collate=True
lp -n num-copies -o Collate=True filename
thanks to http://www.cups.org/documentation.php/options.html

Parsing grep output

I'm trying to make a server manager and here is what I have so far:
<?php
$COMMAND = shell_exec('ps ax --format command | grep skulltag');
$arr = explode("./",$COMMAND);
$text = shell_exec('pgrep -u doom');
$arrtext = preg_split('/\s+/', $text);
for( $i = 1; $i < count($arr); $i++ ) {
echo $i,". PROCESS ID ",$arrtext[$i]," Command issued: ",$arr[$i];
echo '<br>';
}
?>
As you can see, I'm separating the $COMMAND string with ./ (file execution). However, for some reason at the end of the list there's this:
sh -c ps ax --format command | grep skulltag grep skulltag
Here is the full output for reference:
PROCESS ID 4793 Command issued: skulltag-server
PROCESS ID 4956 Command issued: skulltag-server -port 13000
PROCESS ID 4958 Command issued: skulltag-server -port 13001 sh -c
ps ax --format command | grep skulltag grep skulltag
What would be the easiest and most effective way to get rid of that line, and how would I do it? Thanks.
Change this:
ps ax --format command | grep skulltag
To this:
ps ax --format command | grep [s]kulltag
That way, the grep command itself contains the string '[s]kultag', which is not matched by the grep regular expression '[s]kultag'.
Also, two suggestions: 1. there's no guarantee that your initial ps | grep and your later pgrep will line up. Instead, use a single pgrep:
pgrep -afl skulltag
And 2. your for loop starts with 1, which will skip the process in arr[0].
Your php could be rewritten something like this:
$processes = explode("\n", shell_exec('pgrep -afl skulltag'));
foreach($processes as $i => $process) {
($pid, $command) = explode(' ',$process,2);
echo $i+1,". PROCESS ID ",$pid," Command issued: ",$command;
echo '<br>';
}
My quick and dirty solution is to append | grep -v grep to the command.

Categories