可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
As a way to build a poor-man's watchdog and make sure an application is restarted in case it crashes (until I figure out why), I need to write a PHP CLI script that will be run by cron every 5mn to check whether the process is still running.
Based on this page, I tried the following code, but it always returns True even if I call it with bogus data:
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;
}
#if(processExists("lighttpd"))
if(processExists("dummy"))
print("Exists\n")
else
print("Doesn't exist\n");
Next, I tried this code...
(exec("ps -A | grep -i 'lighttpd -D' | grep -v grep", $output);)
print $output;
... but don't get what I expect:
/tmp> ./mycron.phpcli
Arrayroot:/tmp>
FWIW, this script is run with the CLI version of PHP 5.2.5, and the OS is uClinux 2.6.19.3.
Thank you for any hint.
Edit: This seems to work fine
exec("ps aux | grep -i 'lighttpd -D' | grep -v grep", $pids);
if(empty($pids)) {
print "Lighttpd not running!\n";
} else {
print "Lighttpd OK\n";
}
回答1:
I'd use pgrep
to do this (caution, untested code):
exec("pgrep lighttpd", $pids);
if(empty($pids)) {
// lighttpd is not running!
}
I have a bash script that does something similar (but with SSH tunnels):
#!/bin/sh
MYSQL_TUNNEL="ssh -f -N -L 33060:127.0.0.1:3306 tunnel@db"
RSYNC_TUNNEL="ssh -f -N -L 8730:127.0.0.1:873 tunnel@db"
# MYSQL
if [ -z `pgrep -f -x "$MYSQL_TUNNEL"` ]
then
echo Creating tunnel for MySQL.
$MYSQL_TUNNEL
fi
# RSYNC
if [ -z `pgrep -f -x "$RSYNC_TUNNEL"` ]
then
echo Creating tunnel for rsync.
$RSYNC_TUNNEL
fi
You could alter this script with the commands that you want to monitor.
回答2:
If you're doing it in php, why not use php code:
In the running program:
define('PIDFILE', '/var/run/myfile.pid');
file_put_contents(PIDFILE, posix_getpid());
function removePidFile() {
unlink(PIDFILE);
}
register_shutdown_function('removePidFile');
Then, in the watchdog program, all you need to do is:
function isProcessRunning($pidFile = '/var/run/myfile.pid') {
if (!file_exists($pidFile) || !is_file($pidFile)) return false;
$pid = file_get_contents($pidFile);
return posix_kill($pid, 0);
}
Basically, posix_kill has a special signal 0
that doesn't actually send a signal to the process, but it does check to see if a signal can be sent (the process is actually running).
And yes, I do use this quite often when I need long running (or at least watchable) php processes. Typically I write init scripts to start the PHP program, and then have a cron watchdog to check hourly to see if it's running (and if not restart it)...
回答3:
You can try this, which combines bits of those two approaches:
function processExists($processName) {
$exists= false;
exec("ps -A | grep -i $processName | grep -v grep", $pids);
if (count($pids) > 0) {
$exists = true;
}
return $exists;
}
If that doesn't work, you may want to just try running the ps command on your system and seeing what output it gives.
回答4:
Try this one
function processExists ($pid) {
return file_exists("/proc/{$pid}");
}
Function checks whether process file is exists in /proc/
root directory. Works for Linux only
回答5:
<?php
function check_if_process_is_running($process)
{
exec("/bin/pidof $process",$response);
if ($response)
{
return true;
} else
{
return false;
}
}
if (check_if_process_is_running("mysqld"))
{
echo "MySQL is running";
} else
{
echo "Mysql stopped";
}
?>
回答6:
The main problem is the if you run a php script, the exec command will be run as the web-servers user (www-data); this user can't see pid's from other users, unless you use "pidof"
<?php
//##########################################
// desc: Diese PHP Script zeig euch ob ein Prozess läuft oder nicht
// autor: seevenup
// version: 1.3
// info: Da das exec kommando als apache user (www-data) ausgefuert
// wird, muss pidof benutzt werden da es prozesse von
// anderen usern anzeigen kann
//##########################################
if (!function_exists('server_status')) {
function server_status($string,$name) {
$pid=exec("pidof $name");
exec("ps -p $pid", $output);
if (count($output) > 1) {
echo "$string: <font color='green'><b>RUNNING</b></font><br>";
}
else {
echo "$string: <font color='red'><b>DOWN</b></font><br>";
}
}
}
//Beispiel "Text zum anzeigen", "Prozess Name auf dem Server"
server_status("Running With Rifles","rwr_server");
server_status("Starbound","starbound_server");
server_status("Minecraft","minecarf");
?>
More information about the script here http://umbru.ch/?p=328
回答7:
i have a function to get the pid of a process...
function getRunningPid($processName) {
$pid = 0;
$processes = array();
$command = 'ps ax | grep '.$processName;
exec($command, $processes);
foreach ($processes as $processString) {
$processArr = explode(' ', trim($processString));
if (
(intval($processArr[0]) != getmypid())&&
(strpos($processString, 'grep '.$processName) === false)
) {
$pid = intval($processArr[0]);
}
}
return $pid;
}
回答8:
I didn't see this mentioned here, but here's another approach taking the second grep out of the equation, i use this with alot of my PHP scripts and should work universally
exec("ps aux | grep -i '[l]ighttpd -D'", $pids);
if(empty($pids)) {
print "Lighttpd not running!\n";
} else {
print "Lighttpd OK\n";
}
Enjoy.
回答9:
To check whether process is running by its name, you can use pgrep
, e.g.
$is_running = shell_exec("pgrep -f lighttpd");
or:
exec("pgrep lighttpd", $output, $return);
if ($return == 0) {
echo "Ok, process is running\n";
}
as per this post.
If you know the PID of the process, you can use one the following functions:
/**
* Checks whether the process is running.
*
* @param int $pid Process PID.
* @return bool
*/
public static function isProcessRunning($pid) {
// Calling with 0 kill signal will return true if process is running.
return posix_kill((int) $pid, 0);
}
/**
* Get the command of the process.
* For example apache2 in case that's the Apache process.
*
* @param int $pid Process PID.
* @return string
*/
public static function getProcessCommand($pid) {
$pid = (int) $pid;
return trim(shell_exec("ps o comm= $pid"));
}
Related: How to check whether specified PID is currently running without invoking ps from PHP?