?
Solved

Find running process id using php within crontab (RHEL4)

Posted on 2009-04-20
9
Medium Priority
?
3,198 Views
Last Modified: 2013-12-16
I'm writing a php file that -via crontab- gets executed once every minute to send out mails. I'm not being able to device a method to prevent multiple instances of this program from running simultaneously. I only want ONE instance at a time.

My logic is:
1) Get all running processes using "ps auxwww" (plus some awk magic to get only pids for the specified file)
2) If there is more than one process running, meaning there is me, plus another process, exit gracefully.

The problem is that when I run this (see the code window below), I can ONLY see the process id of the currently running php file and none other. Even without filtering anything out, the output of ps auxw only has one process!

I'm guessing there is some sort of user permission thing going on. How can I go around this?

Thanks!

Context: Dedicated server running Red Hat Enterprise Linux 4 with PHP 5.2.9. I have root shell access.
<?php
// over simplified version
echo exec("ps auxw");
?>

Open in new window

0
Comment
Question by:poisa
  • 4
  • 2
  • 2
  • +1
9 Comments
 
LVL 14

Expert Comment

by:EMB01
ID: 24185934
Does your PHP script check a database?

What I do is add a field to whatever table gets checked by the script for a "processed_on". Then, in the first iteration, simply update the field with 00/00/00. Your script should only check for rows in the table that have a NULL value for the "processed_on" date. Then, when the iteration is complete, update the field again and fill it with the appropriate date like 04/20/09.

Please let me know if you have any questions.
0
 
LVL 2

Author Comment

by:poisa
ID: 24186227
EMB01, thanks for your answer, but my problem hasn't got to do with keeping track of what rows to deal with.

What I need is a way to prevent multiple instances of the program from running.

0
 
LVL 14

Expert Comment

by:EMB01
ID: 24186520
Sorry, I only know of the alternative I posted above. If you don't mind my asking, what's the problem if the script only runs a few lines before being told to continue or exit.

Here's a shell_exec class I found:
http://us.php.net/manual/en/function.shell-exec.php#59898

It's also been attached.

Sorry I can't help much more.
<?php
/**
 * @author     Ashraf M Kaabi
 * @name       Advance Linux Exec
 */
class exec {
    /**
     * Run Application in background
     *
     * @param     unknown_type $Command
     * @param     unknown_type $Priority
     * @return     PID
     */
    function background($Command, $Priority = 0){
       if($Priority)
           $PID = shell_exec("nohup nice -n $Priority $Command > /dev/null & echo $!");
       else
           $PID = shell_exec("nohup $Command > /dev/null & echo $!");
       return($PID);
   }
   /**
    * Check if the Application running !
    *
    * @param     unknown_type $PID
    * @return     boolen
    */
   function is_running($PID){
       exec("ps $PID", $ProcessState);
       return(count($ProcessState) >= 2);
   }
   /**
    * Kill Application PID
    *
    * @param  unknown_type $PID
    * @return boolen
    */
   function kill($PID){
       if(exec::is_running($PID)){
           exec("kill -KILL $PID");
           return true;
       }else return false;
   }
};
?> 

Open in new window

0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
LVL 9

Accepted Solution

by:
tkalchev earned 2000 total points
ID: 24202156
Assuming your script is called mailerscript.php

crontab :

* * * * * [ -z "$(ps ax|grep mailerscript.php|grep -v grep)" ] && mailerscript.php
0
 
LVL 2

Author Comment

by:poisa
ID: 24251606
EMB01: "If you don't mind my asking, what's the problem if the script only runs a few lines before being told to continue or exit."

There's no problem at all with that. The real problem is that in my environment, the class you suggest will never work as it relies on exec("ps $PID", $ProcessState) to know whether a process is running or not.
As mentioned in my initial post, executing that command will return ONLY the currently running process and NOTHING else.

tkalchev, I still need to try your option out. Could you explain a little bit what it does? I'm not very proficient  in shell scripts and I'm not sure what the -z, the brackets, the && and the "$" do.
0
 
LVL 9

Expert Comment

by:tkalchev
ID: 24251738
ps ax - gives a list of all running processes
grep mailerscript.php - displays only the lines, which contain "mailerscript.php"
grep -v grep - filters the word "grep" out

$(xxx) - executes a command and returns its output, same as `xxx`, but at least for me looks much clear

-z  - tests if the following string is empty
&& - executes the following command is the result of the previous one is zero ( http://www.gnu.org/software/bash/manual/bashref.html#Lists ). Same as
if [ -z "$(ps ax|grep mailerscript.php|grep -v grep)" ]; then
  malerscript.php
fi ,but much more compact :)

So the meaning of the expression is the following :
Give me the list of all running processes, containing "mailerscript.php" and not containing "grep" and if this list is empty, execute mailerscript.php
0
 
LVL 2

Author Closing Comment

by:poisa
ID: 31572278
I ended up tweaking this a little but your suggestion did work. Thanks!
0
 
LVL 2

Expert Comment

by:mriz81
ID: 30096468
This is the function that tell is a process is running or not.
function processExists($process)
 {
		// Check if file is in process list
		exec("ps -ef|grep $process|grep -v grep", $pids);
		if (count($pids) >= 1)
		{
			$pids[0] = implode(" ", array_filter(explode(" ", $pids[0])));			
			$data = explode(" ", $pids[0]);
			if( isset($data[1]) )
			{
				echo($file . " executing with pid " . $data[1]);
				exit();
			}
		}
		echo($file . " not executing.");
}

Open in new window

0
 
LVL 2

Author Comment

by:poisa
ID: 30130163
mriz81,

Your function relies on exec() too. Won't work for my setup.
0

Featured Post

Visualize your virtual and backup environments

Create well-organized and polished visualizations of your virtual and backup environments when planning VMware vSphere, Microsoft Hyper-V or Veeam deployments. It helps you to gain better visibility and valuable business insights.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

In part one, we reviewed the prerequisites required for installing SQL Server vNext. In this part we will explore how to install Microsoft's SQL Server on Ubuntu 16.04.
The title says it all. Writing any type of PHP Application or API code that provides high throughput, while under a heavy load, seems to be an arcane art form (Black Magic). This article aims to provide some general guidelines for producing this typ…
Learn how to find files with the shell using the find and locate commands. Use locate to find a needle in a haystack.: With locate, check if the file still exists.: Use find to get the actual location of the file.:
This demo shows you how to set up the containerized NetScaler CPX with NetScaler Management and Analytics System in a non-routable Mesos/Marathon environment for use with Micro-Services applications.
Suggested Courses

809 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question