2

This is the line in my Lambda function that's raising an error:

// running in Node 8
const { execSync } = require('child_process');
execSync('curl https://github.com');

I'm trying to upgrade my Lambda function from Node 8 to Node 10 or Node 12, since Node 8 on Lambda is being deprecated at the end of December, 2019 (so I won't be able to update it). However, when I dig into my CloudWatch logs I'm seeing the following error:

bin/sh: curl: command not found

And when I update my Lambda function to just run which curl I get a similar error: bin/sh: which: command not found

Per documentation here, I know that Node 8+, Python 3.8+ and Java 11+ are using the new AWS Lambda Runtime, Amazon Linux 2.

Any help is appreciated.

Matt
  • 5,800
  • 1
  • 44
  • 40
  • 1
    why are you curling via a subprocess rather than calling a GET from axios or requests? even using the native http/https npm module? – LostJon Dec 03 '19 at 21:26
  • We have different development environments that rely on an an underlying application used in Node, and using curl we can work on that application on most systems independently of Node. Also, we are doing quite a bit of work a the command line level through the rest of the application. – Matt Dec 03 '19 at 21:36
  • sure...but using Node should still follow good package dependency management. your CI/CD pipelines should handle consistency. Anyways, this is a deviation from your initial question...for which I have no good response. I would imaging that if you are using Linux specific tooling (ie curl or ssh) you will always run into issues with base Linux images because they try to be as lean and mean as possible. – LostJon Dec 03 '19 at 21:50

2 Answers2

3

Node V10 and V12 above is based on Amazon Linux 2 and you can not run curl.

enter image description here

cURL on AWS Lambda gives command not found error

You have two options

  • Use native binary package in AWS Lambda
  • Use nodejs request or http built-in module

How do I use Amazon Linux AMI native binary packages in an AWS Lambda deployment package?

Short Description

A Lambda deployment package is a .zip file that contains your code and any dependencies. The Lambda execution environment is based on a specific Amazon Linux AMI and kernel version. Any native binaries that are used in a Lambda deployment package must be compiled in this environment, and only 64-bit binaries are supported.

To use the Amazon Linux AMI native binary packages, you can extract the 64-bit libraries and then include them in your Lambda deployment package. (Another option, that is not covered in this article, is to download the source code to the shared library and then recompile the package.)

lambda-runtimes

So as suggested in the comment the other way is to use the node package.

you can try for testing purpose something like

exports.handler = async (event) => {
  const https = require('https');                
  var response=https.get('https://api.github.com');
  return JSON.stringify(response.output)
}

Adiii
  • 54,482
  • 7
  • 145
  • 148
  • Thanks for the answer. What is the source of the short description? Could you add a link please? – Matt Dec 03 '19 at 22:33
  • 1
    Oh here it is https://aws.amazon.com/premiumsupport/knowledge-center/lambda-linux-binary-package/ – Adiii Dec 03 '19 at 22:36
  • We're also extracting TAR files from the command line. I was able to successfully swap curl for javascript's request library, adding many lines of code, but have not yet found a great js solution for TAR. I may end up trying to import these libraries manually and going back to the command line. – Matt Dec 09 '19 at 13:37
1

Instead of zipping the native binary package with lambda function, I would suggest to have a look at AWS Lambda Layers (https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html)

This way if you have multiple lambda functions, they could share these binary packages. You will have a to upload the content in a nodejs folder and zip it. In your code you could access it /opt/nodejs/ path

By the way I would prefer to use nodejs to make http calls instead of using curl from nodejs.

Ashish Modi
  • 7,529
  • 2
  • 20
  • 35
  • Thanks, Ashnish. I will look into Layers. It's not just cURL for us, this just happened to be the library I chose in the question. I was able to successfully replace curl with the JS request libarary (1 line of code to 20, unfortunately), but now we need to extract a gzip'd TAR. Haven't found a tool comparable to those in the command line. – Matt Dec 09 '19 at 13:34