我需要在用户操作时执行目录复制,但目录相当大,因此我希望能够在用户不知道完成复制所需时间的情况下执行这样的操作。
任何建议都将不胜感激。
我需要在用户操作时执行目录复制,但目录相当大,因此我希望能够在用户不知道完成复制所需时间的情况下执行这样的操作。
任何建议都将不胜感激。
当前回答
用任何方便的语言(php/bash/perl/etc)将进程作为服务器端脚本编写,然后从php脚本中的进程控制函数调用它。
该函数可能会检测是否使用标准io作为输出流,如果是,则设置返回值,如果不是,则结束
proc_close( proc_open( "./command --foo=1 &", array(), $foo ) );
我在命令行中使用“sleep 25s”作为命令快速测试了这个功能,效果非常好。
(答案在这里)
其他回答
如果你只需要在后台做一些事情,而不需要PHP页面等待它完成,你可以使用另一个(后台)PHP脚本,用wget命令“调用”。当然,与系统上的任何其他PHP脚本一样,这个后台PHP脚本将以特权执行。
下面是一个在Windows上使用gnuwin32包中的wget的例子。
后台代码(文件test-proc-bg.php)为例…
sleep(5); // some delay
file_put_contents('test.txt', date('Y-m-d/H:i:s.u')); // writes time in a file
前台脚本,调用…
$proc_command = "wget.exe http://localhost/test-proc-bg.php -q -O - -b";
$proc = popen($proc_command, "r");
pclose($proc);
你必须使用popen/pclose才能正常工作。
wget选项:
-q keeps wget quiet.
-O - outputs to stdout.
-b works on background
如果使用PHP,使用pcntl_fork有一个更简单的方法:
http://www.php.net/manual/en/function.pcntl-fork.php
我大量使用fast_cgi_finish_request()
结合使用闭包和register_shutdown_function()
$message ='job executed';
$backgroundJob = function() use ($message) {
//do some work here
echo $message;
}
然后注册这个闭包,在关闭之前执行。
register_shutdown_function($backgroundJob);
最后,当响应被发送到客户端时,您可以关闭到客户端的连接,并继续使用PHP进程:
fast_cgi_finish_request();
闭包将在fast_cgi_finish_request之后执行。
$消息在任何时候都不可见。您可以注册任意数量的闭包,但要注意脚本执行时间。 这将只在PHP作为一个快速CGI模块运行时工作(这是正确的吗?!)
您是否可以安排派生一个单独的进程,然后在后台运行您的副本?我已经有一段时间没有使用PHP了,但是函数pcntl-fork看起来很有前途。
一个适用于Windows和Linux的解决方案。在我的github页面上找到更多信息。
function run_process($cmd,$outputFile = '/dev/null', $append = false){
$pid=0;
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {//'This is a server using Windows!';
$cmd = 'wmic process call create "'.$cmd.'" | find "ProcessId"';
$handle = popen("start /B ". $cmd, "r");
$read = fread($handle, 200); //Read the output
$pid=substr($read,strpos($read,'=')+1);
$pid=substr($pid,0,strpos($pid,';') );
$pid = (int)$pid;
pclose($handle); //Close
}else{
$pid = (int)shell_exec(sprintf('%s %s %s 2>&1 & echo $!', $cmd, ($append) ? '>>' : '>', $outputFile));
}
return $pid;
}
function is_process_running($pid){
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {//'This is a server using Windows!';
//tasklist /FI "PID eq 6480"
$result = shell_exec('tasklist /FI "PID eq '.$pid.'"' );
if (count(preg_split("/\n/", $result)) > 0 && !preg_match('/No tasks/', $result)) {
return true;
}
}else{
$result = shell_exec(sprintf('ps %d 2>&1', $pid));
if (count(preg_split("/\n/", $result)) > 2 && !preg_match('/ERROR: Process ID out of range/', $result)) {
return true;
}
}
return false;
}
function stop_process($pid){
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {//'This is a server using Windows!';
$result = shell_exec('taskkill /PID '.$pid );
if (count(preg_split("/\n/", $result)) > 0 && !preg_match('/No tasks/', $result)) {
return true;
}
}else{
$result = shell_exec(sprintf('kill %d 2>&1', $pid));
if (!preg_match('/No such process/', $result)) {
return true;
}
}
}