我正在编写一个 PHP 脚本网页,该网页旨在接受先前上传到服务器的 JFFS2 图像的文件名。然后,该脚本将使用映像重新刷新服务器上的分区,并输出结果。我一直在用这个:
$tmp = shell_exec("update_flash -v " . $filename . " 4 2>&1");
echo '<h3>' . $tmp . '</h3>';
echo verifyResults($tmp);
(verifyResults 函数将返回一些 HTML,向用户指示更新命令是否成功完成。即,在更新成功完成的情况下,显示重新启动设备的按钮等)
这样做的问题是更新命令需要几分钟才能完成,并且 PHP 脚本会阻塞,直到 shell 命令完成才返回任何输出。这通常意味着更新命令将继续运行,而用户将看到 HTTP 504 错误(最坏的情况)或等待页面加载几分钟。
我正在考虑做这样的事情:
shell_exec("rm /tmp/output.txt");
shell_exec("update_flash -v " . $filename . " 4 2>&1 >> /tmp/output.txt &");
echo '<div id="output"></div>';
echo '<div id="results"></div>';
理论上,这会将命令置于后台并将所有输出附加到 /tmp/output.txt。
然后,在 Javascript 函数中,我会定期请求 getOutput.php,它会简单地打印 /tmp/output.txt 的内容并将其粘贴到“输出”div 中。命令完成后,另一个 Javascript 函数将处理输出并在“结果”div 中显示结果。
但我在这里看到的问题是,在更新设备闪存的过程中,getOutput.php 最终将变得无法访问,因为它位于要更新的分区上。因此,这可能会让我处于与以前相同的位置,尽管没有 504 或看似永远加载的页面。
我可以将 getOutput.php 移动到设备中的另一个分区,但我想我仍然需要对网络服务器配置做一些有趣的事情才能在那里访问它(从网络根目录到它的符号链接会像任何其他一样)文件,最终在重新刷新期间被覆盖)。
有没有其他方法可以显示命令运行时的输出,或者我应该使用我拥有的解决方案?
Edit 1:我目前正在测试一些解决方案。稍后我将用结果更新我的问题。
Edit 2:看来文件系统并没有像我最初想象的那样被覆盖。相反,系统似乎以只读模式挂载现有文件系统,因此即使文件系统重新刷新后我仍然可以访问 getOutput.php。
我在问题中描述的第二个解决方案似乎确实可以使用 popen (如下面的答案中提到的)而不是 shell_exec 来工作。页面加载,通过 Ajax 我可以显示 output.txt 的内容。
However, it seems that output.txt does not reflect the output from the re-flash command in real time-- it seems to display nothing until the update command returns from execution. I will need to do further testing to see what's going on here.
Edit 3:没关系,它看起来像文件is当我访问它时是当前的。当内核执行一些由我使用存储源 JFFS2 映像的分区触发的 JFFS2 相关任务时,我遇到了延迟。我不知道为什么,但这显然会导致所有 PHP 脚本阻塞,直到完成为止。
为了解决这个问题,我将把更新命令调用放在一个单独的脚本中,并通过 Ajax 请求它——这样,用户在技术上仍在等待系统时至少会收到一些预先打包的反馈。