【问题标题】:Permissions trouble on AWS Lambda, can't spawn child processAWS Lambda 上的权限问题,无法生成子进程
【发布时间】:2016-05-08 05:30:46
【问题描述】:

所以我创建了这个漂亮的小 lambda,它在本地运行良好,但实际上在野外运行时并没有那么多。

lambda 接受一个事件,事件源中包含 html,将该 html 转换为 PDF(使用 html-pdf 节点模块),将该 pdf 传递给 s3 存储桶,然后返回一个已签名的 url,该 url 在60 秒。

或者至少这是应该发生的事情(同样,在本地工作)。在 Lambda 上进行测试时,出现以下错误:

{
   "errorMessage": "spawn EACCES",
   "errorType": "Error",
   "stackTrace": [
       "exports._errnoException (util.js:870:11)",
       "ChildProcess.spawn (internal/child_process.js:298:11)",
       "Object.exports.spawn (child_process.js:362:9)",
       "PDF.PdfExec [as exec] (/var/task/node_modules/html-pdf/lib/pdf.js:87:28)",
       "PDF.PdfToFile [as toFile] (/var/task/node_modules/html-pdf/lib/pdf.js:83:8)",
       "/var/task/index.js:72:43",
       "Promise._execute (/var/task/node_modules/bluebird/js/release/debuggability.js:272:9)",
       "Promise._resolveFromExecutor (/var/task/node_modules/bluebird/js/release/promise.js:473:18)",
       "new Promise   (/var/task/node_modules/bluebird/js/release/promise.js:77:14)",
       "createPDF (/var/task/index.js:71:19)",
       "main (/var/task/index.js:50:5)"
  ]
}

这是代码本身(未编译,有一个方便的 gulp 任务)

if(typeof regeneratorRuntime === 'undefined') {
    require("babel/polyfill")
}

import fs from 'fs'
import pdf from 'html-pdf'
import md5 from 'md5'
import AWS from 'aws-sdk'
import Promise from 'bluebird'
import moment from 'moment'

const tempDir = '/tmp'
const config = require('./config')
const s3 = new AWS.S3()

export const main = (event, context) => {
    console.log("Got event: ", event)

    AWS.config.update({
        accessKeyId: config.awsKey,
        secretAccessKey: config.awsSecret,
        region: 'us-east-1'
    })

    const filename = md5(event.html) + ".pdf"

    createPDF(event.html, filename).then(function(result) {
        uploadToS3(filename, result.filename).then(function(result) {
            getOneTimeUrl(filename).then(function(result) {
                return context.succeed(result)
            }, function(err) {
                console.log(err)
                return context.fail(err)
            })
        }, function(err) {
            console.log(err)
            return context.fail(err)
        })
    }, function(err) {
        console.log(err)
        return context.fail(err)
    })
}

const createPDF = (html, filename) => {
    console.log("Creating PDF")
    var promise = new Promise(function(resolve, reject) {
        pdf.create(html).toFile(filename, function(err, res) {
            if (err) {
                reject(err)
            } else {
                resolve(res)
            }
        })
    })
    return promise
}

const uploadToS3 = (filename, filePath) => {
    console.log("Pushing to S3")
    var promise = new Promise(function(resolve, reject) {

        var fileToUpload = fs.createReadStream(filePath)
        var expiryDate = moment().add(1, 'm').toDate()

        var uploadParams = {
            Bucket: config.pdfBucket,
            Key: filename,
            Body: fileToUpload
        }

        s3.upload(uploadParams, function(err, data) {
            if(err) {
                reject(err)
            } else {
                resolve(data)
            }
        })
    })
    return promise
}

const getOneTimeUrl = (filename) => {
    var promise = new Promise(function(resolve, reject) {
        var params = {
            Bucket: config.pdfBucket,
            Key: filename,
            Expires: 60
        }

        s3.getSignedUrl('getObject', params, function(err, url) {
            if (err) {
                reject(err)
            } else {
                resolve(url)
            }
        })
    })
    return promise
}

似乎是 html-pdf 中的一个问题。由于我在这里做了一些阅读,我认为这可能是 PhantomJS(html-pdf 依赖)的问题:https://engineering.fundingcircle.com/blog/2015/04/09/aws-lambda-for-great-victory/,但是,由于 Lambda 已将最大 zip 大小提高到 50mb,所以上传没有问题二进制文件。

有什么想法吗?

【问题讨论】:

    标签: javascript node.js amazon-web-services phantomjs aws-lambda


    【解决方案1】:

    html-pdf 底层使用phantomjs,安装时需要编译一些二进制文件。我猜您的问题是您正在部署那些本地编译的二进制文件,但 Lambda 需要在 Amazon Linux 上编译的二进制文件。

    您可以通过在运行 Amazon Linux 的 EC2 实例上构建部署包来解决此问题,然后使用例如直接从那里部署它,就像在this tutorial 中解释的那样。

    也可以查看this answer 的类似问题。

    【讨论】:

    • 试试这个,一旦我明白了就会接受,感谢朋友的澄清
    • 好吧,最后没有用...我能够在 ec2 上构建我的代码并部署好,但我最终遇到了完全相同的错误...查看 node_modules html-pdf 的,它使用的是 phantomjs_prebuilt,认为这可能与它有关吗?
    • 代码是否在 EC2 上运行?使用 phantomjs-prebuilt 时,您可能需要调用 npm rebuild
    • 是的,它在 ec2 上按预期运行(当我使用 lambda-local 运行 dist/ 代码时)
    • 我终于可以运行它了。 Phantomjs-prebuilt 在运行时动态拉入任何被认为是“理想”的 phantomjs 库,而不是在我运行 npm install 或 npm rebuild 时静态编译二进制文件。因此,即使我设置了可执行标志,最终加载的二进制文件,我也无权访问(读取:权限)。解决方法是在 aws linux 上静态编译我自己的 phantomjs 库,然后将其上传到 s3 存储桶,然后告诉 html-pdf 使用该静态编译的 phantom 版本,而不是找到它自己的...感谢您的所有帮助!
    猜你喜欢
    • 1970-01-01
    • 2019-12-14
    • 2021-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-21
    • 2019-10-14
    • 1970-01-01
    相关资源
    最近更新 更多