如何同时(同步)运行 2 个 PHP 脚本来监控 popen 命令?
我有一个脚本启动这样的命令:
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 每 1000 毫秒调用一次监听器 (listener.php)。 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);
}
});
}
编辑 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);
}
最佳答案
杰里米,
几个月前,我回答了一个关于在 *NIX/PHP 环境中运行服务器端批处理作业的类似问题。如果我理解正确,您的要求会有所不同,但答案中可能会有一些帮助。
Run a batch file from my website
编辑
这是您的客户端代码的修改版本。您会看到我所做的主要更改是:
- 将
listen(jobid);
移动到 backup_launch 的成功处理程序中。 - 添加错误处理程序以便您可以观察错误。
其他一切都只是编程风格的问题。
function backup_launch(jobid) {
x(['jobid: ' + jobid, 'on state', state].join(' '));
$.ajax({
url: 'backup.manager.php',
data: {
'json': 1,
'jobid': jobid,
'state': state
}
dataType: 'json',
success:function(data) {
state = 3;
x("Job started: " + jobid);
listen(jobid);
x("Listener launched: " + jobid);
},
error: function(jqXHR, textStatus, errorThrown) {
x(["backup.manager error", textStatus, errorThrown, jobid].join(": "));
}
});
}
function listen(jobid) {
$.ajax({
url: 'backup.listener.php',
data: {
'json': 1
'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].join(' '));
timeout = setTimeout(function() {
listen(jobid);
}, 500);
},
error: function(jqXHR, textStatus, errorThrown) {
x(["Listener error", textStatus, errorThrown, jobid].join(": "));
}
});
}
关于php - 如何同时(非阻塞)运行 2 个 PHP 脚本来监视 popen 命令?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14289547/