在 IIS 重新启动之前, 使用 PHP exec 运行 google Chrome 无头不会返回输出

共2个回答, 标签: php iis exec google-chrome-headless

我的环境是 Windows Server 2016 和 IIS 10。在我的 PHP 脚本中, 我试图在无头模式下运行 Google Chrome, 以获取外部网页的 html 代码:

 page.html";

exec ($command);
?>

该代码的工作原理, 如果我运行

>C:\php script.php

从命令行。如果我运行实际命令, 它也可以工作:

>"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" \
--headless --disable-gpu --dump-dom https://google.com > page.html

但是, 如果我从浏览器运行该脚本, 它将创建空 page. html 文件和 hungs 直到超时。但是, 如果我在 iis 执行过程中重新启动 IIS, 我将获得充满所需数据的 page. html 文件。

这里可能有什么问题?

第1个答案

你有 4 个过程在这里发挥。

  • W3WP.exe
  • Php. exe
  • Cmd. exe
  • Chromee. exe

Cmd. exe 正在获取 Chrome. exe 的输出并将其传送到您的文件。 它将在 chromee. exe 完成后执行此操作, 或者可以间歇性地进行部分执行。 当我运行类似的代码与上面的你的代码, 我的 chromee. exe 没有完成。 我可以看到 chromee. exe 仍在任务管理器中运行, 占用 25% 的 CPU (在我的一个内核上为 100%)。

我猜重新启动 IIS 以某种方式强制刷新命令的过程中。 在我的大多数情况下, 在做 IISReset 之前, page. html 文件中都有数据, 认为并不是全部。 (Windows 资源管理器显示 0KBs, 但打开文件仍显示文件中的数据)。

至于要尝试的事情, 试试--无沙箱作为一个参数, 因为这个过程是在非交互式会话下运行的。

第2个答案

这不是一个答案, 但太多, 把一个评论, 执行 () 并不真正给出太多的反馈,

首先不要这样做:

$command = "\"$chromeApp\" ";

因为不同的炮弹不能就如何引用东西达成一致, 所以你应该用逃逸的函数代替, 也不要这样做 "

--dump-dom $urladdress > page.html

因为 $urladdress 可能需要转义 (如果黑客能够控制您的 $urladdress, 那么这实际上是一个任意代码执行漏洞), 因此请执行此操作:

$command = escapeshellarg($chromeApp)." --headless --disable-gpu \
 --dump-dom ".escapeshellarg($urladdress)." > page.html";

(如果你 page.html 的名字也可能有特殊字符, 你也应该通过逃避地狱 () 运行这个名字.)

但将 exec () 替换为 proc _ open, 告诉我您从运行此得到了什么:

 array("pipe", "rb"),  // by default stdin is inherited, we don't want that so we create a stdin pipe just so we can fclose() it.
    1 => array("pipe", "wb"),  // stdout
    2 => array("pipe", "wb"),  // stderr
);

$proc=proc_open($command,$descriptorspec,$pipes);
if(!$proc){
    throw new \RuntimeException("failed to create process! \"{$command}\"");
}
$stdout="";
$stderr="";
$fetch=function()use(&$stdout,&$stderr,&$pipes){
    $tmp=stream_get_contents($pipes[1]);
    if(is_string($tmp) && strlen($tmp) > 0){
        $stdout.=$tmp;
    }
    $tmp=stream_get_contents($pipes[2]);
    if(is_string($tmp) && strlen($tmp) > 0){
        $stderr.=$tmp;
    }
};
fclose($pipes[0]);
$status=array();
while(($status=proc_get_status($proc))['running']){
    $fetch();
}
$fetch();
fclose($pipes[1]);
fclose($pipes[2]);
proc_close($proc);
var_dump($stdout,$stderr,$status);


     function _uncygwinify_filepath(string $path) : string
    {
        static $is_cygwin_cache = null;
        if ($is_cygwin_cache === null) {
            $is_cygwin_cache = (false !== stripos(PHP_OS, "cygwin"));
        }
        if ($is_cygwin_cache) {
            return trim(shell_exec("cygpath -aw " . escapeshellarg($path)));
        } else {
            return $path;
        }
    }
    function _cygwinify_filepath(string $path) : string
    {
        static $is_cygwin_cache = null;
        if ($is_cygwin_cache === null) {
            $is_cygwin_cache = (false !== stripos(PHP_OS, "cygwin"));
        }
        if ($is_cygwin_cache) {
            return trim(shell_exec("cygpath -a " . escapeshellarg($path)));
            //return "/cygdrive/" . strtr($path, array(':' => '', '\\' => '/'));
        } else {
            return $path;
        }
    }

编辑: 我写 use(&$stdout,$stderr,&$pipes)use(&$stdout,&$stderr,&$pipes) , 而不是, 对不起, 修复. 如果你只是在没有这个修复的情况下运行它, 那就重新运行它。

相关问题

mysql _ 拿给数组 ()/mysql_fetch_assoc ()/mysql_fetch_row ()/mysql_num_rows 等希望参数1是资源或结果 参考-此错误在 PHP 中意味着什么? 如何在 PHP 中分析和处理 HTML\ xml? 在 IIS 重新启动之前, 使用 PHP exec 运行 google Chrome 无头不会返回输出