我需要在用户操作时执行目录副本,但目录非常大,所以我希望能够执行这样的操作,而无需用户知道副本完成所需的时间.
任何建议将不胜感激.
假设这是在Linux机器上运行的,我总是像这样处理它:
exec(sprintf("%s > %s 2>&1 & echo $! >> %s", $cmd, $outputfile, $pidfile));
这将启动命令$cmd
,将命令输出重定向到$outputfile
,并将进程ID写入$pidfile
.
这使您可以轻松监控进程正在执行的操作以及它是否仍在运行.
function isRunning($pid){ try{ $result = shell_exec(sprintf("ps %d", $pid)); if( count(preg_split("/\n/", $result)) > 2){ return true; } }catch(Exception $e){} return false; }
exec(sprintf("$ s> $ s 2>&1&echo $ 1",$ cmd,$ outputfile),$ pidArr); code>生成的进程PID在$ pidArr [0]中
Kaiesh做了一个错字,'$'而不是'%'.更正版本:exec(sprintf("%s>%s 2>&1&echo $!",$ cmd,$ outputfile),$ pidArr)
sudo设置是否在没有提示输入密码的情况下运行?任何需要用户输入的命令都不起作用.
@Kaiesh:它应该是"echo $!"
如果要处理退出代码,只需将第一个“%s`”替换为“`(%s; printf \” \\ n $?\“)`”。这会将命令的退出代码放在日志的最后一行。
2> Eric Goodwin..:
将进程编写为服务器端脚本,无论使用何种语言(php/bash/perl/etc)都很方便,然后从php脚本中的进程控制函数中调用它.
该函数可能检测到标准io是否用作输出流,如果是,那么它将设置返回值..如果不是那么它结束
Proc_Close (Proc_Open ("./command --foo=1 &", Array (), $foo));
我使用"sleep 25s"作为命令从命令行快速测试了它,它就像一个魅力.
(这里找到答案)
这是我可以让它在centos上工作的唯一方法.谢谢!
3> wlf..:
您可能想尝试将此附加到您的命令
>/dev/null 2>/dev/null &
例如.
shell_exec('service named reload >/dev/null 2>/dev/null &');
4> Captain Obvi..:
我想在Windows上添加一个非常简单的示例来测试此功能:
创建以下两个文件并将其保存到Web目录:
foreground.php:
loading page
";
function run_background_process()
{
file_put_contents("testprocesses.php","foreground start time = " . time() . "\n");
echo " foreground start time = " . time() . "
";
// output from the command must be redirected to a file or another output stream
// http://ca.php.net/manual/en/function.exec.php
exec("php background.php > testoutput.php 2>&1 & echo $!", $output);
echo " foreground end time = " . time() . "
";
file_put_contents("testprocesses.php","foreground end time = " . time() . "\n", FILE_APPEND);
return $output;
}
echo "calling run_background_process
";
$output = run_background_process();
echo "output = "; print_r($output); echo "
";
echo "end of page
";
?>
background.php:
file_put_contents("testprocesses.php","background start time = " . time() . "\n", FILE_APPEND);
sleep(10);
file_put_contents("testprocesses.php","background end time = " . time() . "\n", FILE_APPEND);
?>
授予IUSR权限以写入您在其中创建上述文件的目录
授予IUSR READ和EXECUTE C:\ Windows\System32\cmd.exe的权限
从Web浏览器中点击foreground.php
应将以下内容呈现给浏览器w /输出数组中的当前时间戳和本地资源#:
loading page
calling run_background_process
foreground start time = 1266003600
foreground end time = 1266003600
output = Array
(
[0] => 15010
)
end of page
您应该在保存上述文件的同一目录中看到testoutput.php,它应该为空
您应该在保存上述文件的同一目录中看到testprocesses.php,它应该包含以下文本和当前时间戳:
foreground start time = 1266003600
foreground end time = 1266003600
background start time = 1266003600
background end time = 1266003610
5> 小智..:
如果你需要在没有PHP页面等待它完成的情况下在后台执行某些操作,可以使用wget命令"调用"的另一个(后台)PHP脚本.当然,这个后台PHP脚本将以特权执行,就像系统上的任何其他PHP脚本一样.
以下是使用wget from gnuwin32 packages的Windows上的示例.
背景代码(文件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
6> Alph.Dev..:
这是一个在PHP中启动后台进程的函数.在经过大量阅读和测试不同的方法和参数之后,最后创建了一个实际上也可以在Windows上运行的程序.
function LaunchBackgroundProcess($command){
// Run command Asynchroniously (in a separate thread)
if(PHP_OS=='WINNT' || PHP_OS=='WIN32' || PHP_OS=='Windows'){
// Windows
$command = 'start "" '. $command;
} else {
// Linux/UNIX
$command = $command .' /dev/null &';
}
$handle = popen($command, 'r');
if($handle!==false){
pclose($handle);
return true;
} else {
return false;
}
}
注1:在Windows上,不要使用/B
其他地方建议的参数.它强制进程与start
命令本身一起运行相同的控制台窗口,从而导致进程同步处理.要在单独的线程中运行该进程(异步),请不要使用/B
.
注意2:start ""
如果命令是带引号的路径,则需要后面的空双引号.start
command将第一个引用的参数解释为窗口标题.
7> Morfidon..:
好吧,我发现使用的版本更快更容易
shell_exec('screen -dmS $name_of_screen $command');
它的工作原理.