在web服务器上通过PHP运行一个SlimerJS +无头Firefox脚本


Running a SlimerJS + headless Firefox script through PHP on webserver?

在我的服务器(Ubuntu 14.04.4 LTS)上,我安装了Firefox,以及用于无头Firefox操作的xvfb,以及带有SlimerJS的CasperJS。我也有一个CasperJS脚本工作良好。我想利用这个脚本从PHP;这是PHP脚本的精髓,我们把它命名为mytest.php:

echo "php_sapi_name() " . php_sapi_name() . "'n"; // "cli" for php cli, "apache2handler" for php via webserver
chdir(dirname(__FILE__));
$nodeModPath = "/home/USERNAME/.nvm/versions/node/v4.0.0/lib/node_modules";
putenv("SLIMERJSLAUNCHER=/usr/bin/firefox46");
$cmdline = "xvfb-run $nodeModPath/casperjs/bin/casperjs --engine=slimerjs --debug=true mySlimerScript.js";
$returnString = shell_exec($cmdline);
echo "$returnString'n";

编辑:注意命令也可以是:

$cmdline = "xvfb-run $nodeModPath/casperjs/bin/casperjs --engine=slimerjs --debug=true 2>&1";

…也就是说,没有列出任何JS脚本-在这种情况下,帮助应该被转储(并且,在CLI访问的情况下-但是通过webserver访问时报告的错误与下面相同)


当我从终端命令行(通过SSH)运行这个PHP脚本时,这是通过PHP在CLI模式:

$ php mytest.php 

…一切都很好,没有任何问题。

然而,当我通过web服务器在线调用这个PHP脚本时,即通过http://example.com/mytest.php,它首先失败,错误:

Gecko error: it seems /usr/bin/firefox46 is not compatible with SlimerJS.
See Gecko version compatibility. If version is correct, launch slimerjs
with --debug=true to see Firefox error message

…在添加--debug=true(如上面的例子中已经包含的)之后,我还得到了这个错误:

JavaScript error: resource://gre/modules/FileUtils.jsm, line 63: NS_ERROR_FAILURE: Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsIProperties.get]

所以,当PHP通过web服务器调用时,显然我的无头Firefox不想运行(在这种情况下,PHP报告它使用apache2handler SAPI)。

有没有人知道为什么会发生这种情况-我怎么能得到脚本正确执行时,从一个web服务器调用,就像当它在PHP CLI模式下运行?


EDIT 2:现在可以通过CLI模式重建这个错误,并且可以确认这是由于用户;所以没有在$command中提供任何JS脚本,我得到这个:

$ sudo -H -u root php mytest.php
...
Usage: casperjs [options] script.[js|coffee] [script argument [script argument ...]]
       casperjs [options] test [test path [test path ...]]
       casperjs [options] selftest
...
$ sudo -H -u www-data php mytest.php
JavaScript error: resource://gre/modules/FileUtils.jsm, line 63: NS_ERROR_FAILURE: Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsIProperties.get]
Gecko error: it seems /usr/bin/firefox46 is not compatible with SlimerJS.
See Gecko version compatibility. If version is correct, launch slimerjs
with --debug=true to see Firefox error message

这是一个棘手的问题。我最终做了一个strace,并比较了root用户和www-data用户在运行完整的slimerjs时的日志(完整的命令行可以通过将echo添加到/path/to/slimerjs-0.10.1-pre/slimerjs中来找到):

sudo -H -u www-data strace '
  /usr/bin/firefox46 -app /path/to/slimerjs-0.10.1-pre/application.ini '
  --profile /path/to/firefox-46.0.1/profile-46 -no-remote --debug=true /home/USERNAME/.nvm/versions/node/v4.0.0/lib/node_modules/casperjs/bin/bootstrap.js --casper-path=/home/USERNAME/.nvm/versions/node/v4.0.0/lib/node_modules/casperjs '
  --cli 2>&1 '
  | tee /tmp/strace.log
sudo -H -u root strace '
  /usr/bin/firefox46 -app /path/to/slimerjs-0.10.1-pre/application.ini '
  --profile /path/to/firefox-46.0.1/profile-46 -no-remote --debug=true /home/USERNAME/.nvm/versions/node/v4.0.0/lib/node_modules/casperjs/bin/bootstrap.js --casper-path=/home/USERNAME/.nvm/versions/node/v4.0.0/lib/node_modules/casperjs '
  --cli 2>&1 '
  | tee /tmp/straceR.log

如果这些日志现在在meld中进行比较,那么最终开始在如下点发散:

mkdir("/root/.innophi", 0700)           = 0
mkdir("/root/.innophi/slimerjs", 0700)  = 0
... [vs.] ...
mkdir("/var/www/.innophi", 0700)        = -1 EACCES (Permission denied)
access("/var/www/.innophi", F_OK)       = -1 ENOENT (No such file or directory)

因此,casperJS基本上尝试在用户的主目录下创建一个目录;问题是,www-data$HOME/var/www,它似乎没有写访问!

所以,对我来说最简单的事情是"破解"mytest.php脚本中的$HOME环境变量,并将其设置为/tmp,其中www-data绝对具有写权限:

...
putenv("SLIMERJSLAUNCHER=/usr/bin/firefox46");
putenv("HOME=/tmp");
...

…最后,脚本也在CLI的www-data用户下工作:

$ sudo -H -u www-data php test_commands.php
...
Options:
--verbose   Prints log messages to the console
--log-level Sets logging level
--help      Prints this help
...

顺便说一句,这个.innophi目录似乎也在https://docs.slimerjs.org/current/configuration.html#profiles中提到过,