2010-06-24 24 views
21

Como una forma de construir un perro guardián de un hombre pobre y asegurarme de que se reinicie una aplicación en caso de que falle (hasta que descubra por qué), necesito escribir un script CLI PHP que cron ejecutará cada 5mn para verificar si el proceso aún se está ejecutando.Comprobando si el proceso aún se está ejecutando?

Basado en this page, probé el siguiente código, pero siempre devuelve True incluso si la llamo con datos falsos:

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"); 

A continuación, he intentado this code ...

(exec("ps -A | grep -i 'lighttpd -D' | grep -v grep", $output);) 
print $output; 

... pero no obtengo lo que esperaba:

/tmp> ./mycron.phpcli 
Arrayroot:/tmp> 

FWIW, este script se ejecuta con la versión CLI de PHP 5.2.5, y el sistema operativo es uClinux 2.6.19.3.

Gracias por cualquier pista.


Editar: Esto parece funcionar bien

exec("ps aux | grep -i 'lighttpd -D' | grep -v grep", $pids); 
if(empty($pids)) { 
     print "Lighttpd not running!\n"; 
} else { 
     print "Lighttpd OK\n"; 
} 

Respuesta

21

que haría uso de pgrep para hacer esto (precaución, el código no probado):

 

exec("pgrep lighttpd", $pids); 
if(empty($pids)) { 

    // lighttpd is not running! 
} 
 

Tengo un script bash que hace algo similar (pero con túneles SSH):

 

#!/bin/sh 

MYSQL_TUNNEL="ssh -f -N -L 33060:127.0.0.1:3306 [email protected]" 
RSYNC_TUNNEL="ssh -f -N -L 8730:127.0.0.1:873 [email protected]" 

# 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 

 

Usted podría alterar esta secuencia de comandos con los comandos que desea supervisar.

+0

gracias a todos. Llamar a exec() con grep (pgrep no está disponible en el dispositivo integrado en el que estoy ejecutando esto) parece hacer el trabajo. – Gulbahar

+4

Pensé que compartiría un comentario rápido aquí. Probé 'pgrep' con' exec' como se muestra, Parece que el proceso de ejecución creará rápidamente otro proceso ... que tiene la misma cadena. Por lo tanto, siempre devuelve una única ID ... pensando quizás usando algo como 'if count = 2' ... Hasta ahora usar count = 2 funciona ... Pero solo una palabra de advertencia aquí ... – Mayhem

8

Puede probar esto, que combina fragmentos de esos dos enfoques:

function processExists($processName) { 
    $exists= false; 
    exec("ps -A | grep -i $processName | grep -v grep", $pids); 
    if (count($pids) > 0) { 
     $exists = true; 
    } 
    return $exists; 
} 

Si eso no funciona, es posible simplemente intente ejecutar el comando ps en su sistema y ver qué salida le da.

1

tengo una función para obtener el PID de un proceso ...

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; 
} 
+4

Eche un vistazo al pgrep ¡mando! – mmattax

29

Si lo estás haciendo en php, por qué no usar código PHP:

En el programa en ejecución:

define('PIDFILE', '/var/run/myfile.pid'); 

file_put_contents(PIDFILE, posix_getpid()); 
function removePidFile() { 
    unlink(PIDFILE); 
} 
register_shutdown_function('removePidFile'); 

Luego, en el programa de vigilancia, todo lo que tiene que hacer es:

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); 
} 

Básicamente, posix_kill tiene una señal especial 0 que en realidad no envía una señal al proceso, pero sí verifica si se puede enviar una señal (el proceso se está ejecutando realmente).

Y sí, lo uso con bastante frecuencia cuando necesito procesos php de larga ejecución (o al menos observables). Normalmente escribo guiones de inicio para iniciar el programa PHP, y luego tengo un cron watchdog para verificar cada hora para ver si se está ejecutando (y si no lo reinicio) ...

+0

Gracias por esta impresionante respuesta ircmaxell. ¿Cuál podría ser la diferencia entre! File_exists ($ pidFile) y! Is_file ($ pidFile) en este caso? – RafaSashi

+1

@RafaSashi: "file_exists - Comprueba si existe un archivo o directorio" ([link] (http://us1.php.net/manual/en/function.file-exists.php)). Así que si comprueba que existe y que es un archivo. –

2
<?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

prueba este

function processExists ($pid) { 
    return file_exists("/proc/{$pid}"); 
} 

función comprueba si el fichero de proceso es /proc/ existe en el directorio raíz. Obras para Linux solamente

+1

Para aclarar, esto solo funcionará necesariamente para Linux. No hay garantía de que otras cajas UNIX tengan un directorio/proc/ – Doug

1

No vi esta mencionado aquí, pero aquí es otro enfoque de tomar la segunda grep fuera de la ecuación, yo uso esto con muchos de mis scripts PHP y debería funcionar universalmente

exec("ps aux | grep -i '[l]ighttpd -D'", $pids); 
if(empty($pids)) { 
     print "Lighttpd not running!\n"; 
} else { 
     print "Lighttpd OK\n"; 
} 

Disfrútalo.

+0

. Esto siempre tendrá '$ pids' ya que el comando completo es uno. – maxisme

2

El problema principal es que si ejecuta un script php, el comando exec se ejecutará como el usuario de los servidores web (www-data); Este usuario no puede ver de PID de otros usuarios, a menos que utilice "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"); 
?> 

Más información sobre la secuencia de comandos aquí http://umbru.ch/?p=328

+2

No debe usar el idioma alemán en SO, incluso en el script ... – dogsgod

0

Para comprobar si el proceso se está ejecutando por su nombre, puede utilizar pgrep, p.ej

$is_running = shell_exec("pgrep -f lighttpd"); 

o:

exec("pgrep lighttpd", $output, $return); 
if ($return == 0) { 
    echo "Ok, process is running\n"; 
} 

según esta post.

Si conoce el PID del proceso, puede utilizar una de las siguientes funciones:

/** 
    * 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")); 
    } 

relacionados: How to check whether specified PID is currently running without invoking ps from PHP?

Cuestiones relacionadas