it-swarm.com.ru

Проверка, запущен ли еще процесс?

В качестве способа создания сторожевого таймера бедного человека и обеспечения перезапуска приложения в случае его сбоя (пока я не выясню почему), мне нужно написать PHP CLI-скрипт, который будет запускаться cron каждые 5 минут до проверьте, запущен ли процесс.

Основываясь на этой странице , я попробовал следующий код, но он всегда возвращает True, даже если я вызываю его с поддельными данными:

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

Далее я попробовал этот код ...

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

... но не получить то, что я ожидаю:

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

Кстати, этот скрипт запускается с CLI-версией PHP 5.2.5, а операционной системой является uClinux 2.6.19.3.

Спасибо за любую подсказку.


Правка: кажется, работает нормально

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

Я бы использовал pgrep для этого (осторожно, непроверенный код):


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

    // lighttpd is not running!
}

У меня есть скрипт bash, который делает что-то подобное (но с 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

Вы можете изменить этот скрипт с помощью команд, которые вы хотите отслеживать.

20
mmattax

Если вы делаете это в php, почему бы не использовать php-код:

В запущенной программе:

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

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

Затем в программе watchdog все, что вам нужно сделать, это:

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

По сути, posix_kill имеет специальный сигнал 0, который на самом деле не отправляет сигнал процессу, но он проверяет, может ли сигнал быть отправлен (процесс на самом деле выполняется).

И да, я использую это довольно часто, когда мне нужны длительные (или, по крайней мере, наблюдаемые) процессы php. Обычно я пишу сценарии инициализации, чтобы запустить программу PHP, а затем имею сторожевой таймер cron, чтобы ежечасно проверять, работает ли он (и если нет, перезапустить его) ... 

33
ircmaxell

Вы можете попробовать это, который объединяет биты этих двух подходов:

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

Если это не сработает, вы можете просто попробовать запустить команду ps в своей системе и посмотреть, какой вывод это даст.

9
John Lawrence

Попробуй это

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

Функция проверяет, существует ли файл процесса в корневом каталоге /proc/. Работает только для Linux

7
Anatoly Rugalev
<?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";
}

?>
1
Softmixt

Я не видел здесь упомянутого, но вот еще один подход, позволяющий убрать второй grep из уравнения, я использую это со многими моими PHP скриптами и должен работать универсально 

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

Наслаждаться.

1
Destreyf

Основная проблема заключается в том, что если вы запустите скрипт php, команда exec будет выполняться от имени пользователя веб-сервера (www-data); этот пользователь не может видеть pid от других пользователей, если вы не используете "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");
?>

Больше информации о скрипте здесь http://umbru.ch/?p=328

1
Sven Lauber

у меня есть функция, чтобы получить pid процесса ...

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;
}
0
Sergey Eremin