Pull to refresh

Установить время выполнения консольной команды

Reading time3 min
Views4.3K
Довелось однажды писать скрипт, который в процессе своей работы пробегал по списку видео файлов и для каждого запускал ffmpeg с ключом, позволяющим получить информацию о файле. Мне собственно требовалось время воспроизведения.

Все бы хорошо, да вот на одном файле ffmpeg подвисал и не думал завершаться, а в момент завершения отваливался и php скрипт без видимых на то причин.

После долгих поисков решения данной проблемы, был найден код, который после небольшой переделки я готов представить на ваш суд :)


Основная проблема заключалась в том, что не было возможности ограничить время выполнения ffmpeg.

Помог следующий код:

<?php

  /**
   * Run process with timeout
   * @param str $command
   * @param int $timeout - sec
   * @param int $sleep
   * @param str $file_out_put - if default value, then return true else return out of process
   * @return bool or str
   */
  function PsExecute($command, $timeout = 10, $sleep = 1, $file_out_put = '/dev/null') {

    $pid = PsExec($command, $file_out_put);

    if( $pid === false ) {
      return false;
    }

    $cur = 0;

    // пока не истекло время отведенное на выполнение скрипта продолжаем ждать
    while( $cur < $timeout ) {
      sleep($sleep);
      $cur += $sleep;
      
      if( !PsExists($pid) ) {
        // скрипт завершил своё выполнение, можно посмотреть его результат или просто вернуть true
        if ($file_out_put != '/dev/null') {
          return file_get_contents($file_out_put);
        } else {
          return true;
        }
      }
    }

    // не дождались пока звершиться скрипт, по этому автоматически убиваем его
    PsKill($pid);
    return false;
  }

  /**
   * Run process in background with out buffer to file
   * @param str $commandJob
   * @param str $file_out_put
   * @return int or false
   */
  function PsExec($commandJob, $file_out_put) {
    $command = $commandJob.' > '.$file_out_put.' 2>&1 & echo $!';
    exec($command ,$op);
    $pid = (int)$op[0];

    if($pid!="") return $pid;

    return false;
  }

  /**
   * If process exists then return true else return false
   * @param int $pid
   * @return bool
   */
  function PsExists($pid) {

    exec("ps ax | grep $pid 2>&1", $output);

    while( list(,$row) = each($output) ) {

      $row_array = explode(" ", $row);
      $check_pid = $row_array[0];

      if($pid == $check_pid) {
        return true;
      }

    }

    return false;
  }

  /**
   * Kill process
   * @param int $pid
   */
  function PsKill($pid) {
    exec("kill -9 $pid", $output);
  }

?>


* This source code was highlighted with Source Code Highlighter.


Код довольно простой и понятный, по этому наверное нет смысла писать к нему описание.

Пример использования

PsExecute('ffmpeg -i video_file.flv', 5, 1, '/tmp/1.txt');
Если за 5 секунд ffmpeg не завершится, то он будет завершен автоматически.

Скачать в архиве
Tags:
Hubs:
Total votes 31: ↑27 and ↓4+23
Comments23

Articles