Here is how you'd use exec on a posix system to accomplish counting processes quickly.
I want to know how many processes are running with 'update.php' in the command:
ps aux|grep "[u]pdate.php"|wc -l
(the trick of using [u]pdate.php instead of update.php makes sure that the grep command itself is not matched). Be sure to use quotes in the command, or it won't work either.
So, the code:
<?php
function countProcesses($scriptName)
{
// ps aux|grep "[u]pdate.php"|wc -l
$first = substr($scriptName, 0, 1);
$rest = substr($scriptName, 1);
$name = '"['.$first.']'.$rest.'"';
$cmd = "ps aux | grep $name | wc -l";
$result = exec($cmd);
return $result;
}
?>
getmypid
(PHP 4, PHP 5)
getmypid — PHP のプロセス ID を取得する
説明
int getmypid
( void
)
現在の PHP プロセスの ID を取得します。
返り値
現在の PHP のプロセス ID を返し、エラーの場合は FALSE を返します。
注意
警告
プロセス ID は一意ではなく、エントロピ源として優れたものではありません。 セキュリティが問題となる状況では、PID に頼らないようにしましょう。
参考
- getmygid() - PHP スクリプトの所有者の GID を得る
- getmyuid() - PHP スクリプト所有者のユーザ ID を取得する
- get_current_user() - 現在の PHP スクリプトの所有者の名前を取得する
- getmyinode() - 現在のスクリプトの inode を取得する
- getlastmod() - 最終更新時刻を取得する
pdc at example dot com
29-Dec-2011 09:50
wouter99999 at gmail dot com
05-Jun-2011 12:03
On windows, ps is not available. Instead, to view a list of running processes, you can use exec('tasklist'); To kill processes you can use exec('taskkill); Enter taskkill /? for more information.
Robert Mays Jr
04-May-2011 06:39
All of the examples above require you to have shell command execution turned on- this example uses only PHP functions and should work on any system (posix is included by default)-
the key is posix_getsid which will return FALSE if the processes does not exist.
<?php
$lockfile = sys_get_temp_dir() . '/myScript.lock';
$pid = file_get_contents($lockfile);
if (posix_getsid($pid) === false) {
print "process has died! restarting...\n";
file_put_contents($lockfile, getmypid()); // create lockfile
} else {
print "PID is still alive! can not run twice!\n";
exit;
}
?>
:-) perfect if you need to make sure a cron job or shell script has ended before it can be started again.
This works across users- if the cron job is started as 'root' your 'web user' can see if the process is still alive (useful for system status pages)
gabe at fijiwebdesign dot com
02-Feb-2010 06:53
Based on what james at voodoo dot co dot uk said, but modified for CLI scripts (ie: there is no $_SERVER).
<?php
/**
* Check for a current process by filename
* @param $file[optional] Filename
* @return Boolean
*/
function processExists($file = false) {
$exists = false;
$file = $file ? $file : __FILE__;
// Check if file is in process list
exec("ps -C $file -o pid=", $pids);
if (count($pids) > 1) {
$exists = true;
}
return $exists;
}
?>
james at voodoo dot co dot uk
25-Dec-2009 10:50
The 'ps' command has an option that can make filtering for a specific process more efficient. Using this the work of looking for matching processes can be made neater:
<?php
/*
Return an array of the pids of the processes that are running for the specific command
e.g.
returnPids('myprocess.php');
*/
function returnPids($command) {
exec("ps -C $command -o pid=",$pids);
foreach ($pids as $key=>$value) $pids[$key]=trim($value);
return $pids;
}
/*
Returns an array of the pids for processes that are like me, i.e. my program running
*/
function returnMyPids() {
return returnPids(basename($_SERVER["SCRIPT_NAME"]));
}
?>
e.g. to bomb out if I'm running already
if (count(returnMyPids())>1) exit;
Erickson Reyes ercbluemonday at yahoo dot com
10-Nov-2009 02:01
We also had this challenge in our company to prevent a php script in a cron job from overlapping each other.
We made this solution
<?php
// Initialize variables
$found = 0;
$file = basename(__FILE__);
$commands = array();
// Get running processes.
exec("ps w", $commands);
// If processes are found
if (count($commands) > 0) {
foreach ($commands as $command) {
if (strpos($command, $file) === false) {
// Do nothin'
}
else {
// Let's count how many times the file is found.
$found++;
}
}
}
// If the instance of the file is found more than once.
if ($found > 1) {
echo "Another process is running.\n";
die();
}
/**
*
* Regular process here...
*
*/
?>
Kevin Traas (ktraas- at -gmail dot com)
25-Sep-2009 10:51
Looking to create a lock-file mechanism for a cmd-line script?
Enjoy!
#!/usr/bin/php
<?php
define( 'LOCK_FILE', "/var/run/".basename( $argv[0], ".php" ).".lock" );
if( isLocked() ) die( "Already running.\n" );
# The rest of your script goes here....
echo "Hello world!\n";
sleep(30);
unlink( LOCK_FILE );
exit(0);
function isLocked()
{
# If lock file exists, check if stale. If exists and is not stale, return TRUE
# Else, create lock file and return FALSE.
if( file_exists( LOCK_FILE ) )
{
# check if it's stale
$lockingPID = trim( file_get_contents( LOCK_FILE ) );
# Get all active PIDs.
$pids = explode( "\n", trim( `ps -e | awk '{print $1}'` ) );
# If PID is still active, return true
if( in_array( $lockingPID, $pids ) ) return true;
# Lock-file is stale, so kill it. Then move on to re-creating it.
echo "Removing stale lock file.\n";
unlink( LOCK_FILE );
}
file_put_contents( LOCK_FILE, getmypid() . "\n" );
return false;
}
?>
kroczu at interia dot pl
19-Dec-2005 01:59
<?php
/*
mixed getpidinfo(mixed pid [, string system_ps_command_options])
this function gets PID-info from system ps command and return it in useful assoc-array,
or return false and trigger warning if PID doesn't exists
$pidifo=getpidinfo(12345);
print_r($pidifo);
Array
(
[USER] => user
[PID] => 12345
[%CPU] => 0.0
[%MEM] => 0.0
[VSZ] => 1720
[RSS] => 8
[TT] => ??
[STAT] => Is
[STARTED] => 6:00PM
[TIME] => 0:00.01
[COMMAND] => php someproces.php > logfile
)
*/
//////////////////////////////////////////////
function getpidinfo($pid, $ps_opt="aux"){
$ps=shell_exec("ps ".$ps_opt."p ".$pid);
$ps=explode("\n", $ps);
if(count($ps)<2){
trigger_error("PID ".$pid." doesn't exists", E_USER_WARNING);
return false;
}
foreach($ps as $key=>$val){
$ps[$key]=explode(" ", ereg_replace(" +", " ", trim($ps[$key])));
}
foreach($ps[0] as $key=>$val){
$pidinfo[$val] = $ps[1][$key];
unset($ps[1][$key]);
}
if(is_array($ps[1])){
$pidinfo[$val].=" ".implode(" ", $ps[1]);
}
return $pidinfo;
}
?>
Pure-PHP
21-Mar-2005 11:26
You can use this function also to avoid more than one instance of your app.
You can also use this class.
http://www.pure-php.de/node/20
Usage:
<?php
inlude("ProcessHandler.class.php");
if(ProcessHandler::isActive()){
die("Already running!\n";);
}else{
ProcessHandler::activate();
//run my app
}
?>
brooke at jump dot net
25-Oct-2003 02:49
One good use for this is deciding on a concurrency-safe temporary file or directory name. You can be assured that no two processes on the same server have the same PID, so this is enough to avoid collisions. For example:
<?php
$tmpfile = "/tmp/foo_".getmypid();
// Use $tmpfile...
// Use $tmpfile...
// Use $tmpfile...
unlink ($tmpfile);
?>
If you are sharing /tmp over the network (which is odd....) then you can, of course, mix in the PHP server's IP address.
