【问题标题】:PHP script stuck on exec even after running command in backgroud on Windows即使在 Windows 后台运行命令后 PHP 脚本仍停留在 exec 上
【发布时间】:2015-09-30 17:47:46
【问题描述】:

我想要一个 php 脚本,我可以从中执行一个程序,如果它没有在 2 秒内完成执行,则终止它。我正在使用 Windows。我试过以下代码:

exec("start /B program.exe");
sleep(2);
exec('taskkill /F /IM "program.exe"');

这似乎不起作用,因为只要 program.exe 未完成执行,脚本就会停留在第一个 exec 语句上。我不知道如何解决这个问题。

【问题讨论】:

    标签: php windows exec


    【解决方案1】:

    没错,exec() 将阻塞直到执行完成。 This question 对于如何在超时情况下执行 exec() 有很好的答案。我认为this 可能最适合您。为了完整起见,我将在此处发布代码(但我不能接受任何功劳!):

    /**
     * Execute a command and return it's output. Either wait until the command exits or the timeout has expired.
     *
     * @param string $cmd     Command to execute.
     * @param number $timeout Timeout in seconds.
     * @return string Output of the command.
     * @throws \Exception
     */
    function exec_timeout($cmd, $timeout) {
      // File descriptors passed to the process.
      $descriptors = array(
        0 => array('pipe', 'r'),  // stdin
        1 => array('pipe', 'w'),  // stdout
        2 => array('pipe', 'w')   // stderr
      );
    
      // Start the process.
      $process = proc_open('exec ' . $cmd, $descriptors, $pipes);
    
      if (!is_resource($process)) {
        throw new \Exception('Could not execute process');
      }
    
      // Set the stdout stream to none-blocking.
      stream_set_blocking($pipes[1], 0);
    
      // Turn the timeout into microseconds.
      $timeout = $timeout * 1000000;
    
      // Output buffer.
      $buffer = '';
    
      // While we have time to wait.
      while ($timeout > 0) {
        $start = microtime(true);
    
        // Wait until we have output or the timer expired.
        $read  = array($pipes[1]);
        $other = array();
        stream_select($read, $other, $other, 0, $timeout);
    
        // Get the status of the process.
        // Do this before we read from the stream,
        // this way we can't lose the last bit of output if the process dies between these     functions.
        $status = proc_get_status($process);
    
        // Read the contents from the buffer.
        // This function will always return immediately as the stream is none-blocking.
        $buffer .= stream_get_contents($pipes[1]);
    
        if (!$status['running']) {
          // Break from this loop if the process exited before the timeout.
          break;
        }
    
        // Subtract the number of microseconds that we waited.
        $timeout -= (microtime(true) - $start) * 1000000;
      }
    
      // Check if there were any errors.
      $errors = stream_get_contents($pipes[2]);
    
      if (!empty($errors)) {
        throw new \Exception($errors);
      }
    
      // Kill the process in case the timeout expired and it's still running.
      // If the process already exited this won't do anything.
      proc_terminate($process, 9);
    
      // Close all streams.
      fclose($pipes[0]);
      fclose($pipes[1]);
      fclose($pipes[2]);
    
      proc_close($process);
    
      return $buffer;
    }
    

    编辑

    proc_open() 的“执行”部分可能无法在 Windows 上运行,但可能没有必要。

    【讨论】:

      【解决方案2】:

      exec() 手册页的first comment 显示了一个非常简单的示例。

      【讨论】:

        【解决方案3】:

        你是在用php cli (command line) 做这个吗?打开command prompt as administrator
        为了不被等待程序close the process of opening the program阻塞。

        php myscript.php

        pclose(popen("start /B program.exe", "r"));
        sleep(2);
        exec('taskkill /F /IM program.exe');
        exit(0);
        

        也可以将 exec start 放入单独的脚本并使用 exec 触发此脚本

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-04-29
          • 1970-01-01
          • 2013-05-14
          • 1970-01-01
          相关资源
          最近更新 更多