【问题标题】:Run a piped shell command in background using PHP使用 PHP 在后台运行管道 shell 命令
【发布时间】:2010-11-09 23:07:52
【问题描述】:

我正在尝试使用 PHP 在后台执行命令,以便 Web 应用程序可以继续加载,但到目前为止没有运气。

该命令用于直播应用,因此涉及以下内容:

<stream pre-process> | ffmpeg <options> | <stream segmenter>

我可以将上述内容粘贴在脚本中,并在后台使用 & 在 bash 中正常执行,但这在 PHP 中不起作用。我之前也尝试过使用 nohup 和“nohup & echo $!”,但没有成功。

我还将所有 stderr 都通过管道传输到 /dev/null,并且我可以在 apache 日志中验证当我执行命令时没有生成输出(但它正在执行)。

下面的一些示例代码..我在这段代码之后的内容在完成之前不会执行,这需要很长时间。

function streamVid ($mid, $width, $height, $br) {
    $cdir = "./temp";
    $zmstrm = "zmstreamer -m ".$mid." 2> /dev/null";
    $seg = "segmenter - 3 ".$cdir."/sample_".$mid." ".$cdir."/stream_".$mid.".m3u8 ./ 2>/dev/null";
    $ffparms = "-f mpegts -analyzeduration 0 -acodec copy -s ".$width."x".$height."   -vcodec libx264 -b ".$br." -flags +loop -cmp +chroma -partitions +parti4x4+partp8x8+partb8x8 -subq 5 -trellis 1 -refs 1 -coder 0 -me_range 16 -keyint_min 25 -sc_threshold 40 -i_qfactor 0.71 -bt 200k -maxrate ".$br." -bufsize ".$br." -rc_eq 'blurCplx^(1-qComp)' -qcomp 0.6 -qmin 10 -qmax 51 -qdiff 4 -level 30 -aspect 320:240 -g 30 -analyzeduration 0 -async 2 - 2> /dev/null";
    $url = $zmstrm . " | ffmpeg -t 10 -analyzeduration 0 -i - ". $ffparms . " | " . $seg;
    shell_exec("nohup ". $url." & echo $!");       
    ob_flush();
    flush();
}

【问题讨论】:

    标签: php ffmpeg video-streaming


    【解决方案1】:

    如果您需要将操作的结果流出来,请使用 system 或 passthru 方法,或者使用 popen 或 proc_open 来完全控制进程的输入和输出。

    一般来说,由您的 Web 服务器触发的 PHP 脚本旨在生成一个页面并退出。它们不是执行视频编码等后台任务的最佳场所,您的网络服务器会限制程序的执行时间,并且很难从您的浏览器中获取状态信息(它看起来会挂起)。

    最好的办法是使用 Python(或 PHP)等语言创建一个单独的守护进程,该进程将在您的计算机上运行。当您的 Web 脚本需要对视频进行转码时,它们可以将必要的信息放在数据库或文件中,以便由守护进程轮询。守护进程还可以使用状态信息更新数据库。

    一般来说,您的 Web 服务页面应尽可能“无阻塞”,这意味着如果某件事需要花费一两秒以上的时间,请在后台执行此操作并在您的网站上创建页面以允许用户查看操作状态并对其进行操作。

    【讨论】:

    • 谢谢扎克。目的不是阻止这一点,我想我正在尝试在线实现“守护程序”功能,但可能不可能。但要澄清一下,我不想流出这个操作的结果;该命令字符串在磁盘上创建由 HTML-5 元素(PHP 程序继续创建)访问的文件。我将看一下守护进程方法,但希望有更简单的方法来简化现场部署。