【问题标题】:Run PHP exec() asynchronously, but check for completion?异步运行 PHP exec(),但检查是否完成?
【发布时间】:2015-11-26 22:27:25
【问题描述】:

我正在编写一个包含用户上传视频的网站后端。为了确保最大的可访问性,我正在压缩上传的视频并将它们重新保存为 .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 命令来转换和压缩视频以供 Web 使用。 两次转换完成后,视频信息将添加到 MySQL 数据库,向用户发送一封电子邮件,并删除原始上传的视频。

这可能只是我对命令行的无知(事实上它几乎肯定是),但我怎么能“排队”这些命令呢?首先进行两种转换,然后调用 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 video asynchronous ffmpeg avconv


    【解决方案1】:

    你只需要像这样检查你的命令行的良好执行很容易:

    // 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();
    

    【讨论】:

      【解决方案2】:

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

      上传.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 您甚至可以传递参数(例如用户/视频 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);
      

      【讨论】:

      • 太棒了!简单易执行,我喜欢。其他答案也是正确的,但我认为这个最适合我的具体情况。老实说,不敢相信我自己没有想到。
      • 正是我想要的。如果调用脚本在 php 5.6 下运行并且正在运行的 /usr/bin/php 版本是 7.4,这仍然有效吗?这就是我的情况。
      【解决方案3】:

      您可以断开 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.)
      

      【讨论】:

      • 似乎是个好主意,但如果会话在脚本中启动,它不会锁定更多请求吗?
      • 这似乎是一种非常聪明的方法,但除非绝对必要,否则我会尽量避免使用标题重定向(因为有时它们似乎不起作用),并且如上所述,这似乎就像它会阻止进一步的请求一样。必须有一种方法可以使用命令行从服务器端执行此操作。
      • 我对类似的事情使用相同的技术。它不应该锁定任何东西,除非你也想要它。它唯一会“锁定”的是它正在转换和移动的文件系统上的文件。在生产代码中,重定向当然应该是一个绝对 URL ......例如“位置:yourdomain/thankyoubutwait.php”否则它们有时会不起作用。
      猜你喜欢
      • 2012-08-06
      • 1970-01-01
      • 1970-01-01
      • 2011-03-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多