运行 PHP exec() 异步执行,但检查是否完成?

Run PHP exec() asynchronously, but check for completion?

我正在编写一个网站后端,其中将包含用户上传的视频。为了确保最大的可访问性,我正在压缩上传的视频并将它们重新保存为 .mp4 和 .webm 格式以覆盖所有浏览器(或尽可能多的浏览器)。为此,我在 PHP exec() 函数中 运行 一个 avconv 命令。

我不想让用户在页面加载前等待脚本完成,所以我 运行 代码是异步的。到目前为止,我的代码如下。

exec('bash -c "exec nohup setsid avconv -i ' . $tempPath . ' -c:v libx264 ' . $transpose . ' ' . $newPath . 'mp4 > /dev/null 2>/dev/null &"');
exec('bash -c "exec nohup setsid avconv -i ' . $tempPath . ' -c:v libvpx ' . $transpose . ' ' . $newPath . 'webm > /dev/null 2>/dev/null &"');

除了 运行 exec 函数外,我还将视频保存到数据库中并向用户发送一封电子邮件,感谢他们上传视频。

难点在于:我希望服务器等待视频转换完成,然后将其添加到数据库并向用户发送电子邮件。基本上,程序流程是:

用户上传视频。 视频放在临时文件夹中。 用户被带到一个感谢页面,表明他们的视频很快就会出现。 服务器执行两个 avconv 命令来转换和压缩视频以供网络使用。 两次转换完成后,视频信息将添加到 MySQL 数据库,向用户发送一封电子邮件,并删除原始上传的视频。

可能只是我对命令行的无知(事实上几乎肯定是),但是我怎么会'queue up'这些命令呢?首先做两个转换,然后调用一个 PHP 脚本添加到数据库,然后删除原始视频,同时与原始 PHP 脚本异步?

编辑:我试过使用“&&”运算符将它们排队,如下所示:

exec('bash -c "exec nohup setsid avconv -i ' . $tempPath . ' -c:v libx264 ' . $transpose . ' ' . $newPath . 'mp4 && avconv -i ' . $tempPath . ' -c:v libvpx ' . $transpose . ' ' . $newPath . 'webm > /dev/null 2>/dev/null &"');

然而,这似乎抵消了我 运行 它是异步的事实,因为页面现在似乎在等待命令完成。

您可以断开 PHP 脚本与客户端的连接,但保留它 运行 完成您的任务。

// Your preliminary stuff here ...
/// then send the user elsewhere but carry on in the background
ignore_user_abort(true);
set_time_limit(0); // i.e. forever

header("Location: thankyoubutwait.php", true);
header("Connection: close", true);
header("Content-Encoding: none\r\n");
header("Content-Length: 0", true);

flush();
ob_flush();

session_write_close();
// more of your video stuff here including database writes
// and clean up bits
// (you may end up with zombie processes though so check your logs or write statuses to files etc.)

您应该启动一个异步 命令行 php 脚本 来对两个视频进行编码,然后 然后 发送一封电子邮件:

upload.php :

exec('/usr/bin/php -f encode_files.php > /dev/null 2>/dev/null &"');
echo "Files will be encoded, come back later !";

encode_files.php

exec('avconv ...'); // Synchronously ! Without > /dev/null etc ...
exec('avconv ...'); // webm ...

mail('user@user.com', 'Encoding complete ! ', 'Great ! ');

我将调用保留为 "bash -c exec ...",但我认为有更短的方法可以异步调用 php 脚本: Asynchronous shell exec in PHP 您甚至可以传递参数(例如 user/video id,...)

$cmd = 'nohup /usr/bin/php -f /path/to/php/file.php action=generate var1_id=23 var2_id=35 gen_id=535 > /path/to/log/file.log & printf "%u" $!';
$pid = shell_exec($cmd);

很简单,您只需像这样检查命令行是否正常执行:

// Your code before...
$command = 'bash -c "exec nohup setsid avconv -i ' . $tempPath . ' -c:v libx264 ' . $transpose . ' ' . $newPath . 'mp4 > /dev/null 2>/dev/null &"'
exec($command, $return, $status);
if($status == 0 ) {
    $command2 = 'bash -c "exec nohup setsid avconv -i ' . $tempPath . ' -c:v libvpx ' . $transpose . ' ' . $newPath . 'webm > /dev/null 2>/dev/null &"';
    exec($command2, $return2, $status2);

    if($status2==0){
        // let your user know your video traitement has been done
        // lauch a new function for alert him
    }
}


// Kill your process at end
die();