popenコマンドを監視するために2つのPHPスクリプトを同時に(同期的に)実行するには?
次のようなコマンドを起動するスクリプトがあります。
7za a -t7z -mx9 backup.7z "H:\Informatique\*"
そして、jQuery と PHP を使用してページに圧縮の進行状況を表示したいと思います。
このコマンドを実行する php スクリプトは次のようになります。
if( ($fp = popen("7za a -t7z ".$GLOBALS["backup_compression"]." \"".$backuplocation.$backupname."\" \"".$pathtobackup."\"", "r")) ) {
while( !feof($fp) ){
$fread = fread($fp, 256);
$line_array = preg_split('/\n/',$fread);
$num_lines = count($line_array);
$_SESSION['job'][$jobid]['currentfile'] = $_SESSION['job'][$jobid]['currentfile']+$num_lines;
$num_lines = 0;
flush();
}
pclose($fp);
}
jQuery は 7za スクリプトを呼び出し、jquery はリスナー ( listener.php )を 1000ms ごとに呼び出します。listener.php ページには、次のコードが含まれています。
session_start();
$jobid = $_GET['jobid'];
if(!isset($_SESSION['job'][$jobid])) { $arr = array("error"=>"Job not found"); echo json_encode($arr); exit(); };
$arr = array(
"curfile" => $_SESSION['job'][$jobid]['currentfile'],
"totalfiles" => $_SESSION['job'][$jobid]['totalfiles'],
);
echo json_encode($arr);
$jobid = null;
$arr = null;
exit();
jquery 呼び出しが完了したら (リスナーを使用し、サーバーから応答を受け取りました)、次のような通常の方法で情報を表示します。$("currentfile").text(data['curfile']);
問題は、リスナーが最初のスクリプトが完了するのを待っている無限ループにあるということです...そしてそれはリスナーの仕事ではありません...すべての最後にリッスンしています...あなたが聞くとき、それは何が何であるかを知ることです.ハプニング。:P
何が起こっているのか、どうすればこの問題を解決できますか? または、この問題に対する新しいアプローチを手伝ってもらえますか?
いつものように、どんな提案も歓迎します。ありがとうございました。
編集
jQuery スクリプト:
function backup_launch(jobid) {
x('jobid: '+jobid+' on state '+state);
x('Listener launched');
listen(jobid);
timeout = setTimeout("listen('"+jobid+"')", 500);
$.ajax({
url:'backup.manager.php?json&jobid='+jobid+'&state='+state,
dataType:'json',
success:function(data)
{
state = 3;
}
});
}
function listen(jobid) {
$.ajax({
url:'backup.listener.php?json&jobid='+jobid,
dataType:'json',
success:function(data)
{
var curfile = data['curfile'];
var totalfiles = data['totalfiles'];
var p = curfile * 100 / totalfiles;
x('File '+curfile+' out of '+totalfiles+' progress%: '+p);
timeout = setTimeout("listen('"+jobid+"')", 500);
}
});
}
EDIT 2 Gearman (http://gearman.org/) を見つけましたが、これを実装する方法がまったくわからず、ポータブル/スタンドアロンである必要があります...調査してみます。
編集3
backup.manager.phpページの完全なコード。スクリプトは応答を正しく送信していますが、バックグラウンドでジョブを実行します。
listen.php ページは、コマンドが完了するのを待ってから結果を返します。
$jobid = isset($_GET['jobid']) ? $_GET['jobid'] : 0;
//Make sure jobid is specified
if($jobid == 0) { return; }
header("Connection: close");
@ob_end_clean();
ignore_user_abort();
ob_start();
echo 'Launched in backgroud';
$size = ob_get_length();
header("Content-Length: ".$size);
ob_end_flush();
flush();
$_SESSION['job'][$jobid]['currentfile'] = 0;
// 3. When app appove backup,
// - Write infos to DB
// - Zip all files into 1 backup file
$datebackup = time();
$bckpstatus = 1; //In progress
$pathtobackup = $_SESSION['job'][$jobid]['path'];
/*
$query = "INSERT INTO backups (watchID, path, datebackup, checksum, sizeori, sizebackup, bckpcomplete)
VALUES ($watchID, '{$path}', '{$datebackup}', '', '{$files_totalsize}', '', '{$bckpstatus}')";
$sth = $db->prepare($query);
$db->beginTransaction();
$sth->execute();
$db->commit();
$sth->closeCursor();
*/
$backupname = $jobid.".".$GLOBALS["backup_ext"];
$backuplocation = "D:\\";
if( ($fp = popen("7za a -t7z ".$GLOBALS["backup_compression"]." \"".$backuplocation.$backupname."\" \"".$pathtobackup."\"", "r")) ) {
while( !feof($fp) ){
$fread = fread($fp, 256);
$line_array = preg_split('/\n/',$fread);
$num_lines = count($line_array);
$_SESSION['job'][$jobid]['currentfile'] = $_SESSION['job'][$jobid]['currentfile']+$num_lines;
$num_lines = 0;
sleep(1);
flush();
}
pclose($fp);
}