BashExecutor.php 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. <?php
  2. namespace Libs;
  3. class BashExecutor
  4. {
  5. public static function run(string $command, int $timeoutSeconds = 30): array
  6. {
  7. $descriptorSpec = [
  8. 0 => ["pipe", "r"], // STDIN
  9. 1 => ["pipe", "w"], // STDOUT
  10. 2 => ["pipe", "w"] // STDERR
  11. ];
  12. $process = proc_open($command, $descriptorSpec, $pipes);
  13. if (!is_resource($process)) {
  14. return [
  15. "exitCode" => -1,
  16. "output" => "",
  17. "error" => "Failed to start process"
  18. ];
  19. }
  20. // Timeout handling
  21. $start = time();
  22. $stdout = "";
  23. $stderr = "";
  24. do {
  25. $status = proc_get_status($process);
  26. $stdout .= stream_get_contents($pipes[1]);
  27. $stderr .= stream_get_contents($pipes[2]);
  28. usleep(100000); // 0.1 segundo
  29. if ((time() - $start) > $timeoutSeconds) {
  30. proc_terminate($process);
  31. return [
  32. "exitCode" => -1,
  33. "output" => $stdout,
  34. "error" => "Timeout of {$timeoutSeconds}s reached"
  35. ];
  36. }
  37. } while ($status['running']);
  38. foreach ($pipes as $pipe) {
  39. fclose($pipe);
  40. }
  41. $lastStatusExitCode = $status['exitcode'] ?? null;
  42. $closeExitCode = proc_close($process);
  43. $exitCode = ($lastStatusExitCode === null || $lastStatusExitCode === -1)
  44. ? $closeExitCode
  45. : $lastStatusExitCode;
  46. return [
  47. "exitCode" => $exitCode,
  48. "output" => trim($stdout),
  49. "error" => trim($stderr)
  50. ];
  51. }
  52. }