Check if a process is running using PHP in Linux - php

I am using kannel to send SMS via PHP. I want to know how can I check if a particular process is running. For kannel to run, a process named bearerbox should be running all time. I want to check if this process is running or not. Because if the process is not running then a mail will be sent to me notifying me about it.

The easiest is to use pgrep, which has an exit code of 0 if the process exists, 1 otherwise.
Here's an example.
exec("pgrep bearerbox", $output, $return);
if ($return == 0) {
echo "Ok, process is running\n";
}

You can use the exec command to find your process and then act accordingly.
Something like:
exec('ps aux | grep bearerbox', $output);
You'll need to work out what is returned on your server to decide if it's running or not.
Good luck.

There are a lot of ways to deal with this. The easiest (and a direct answer to your question) is to grab the output of 'ps'.
Deamons tend to always create a 'pid' file though. This file contains the process-id of the daemon. If yours has that, you can check the contents of the file and see if the process with that id is still running. This is more reliable.
supervisord might also have this functionality. Lastly, maybe it's better to get a real monitoring system rather than build something yourself. Nagios might be a good pick, but there might be others.

Simple yet handy solution to monitor processes through PHP: PHP-Linux-Process-Monitor.
The code goals like:
$ps = explode("\n", trim(shell_exec('ps axo pid,ppid,%cpu,pmem,user,group,args --sort %cpu')));
foreach($ps AS $process){
$processes[]=preg_split('#\s+#', trim($process), 7 );
}
$head= array_shift($processes);
$processes = array_reverse($processes);
$output='';
foreach ($head AS $f) $output.="<td class=\"head\">$f</td>";
$output=sprintf('<tr class="head">%s</tr>',$output);
foreach($processes AS $p){
$output.='<tr>';
foreach ($p AS $i=>$f){
if($i==0) $output.=sprintf('<td>%1$s</td>',$f);
elseif($i==2) $output.=sprintf('<td class="cpu">%1$s<ins style="width:%1$s%%"></ins></td>',$f);
elseif($i==3) $output.=sprintf('<td class="mem">%1$s<ins style="width="%1$s%%"></ins></td>',$f);
elseif($i == 6) $output.=sprintf('<td class="command">%1$s</td>',$f);
else $output.=sprintf('<td>%1$s</td>',$f);
}
$output.='</tr>';
}
$cpu=implode(' ', sys_getloadavg());
$output=sprintf('<table data-cpu="%s" id="process">%s</table>',$cpu, $output);

This is the best way
<?php
exec("ps -eo comm,pid | awk '$1 == "."\"gs\""." { print $2 }'", $output);
if ($output != 0) {
echo "The process gs is running\n";
}
?>
in the above code gs is the process that I was checking

Related

Make sure one copy of php script running in background

I'm using cronjob to run php script that will be executed every 1 minute
I need also to make sure only of copy is running so if this php script is still running after 2 minutes, cronjob should not run another version.
currently I have 2 options and I would like to see your feedback and if you have any more options
Option 1: create a tmp file when the php script start and remove it when php script finish (and check if the file exists) ---> the problem for me with this option is that if I have my php script crash for any reason, it will not run again (the tmp file will not be deleted)
Option 2: run a bash script like the one below to control the php script execution ---> good but looking for something that can be done within php
#!/bin/bash
function rerun {
BASEDIR=$(dirname $0)
echo $BASEDIR/$1
if ps -ef | grep -v grep | grep $1; then
echo "Running"
exit 0
else
echo "NOT running";
/usr/local/bin/php $BASEDIR/$1 &
exit $?
fi
}
rerun myphpscript.php
PS: I just saw "Mutex class" at http://www.php.net/manual/en/class.mutex.php but not sure if it's stable and anyone tried it.
You might want to use my library ninja-mutex which provides simple interface for handling mutex. Currently it can use flock, memcache, redis or mysql to handle lock.
Below is an example which uses memcache:
<?php
require 'vendor/autoload.php';
use NinjaMutex\Lock\MemcacheLock;
use NinjaMutex\Mutex;
$memcache = new Memcache();
$memcache->connect('127.0.0.1', 11211);
$lock = new MemcacheLock($memcache);
$mutex = new Mutex('very-critical-stuff', $lock);
if ($mutex->acquireLock(1000)) {
// Do some very critical stuff
// and release lock after you finish
$mutex->releaseLock();
} else {
throw new Exception('Unable to gain lock!');
}
I often use the program flock that comes with many linux distributions directly in my crontabs like:
* * * * * flock -n /var/run/mylock.LCK /usr/local/bin/myprogram
Of cause it is still possible to actually start two simultaneously instances of myprogram if you do it by hand, but crond will only make one.
Flock being a small compiled binary, makes it super fast to launch compared to a eventually larger chunk of php code. This is especially a benefit if you have many longer running executions, which it is not perfectly clear that you actually have.
If you're not on a NFS mount, you can use flock() (http://php.net/manual/en/function.flock.php):
$fh = fopen('guestbook.txt','a') or die($php_errormsg);
$tries = 3;
while ($tries > 0) {
$locked = flock($fh,LOCK_EX | LOCK_NB);
if (! $locked) {
sleep(5);
$tries--;
} else {
// don't go through the loop again
$tries = 0;
}
}
if ($locked) {
fwrite($fh,$_REQUEST['guestbook_entry']) or die($php_errormsg);
fflush($fh) or die($php_errormsg);
flock($fh,LOCK_UN) or die($php_errormsg);
fclose($fh) or die($php_errormsg);
} else {
print "Can't get lock.";
}
From: http://docstore.mik.ua/orelly/webprog/pcook/ch18_25.htm
I found the best solution for me is creating a separate database user for your Script and limit the concurent connection to 1 for that user.

Passing a variable through to another PHP page

I'm making a server manager. I want to add a "kill" command, which would call a php script that would essentially run a shell_exec('kill $arrtext'); and kill the process, thus closing the server down. Here is the part of my script that returns the results and checks to see which servers are running:
<?php
$COMMAND = shell_exec('ps -o command ax | grep skulltag | grep -v grep');
$old = array("skulltag-server", "-port", "-iwad", "-wad", "+exec");
$new = array("SKULLTAG", "Running on Port", "Using IWAD", "+ PWAD", "with Config");
$COMMAND = str_replace($old, $new, $COMMAND);
$arr = explode("./",$COMMAND);
$text = shell_exec('pgrep -u doom');
$arrtext = preg_split('/\s+/', $text);
for( $i = 1; $i < count($arr); $i++ ) {
echo '<div class = "serverborder">';
echo '<div class = "servertextalign">';
echo $i,'. PROCESS ID <span style="color: #f00;">',$arrtext[$i],'</span> with server parameters: <span style="color: #777;">',$arr[$i],'</span>';
echo '</div>';
echo '</div>';
echo '<br>';
}
?>
However, I have no idea how I would add a link or something that would set the proper $arrtext[] variable (depending on which one they picked) and pass it to the PHP script that would kill the server.
The live demo can be found at http://server.oblivionro.net/servers/
Thanks!
Could you try using a shell_exec in another, tiny, script to run that kill script in the command line? Don't use a GET variable. I would rather create a small form for each server in the list and passing it through POST ie. requiring the tiny script that takes hidden POST variables, sending the form action to the same page, and passing the array as a parameter
// In form
echo '<input type="hidden" name="pid" value="'.$arrtext[$i].'"/>';
// In script
$pid = $_POST['pid'];
shell_exec('php -f /location/of/kill_script.php -- -'. $pid)
Where pid is your process ID. Obviously, you should set up your kill script to check that the pid is valid. The benefit of this is that the script's true location can stay hidden and doesn't need even need to be in the www root. You shouldn't need to link the real script directly.
The dirty, dirty (not recommended) way to do it is to have the link go to the script with the command, like:
KILL
Then in the killScript, you RIGOROUSLY verify that the process they are killing something they're supposed to be killing.
A better way would be to avoid using as powerful a command as "kill", so that someone doesn't go to killScript.php?p=1230 where 1230 is the process number of your Minecraft game or something...
I am confused why you feel the need to ask since you seem to have a grasp of PHP scripting and already create spans etc with the proper data. it is trivial to construct an anchor tag. The anchor tag might reference a GET variable, which could be the PID. After proper validation such as ensuring the PID references a doom server process (and proper login credentials), the PID can then be used to shell a kill command.
Note that you are potentially opening your server up to allow the world to shut down processes on your server.

PHP/Cron Limit Number of Concurrently Running Scripts

I have a script written in PHP that is kicked off by a cron job. It's a long running script, and often cron kicks off another instance before the last is finished. That's fine. I allow 3 instances of this script to run at any given time.
I limit the script to 3 instances with this code at the top of the script:
exec('ps -A | grep nameofmyscript', $results);
if (count($results) > 4) {
echo "Already Running\n"
die(0);
}
It works, but I'm looking for a better way. This approach backfired on me a few weeks back when I renamed the script, and forgot to change that line of code. It also fails when the script is named something similar to an already running process.
Using PHP, you could create a randomly named lock file in a directory specific to the cron job. Check for the number of lock files that exist in the directory before letting the PHP script continue. This may not be the best solution though.
You could automate the name placement...
exec('ps -A | grep ' . escapeshellarg(basename(__FILE__)) , $results);
if (count($results) > 4) {
echo "Already Running\n"
die(0);
}

Killing processes opened with popen()?

I'm opening a long-running process with popen(). For debugging, I'd like to terminate the process before it has completed. Calling pclose() just blocks until the child completes.
How can I kill the process? I don't see any easy way to get the pid out of the resource that popen() returns so that I can send it a signal.
I suppose I could do something kludgey and try to fudge the pid into the output using some sort of command-line hackery...
Well, landed on a solution: I switched back to proc_open() instead of popen(). Then it's as simple as:
$s = proc_get_status($p);
posix_kill($s['pid'], SIGKILL);
proc_close($p);
Just send a kill (or abort) signal using kill function:
php http://php.net/manual/en/function.posix-kill.php
c/c++ http://linux.die.net/man/3/kill
You can find the pid, and checks that you're really its parent by doing:
// Find child processes according to current pid
$res = trim(exec('ps -eo pid,ppid |grep "'.getmypid().'" |head -n2 |tail -n1'));
if (preg_match('~^(\d+)\s+(\d+)$~', $res, $pid) !== 0 && (int) $pid[2] === getmypid())
{
// I'm the parent PID, just send a KILL
posix_kill((int) $pid[1], 9);
}
It's working quite well on a fast-cgi PHP server.

Error handling for popen

I am using popen in PHP to execute a TCL file .
$cmd='C:/wamp/www/Tcl/bin/tclsh84.exe'; //windows
$ph = popen($cmd,'w')
But if someone restarts the machine or the tclsh84.exe process is killed . How do I know this error condition has occured ?
$ph is not returning 0 in these conditions.
Regards,
Mithun
you see the documentation of the tasklist utility from there. This utility is a kind of task manager in command line (a bit less feature since you can only list process and not affect them). Having that utility accessible on your server, you can use exec function to get list of process and work with that.
a probable code would be something like that:
function isTCLRunning(){
$running = false;
exec('tasklist.exe /fo CSV /fi tclsh84.exe', $output);
return count($output) == 1
}
note: this is completly untested you might want to play a bit with tasklist and make sure it is returning expected output before starting to code your PHP function.

Categories