如何在 AWS Lambda 上部署 phantomjs 节点应用程序?
How to deploy a phantomjs node app on AWS Lambda?
我将一个小的 Lambda 函数放在一起,使用 SpookyJS、CasperJS 和 PhantomJS 工具链来抓取网站以进行无头浏览。这个任务很简单,几个月前的某个时候它在 Lambda 中工作。我最近不得不改变一些事情,想重新开始这个项目,但是重新开始,并且很难让 Lambda 达到 运行 而不会出现任何错误。我的问题是 如何在 Lambda 中 运行 phantomjs?
我运行ning的示例代码是:
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 上。下面是我试图诊断的一长串事情:
- 运行 在本地使用
node index.js
并确认它正在工作
- 将 package.json 和 js 文件上传到 Amazon Linux EC2 实例,按照 npm 安装调用的建议和描述进行编译 here
在ec2实例上- 运行
npm install
,再次运行node index.js
保证输出正确
- 压缩所有内容,并使用 cli
部署到 AWS
我的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 上出现相同的错误:
- 尝试非预建版本的 phantom
- 确保可以从
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 );
的路径访问 casperjs 和 phantomjs
通过包装 child_process 的 .spawn()
调用来检查生成调用,并得到以下信息:
{ '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': {} }
直接调用.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);
});
both 结果如下:
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)
我发现问题是路径中包含 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
我通过将每个库各自的 bin 添加到 Lambda 处理函数中的 lambda 路径来解决这个问题:
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 中的 phantom、casper 和 spooky 正确。
我将一个小的 Lambda 函数放在一起,使用 SpookyJS、CasperJS 和 PhantomJS 工具链来抓取网站以进行无头浏览。这个任务很简单,几个月前的某个时候它在 Lambda 中工作。我最近不得不改变一些事情,想重新开始这个项目,但是重新开始,并且很难让 Lambda 达到 运行 而不会出现任何错误。我的问题是 如何在 Lambda 中 运行 phantomjs?
我运行ning的示例代码是:
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 上。下面是我试图诊断的一长串事情:
- 运行 在本地使用
node index.js
并确认它正在工作 - 将 package.json 和 js 文件上传到 Amazon Linux EC2 实例,按照 npm 安装调用的建议和描述进行编译 here 在ec2实例上
- 运行
npm install
,再次运行node index.js
保证输出正确 - 压缩所有内容,并使用 cli 部署到 AWS
我的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 上出现相同的错误:
- 尝试非预建版本的 phantom
- 确保可以从
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 );
的路径访问 casperjs 和 phantomjs
通过包装 child_process 的
.spawn()
调用来检查生成调用,并得到以下信息:{ '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': {} }
直接调用
.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); });
both 结果如下:
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)
我发现问题是路径中包含 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
我通过将每个库各自的 bin 添加到 Lambda 处理函数中的 lambda 路径来解决这个问题:
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 中的 phantom、casper 和 spooky 正确。