5

Stworzyłem więc tę fajną małą lambdę, która działa świetnie lokalnie, jednak nie tak bardzo, gdy faktycznie jest na wolności.Problemy z uprawnieniami na AWS Lambda, nie mogą odrodzić procesu potomnego

Funkcja lambda przyjmuje zdarzenie, z html w źródle zdarzenia, konwertuje ten html do pliku PDF (za pomocą modułu węzła html-pdf), przekazuje ten plik PDF do zasobnika s3, a następnie przekazuje podpisany adres URL, który wygasa w 60 sekund.

A przynajmniej tak powinno się stać (znowu działa lokalnie). Podczas badania na Lambda, pojawia się następujący błąd:

{ 
    "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)" 
    ] 
} 

Oto sam kod (nie skompilowane, jest poręczny zadanie łyk za to)

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 
} 

Wydaje się problem w html-PDF. Pomyślałem, że może to być problem z PhantomJS (od czego html-pdf zależy) z powodu jakiegoś odczytu, który tu zrobiłem: https://engineering.fundingcircle.com/blog/2015/04/09/aws-lambda-for-great-victory/, ponieważ Lambda zderzyła się z maksymalnym zipem do 50mb, nie mam problemu z załadowaniem pliku binarnego .

Jakieś myśli?

Odpowiedz

2

html-pdf używa phantomjs pod maską, która musi skompilować niektóre pliki binarne podczas instalacji. Domyślam się, że twój problem polega na tym, że instalujesz te skompilowane lokalnie pliki binarne, ale Lambda potrzebuje plików binarnych skompilowanych na Amazon Linuksie.

Możesz rozwiązać ten problem, budując pakiet wdrażania na instancji EC2, która działa w systemie Amazon Linux, a następnie na przykład w systemie Linux. bezpośrednio wdrożyć stamtąd, jak to wyjaśniono w this tutorial.

Sprawdź również pod podobnym problemem this answer.

+0

Próbuję tego, zaakceptuję, gdy będę już w pełni zrozumiały, dzięki za jasność przyjaciela – wvm2008

+0

, w końcu to się nie udało ... Udało mi się zbudować kod na ec2 i wdrożyć ok, ale Kończę dokładnie z tym samym błędem ... patrząc w module node_modules html-pdf, używa on phantomjs_prebuilt, myślę, że może mieć z tym coś wspólnego? – wvm2008

+0

Czy kod działa na EC2? Być może będziesz musiał wywołać 'npm rebuild' podczas używania phantomjs-prebuilt. – birnbaum

Powiązane problemy