Как способ создания сторожевого пса бедного человека и убедитесь, что приложение перезагрузилось, если оно сработает (пока я не выясню, почему), мне нужно написать скрипт PHP CLI, который будет выполняться cron каждые 5mn, чтобы проверить, выполняется ли процесс все еще работает.
Основываясь на этой странице , я попробовал следующий код, но он всегда возвращает 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>
FWIW, этот скрипт запускается с версией 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"; }
Я бы использовал pgrep
для этого (осторожный, непроверенный код):
exec("pgrep lighttpd", $pids); if(empty($pids)) { // lighttpd is not running! }
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 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
#!/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
Вы можете изменить этот скрипт с помощью команд, которые вы хотите контролировать.
Если вы делаете это в php, почему бы не использовать php-код:
В текущей программе:
define('PIDFILE', '/var/run/myfile.pid'); file_put_contents(PIDFILE, posix_getpid()); function removePidFile() { unlink(PIDFILE); } register_shutdown_function('removePidFile');
Затем в программе сторожевого таймера все, что вам нужно сделать, это:
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, чтобы проверить, работает ли она (и если не перезапустить ее) …
Вы можете попробовать это, в котором сочетаются биты этих двух подходов:
function processExists($processName) { $exists= false; exec("ps -A | grep -i $processName | grep -v grep", $pids); if (count($pids) > 0) { $exists = true; } return $exists; }
Если это не сработает, вы можете просто попробовать запустить команду ps в своей системе и посмотреть, какой результат она дает.
Попробуй это
function processExists ($pid) { return file_exists("/proc/{$pid}"); }
Функция проверяет, существует ли файл процесса в каталоге /proc/
root. Работает только для Linux
<?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"; } ?>
Основная проблема заключается в том, что если вы запустите 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
У меня есть функция, чтобы получить 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; }
Я не видел этого здесь, но вот еще один подход, взявший второй grep из уравнения, я использую это со многими своими PHP-скриптами и должен работать повсеместно
exec("ps aux | grep -i '[l]ighttpd -D'", $pids); if(empty($pids)) { print "Lighttpd not running!\n"; } else { print "Lighttpd OK\n"; }
Наслаждаться.
Чтобы проверить, запущен ли процесс по его имени, вы можете использовать pgrep
, например
$is_running = shell_exec("pgrep -f lighttpd");
или:
exec("pgrep lighttpd", $output, $return); if ($return == 0) { echo "Ok, process is running\n"; }
в соответствии с этим сообщением .
Если вы знаете PID процесса, вы можете использовать одну из следующих функций:
/** * 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")); }
Связано: Как проверить, работает ли указанный PID, не вызывая ps из PHP?