如果 PHP shell_exec() 工作时间太长或执行的程序挂起...如何捕获错误?

发布于 2024-09-12 21:59:07 字数 189 浏览 6 评论 0原文

如果我使用 shell_exec() 执行外部程序 (unix) 并且它运行超过 30 秒,PHP 将因致命错误而终止。那是因为外部程序挂起/崩溃或者我不知道。

我想捕获这个错误。 try{}..catch{} 在这里不起作用。如何判断外部程序是否已挂起?通常我的外部程序运行时间不超过 2 秒。

If I execute with shell_exec() an external program (unix) and it works for more than 30 seconds, PHP dies with Fatal error. That's because external program hanged/crashed or I don't know.

I want to catch this error. try{}..catch{} does not work in here. How can I tell if an external program has hanged? Usually my external program runs under 2 seconds.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

梦巷 2024-09-19 21:59:07

您可以使用“run-tests.php”脚本中定义的这个函数system_with_timeout

包含在源代码分发中:(关键是传递给stream_select的最后一个参数)

function system_with_timeout($commandline, $env = null, $stdin = null)
{
    global $leak_check, $cwd;

    $data = b'';

    $bin_env = array();
    foreach((array)$env as $key => $value) {
        $bin_env[(binary)$key] = (binary)$value;
    }

    $proc = proc_open($commandline, array(
        0 => array('pipe', 'r'),
        1 => array('pipe', 'w'),
        2 => array('pipe', 'w')
        ), $pipes, $cwd, $bin_env, array('suppress_errors' => true, 'binary_pipes' => true));

    if (!$proc) {
        return false;
    }

    if (!is_null($stdin)) {
        fwrite($pipes[0], (binary) $stdin);
    }
    fclose($pipes[0]);

    $timeout = $leak_check ? 300 : (isset($env['TEST_TIMEOUT']) ? $env['TEST_TIMEOUT'] : 60);

    while (true) {
        /* hide errors from interrupted syscalls */
        $r = $pipes;
        $w = null;
        $e = null;

        $n = @stream_select($r, $w, $e, $timeout);

        if ($n === false) {
            break;
        } else if ($n === 0) {
            /* timed out */
            $data .= b"\n ** ERROR: process timed out **\n";
            proc_terminate($proc);
            return $data;
        } else if ($n > 0) {
            $line = (binary) fread($pipes[1], 8192);
            if (strlen($line) == 0) {
                /* EOF */
                break;
            }
            $data .= $line;
        }
    }

    $stat = proc_get_status($proc);

    if ($stat['signaled']) {
        $data .= b"\nTermsig=" . $stat['stopsig'];
    }

    $code = proc_close($proc);
    return $data;
}

该脚本 超时是通过传递如下数组作为第二个参数来给出的:array('TEST_TIMEOUT' => 200)

You can use this function system_with_timeout defined in the "run-tests.php" script, included in the source distribution:

(the key is the last parameter passed to stream_select)

function system_with_timeout($commandline, $env = null, $stdin = null)
{
    global $leak_check, $cwd;

    $data = b'';

    $bin_env = array();
    foreach((array)$env as $key => $value) {
        $bin_env[(binary)$key] = (binary)$value;
    }

    $proc = proc_open($commandline, array(
        0 => array('pipe', 'r'),
        1 => array('pipe', 'w'),
        2 => array('pipe', 'w')
        ), $pipes, $cwd, $bin_env, array('suppress_errors' => true, 'binary_pipes' => true));

    if (!$proc) {
        return false;
    }

    if (!is_null($stdin)) {
        fwrite($pipes[0], (binary) $stdin);
    }
    fclose($pipes[0]);

    $timeout = $leak_check ? 300 : (isset($env['TEST_TIMEOUT']) ? $env['TEST_TIMEOUT'] : 60);

    while (true) {
        /* hide errors from interrupted syscalls */
        $r = $pipes;
        $w = null;
        $e = null;

        $n = @stream_select($r, $w, $e, $timeout);

        if ($n === false) {
            break;
        } else if ($n === 0) {
            /* timed out */
            $data .= b"\n ** ERROR: process timed out **\n";
            proc_terminate($proc);
            return $data;
        } else if ($n > 0) {
            $line = (binary) fread($pipes[1], 8192);
            if (strlen($line) == 0) {
                /* EOF */
                break;
            }
            $data .= $line;
        }
    }

    $stat = proc_get_status($proc);

    if ($stat['signaled']) {
        $data .= b"\nTermsig=" . $stat['stopsig'];
    }

    $code = proc_close($proc);
    return $data;
}

The timeout is given by passing an array like this: array('TEST_TIMEOUT' => 200) as the second parameter.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文