貧乏人のウォッチドッグを構築し、クラッシュした場合にアプリケーションを再起動する方法として(理由がわかるまで)、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>
FWIW、このスクリプトはCLIバージョンPHP 5.2.5で実行され、OSは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!
}
私は似たようなことをする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
監視するコマンドを使用して、このスクリプトを変更できます。
あなたが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プログラムを開始するinitスクリプトを作成し、cronウォッチドッグを実行して、実行中かどうかを確認します(再起動しない場合)...).
これを試すことができます。これは、これら2つのアプローチのビットを組み合わせたものです。
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/
ルートディレクトリに存在するかどうかをチェックします。 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";
}
?>
私はこれをここで言及していませんでしたが、式から2番目のgrepを取り出す別のアプローチがあります。これを私のPHPスクリプトの多くで使用し、普遍的に動作するはずです
exec("ps aux | grep -i '[l]ighttpd -D'", $pids);
if(empty($pids)) {
print "Lighttpd not running!\n";
} else {
print "Lighttpd OK\n";
}
楽しい。
主な問題は、phpスクリプトを実行すると、execコマンドがWebサーバーユーザー(www-data)として実行されることです。 「pidof」を使用しない限り、このユーザーは他のユーザーからのpidを見ることができません。
<?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;
}