Как развернуть приложение узла phantomjs на AWS Lambda?

Я собрал небольшую функцию Lambda для обхода веб-сайта, используя набор инструментов SpookyJS, CasperJS и PhantomJS для автономного просмотра. Задача довольно простая, и в какой-то момент несколько месяцев назад она работала в Lambda. Недавно мне пришлось кое-что изменить, и я хотел снова поработать над проектом, но начал с чистого листа, и у меня возникли проблемы с запуском Lambda без каких-либо ошибок. Мой вопрос: как я могу запускать фантомы в Lambda?

Пример кода, который я запускаю:

spooky.start('http://en.wikipedia.org/wiki/Spooky_the_Tuff_Little_Ghost');
spooky.then(function () {
    this.emit('hello', 'Hello, from ' + this.evaluate(function () {
        return document.title;
    }));
});
spooky.run();

Ошибка, которую я получаю в Lambda:

{ [Error: Child terminated with non-zero exit code 1] details: { code: 1, signal: null } }

Я выполнил множество процедур, чтобы убедиться, что все работает на Lambda. Ниже приведен длинный список вещей, которые я пытался диагностировать:

  1. Запустите локально, используя node index.js, и убедитесь, что он работает.
  2. Загрузите package.json и файл js в экземпляр Amazon Linux EC2 для компиляции в соответствии с рекомендациями для вызовов установки npm и описанием здесь
  3. Запустите npm install на экземпляре ec2 и снова запустите node index.js, чтобы убедиться в правильности вывода.
  4. заархивируйте все и разверните на AWS с помощью cli

Мой package.json:

{
  "name": "lambda-spooky-test",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "casperjs": "^1.1.3",
    "phantomjs-prebuilt": "^2.1.10",
    "spooky": "^0.2.5"
  }
}

Я также пробовал следующее (большинство также работает локально и на экземпляре AWS EC2, но с той же ошибкой на Lambda:

  1. Пробуем не готовую версию фантома
  2. Обеспечение доступности casperjs и phantomjs по пути с process.env['PATH'] = process.env['PATH'] + ':' + process.env['LAMBDA_TASK_ROOT'] + ':' + process.env['LAMBDA_TASK_ROOT'] + '/node_modules/.bin'; console.log( 'PATH: ' + process.env.PATH );
  3. Проверка вызовов порождения путем упаковки вызова .spawn() в child_process и получение следующего:

    { '0': 'casperjs',
      '1': 
       [ '/var/task/node_modules/spooky/lib/bootstrap.js',
         '--transport=http',
         '--command=casperjs',
         '--port=8081',
         '--spooky_lib=/var/task/node_modules/spooky/lib/../',
         '--spawnOptions=[object Object]' ],
      '2': {} }
    
  4. Вызов .exec('casperjs') и .exec('phantomjs --version') напрямую, подтверждая, что он работает локально и на EC2, но получает следующую ошибку в Lambda. Команда:

    `require('child_process').exec('casperjs', (error, stdout, stderr) => {
    if (error) { console.error('error: ' + error); }
       console.log('out: ' + stdout);
       console.log('err: ' + stderr);
    });
    

оба со следующим результатом:

err: Error: Command failed: /bin/sh -c casperjs
module.js:327
    throw err;
    ^

Error: Cannot find module '/var/task/node_modules/lib/phantomjs'
    at Function.Module._resolveFilename (module.js:325:15)
    at Function.Module._load (module.js:276:25)
    at Module.require (module.js:353:17)
    at require (internal/module.js:12:17)
    at Object.<anonymous> (/var/task/node_modules/.bin/phantomjs:16:15)
    at Module._compile (module.js:409:26)
    at Object.Module._extensions..js (module.js:416:10)
    at Module.load (module.js:343:32)
    at Function.Module._load (module.js:300:12)
    at Function.Module.runMain (module.js:441:10)

2016-08-07T15:36:37.349Z    b9a1b509-5cb4-11e6-ae82-256a0a2817b9    sout: 
2016-08-07T15:36:37.349Z    b9a1b509-5cb4-11e6-ae82-256a0a2817b9    serr: module.js:327
    throw err;
    ^

Error: Cannot find module '/var/task/node_modules/lib/phantomjs'
    at Function.Module._resolveFilename (module.js:325:15)
    at Function.Module._load (module.js:276:25)
    at Module.require (module.js:353:17)
    at require (internal/module.js:12:17)
    at Object.<anonymous> (/var/task/node_modules/.bin/phantomjs:16:15)
    at Module._compile (module.js:409:26)
    at Object.Module._extensions..js (module.js:416:10)
    at Module.load (module.js:343:32)
    at Function.Module._load (module.js:300:12)
    at Function.Module.runMain (module.js:441:10)

person ryanhallcs    schedule 07.08.2016    source источник


Ответы (1)


Я обнаружил, что проблема заключается в том, что включение node_modules/.bin в путь работает как на локальных компьютерах, так и на машинах ec2, потому что эти файлы просто указывают на папки действий /bin в каждой соответствующей библиотеке. Это прерывается, если вызовы в этих файлах используют относительные пути. Проблема:

[ec2-user@ip-172-31-32-87 .bin]$ ls -lrt
total 0
lrwxrwxrwx 1 ec2-user ec2-user 35 Aug  7 00:52 phantomjs -> ../phantomjs-prebuilt/bin/phantomjs
lrwxrwxrwx 1 ec2-user ec2-user 24 Aug  7 00:52 casperjs -> ../casperjs/bin/casperjs

Я работал над этим, добавляя соответствующий бин каждой библиотеки к пути лямбда в функции обработчика лямбда:

process.env['PATH'] = process.env['PATH'] + ':' + process.env['LAMBDA_TASK_ROOT'] 
        + ':' + process.env['LAMBDA_TASK_ROOT'] + '/node_modules/phantomjs-prebuilt/bin'
        + ':' + process.env['LAMBDA_TASK_ROOT'] + '/node_modules/casperjs/bin';

И теперь это будет правильно запускать фантом, каспер и жуткий в Lambda.

person ryanhallcs    schedule 07.08.2016
comment
В случае, если кто-то еще найдет это и страдает аналогичной проблемой. Даже после вышеизложенного я все еще страдал от того, что ребенок завершается с ненулевым кодом выхода 1. Оказывается, мне пришлось зайти в каталог casperjs в node_modules и запустить npm_update, так как в нем отсутствовали зависимости, которые не были получены должным образом от родителя - person Nick; 27.12.2016