Запуск безголового скрипта SlimerJS + Firefox через PHP на веб-сервере?

На моем сервере (Ubuntu 14.04.4 LTS) у меня установлен Firefox, а также xvfb для безголовой работы Firefox и CasperJS с SlimerJS. У меня также есть скрипт 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 - но при доступе через веб-сервер сообщается та же ошибка, что и ниже)


Когда я запускаю этот PHP-скрипт из командной строки терминала (через SSH), то есть через PHP в режиме CLI:

$ php mytest.php 

... все работает нормально, никаких проблем.

Однако, когда я вызываю этот 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]

Итак, очевидно, мой безголовый Firefox не хочет запускаться, когда PHP вызывается через веб-сервер (в этом случае PHP сообщает, что он использует apache2handler SAPI).

Кто-нибудь знает, почему это происходит - и как я могу заставить скрипт правильно выполняться при вызове с веб-сервера, точно так же, как когда он работает в режиме PHP CLI?


РЕДАКТИРОВАТЬ 2: Теперь можно восстановить эту ошибку и через режим CLI и подтвердить, что это связано с пользователем; поэтому без какого-либо сценария JS, представленного в $command, я получаю следующее:

$ 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

person sdbbs    schedule 30.06.2016    source источник
comment
Первые мысли: права доступа к файлам при запуске скрипта в режиме cli будут выполняться пользователем, однако через веб-сервер пользователь будет www-data. Возможно, не так ли?   -  person php-dev    schedule 30.06.2016
comment
Действительно, @php-dev, но я не могу понять, чьи разрешения могут быть проблемой; здесь я вызываю xvfb-run, который вызывает casperjs, который вызывает slimerjs, который вызывает безголовый Firefox. Есть ли способ проверить наличие ошибок разрешения где-нибудь в таком случае? Я пробовал /var/log/apache2/error-mysite.log, но он сообщает о таких PHP-вещах, как Trying to get property of non-object, только после сбоя вызова shell_exec.   -  person sdbbs    schedule 30.06.2016
comment
Попробуйте перенаправить вывод stderr на stdout или в файл.   -  person php-dev    schedule 30.06.2016
comment
Спасибо @php-dev - я добавил 2>&1 в конец $cmdline, но, к сожалению, никакой новой информации не получил. Тем не менее, я также попробовал прямой shell_exec("xvfb-run /usr/bin/firefox46 2>&1"), и этот, похоже, НЕ дает сбоев (однако он также не выходит сам по себе, как и ожидалось). Получается, проблема не только в xvfb-run и firefox?!   -  person sdbbs    schedule 30.06.2016


Ответы (1)


Что ж, это была неприятная проблема. В итоге я сделал strace и сравнил журналы для пользователя root и пользователя www-data при запуске полного slimerjs (полную командную строку можно найти, добавив echoes к /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 в основном пытается создать каталог в домашнем каталоге пользователя; проблема в том, что $HOME www-data - это /var/www, где у него, по-видимому, нет доступа для записи!

Итак, самым простым для меня было «взломать» переменную окружения $HOME в скрипте mytest.php и установить для нее значение /tmp, где www-data точно имеет права на запись:

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

... и что вы знаете, наконец, скрипт работает и под пользователем www-data из CLI:

$ 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 ,

person sdbbs    schedule 30.06.2016