Can I write a bash script inside a Lambda function? I read in the aws docs that it can execute code written in Python, NodeJS and Java 8.
It is mentioned in some doc
AWS recently announced the "Lambda Runtime API and Lambda Layers", two new features that enable developers to build custom runtimes. So, it's now possibile to directly run even bash scripts in Lambda without hacks.
As this is a very new feature (November 2018), there isn't much material yet around and some manual work still needs to be done, but you can have a look at this Github repo for an example to start with (disclaimer: I didn't test it). Below a sample handler in bash:
function handler () {
EVENT_DATA=$1
echo "$EVENT_DATA" 1>&2;
RESPONSE="{\"statusCode\": 200, \"body\": \"Hello World\"}"
echo $RESPONSE
}
This actually opens up the possibility to run any programming language within a Lambda. Here it is an AWS tutorial about publishing custom Lambda runtimes.
Its possible using the 'child_process' node module.
const exec = require('child_process').exec;
exec('echo $PWD && ls', (error, stdout, stderr) => {
if (error) {
console.log("Error occurs");
console.error(error);
return;
}
console.log(stdout);
console.log(stderr);
});
This will display the current working directory and list the files.
Now you can create Lambda functions written in any kind of language by providing a custom runtime which teaches the Lambda function to understand the syntax of the language you want to use.
You can follow this to learn more AWS Lambda runtimes
Something that might help, I'm using Node to call the bash script. I uploaded the script and the nodejs file in a zip to lambda, using the following code as the handler.
exports.myHandler = function(event, context, callback) {
const execFile = require('child_process').execFile;
execFile('./test.sh', (error, stdout, stderr) => {
if (error) {
callback(error);
}
callback(null, stdout);
});
}
You can use the callback to return the data you need.
As you mentioned, AWS does not provide a way to write Lambda function using Bash.
To work around it, if you really need bash function, you can "wrap" your bash script within any languages.
Here is an example with Java:
Process proc = Runtime.getRuntime().exec("./your_script.sh");
Depending on your business needs, you should consider using native languages(Python, NodeJS, Java) to avoid performance loss.
AWS supports custom runtimes now based on this announcement here. I already tested bash script and it worked. All you need is to create a new lambda and choose runtime
of type Custom
it will create the following file structure:
mylambda_func
|- bootstrap
|- function.sh
Example Bootstrap
:
#!/bin/sh
set -euo pipefail
# Handler format: <script_name>.<function_name>
# The script file <script_name>.sh must be located in
# the same directory as the bootstrap executable.
source $(dirname "$0")/"$(echo $_HANDLER | cut -d. -f1).sh"
while true
do
# Request the next event from the Lambda Runtime
HEADERS="$(mktemp)"
EVENT_DATA=$(curl -v -sS -LD "$HEADERS" -X GET "http://${AWS_LAMBDA_RUNTIME_API}/2018-06-01/runtime/invocation/next")
INVOCATION_ID=$(grep -Fi Lambda-Runtime-Aws-Request-Id "$HEADERS" | tr -d '[:space:]' | cut -d: -f2)
# Execute the handler function from the script
RESPONSE=$($(echo "$_HANDLER" | cut -d. -f2) "$EVENT_DATA")
# Send the response to Lambda Runtime
curl -v -sS -X POST "http://${AWS_LAMBDA_RUNTIME_API}/2018-06-01/runtime/invocation/$INVOCATION_ID/response" -d "$RESPONSE"
done
Example handler.sh
:
function handler () {
EVENT_DATA=$1
RESPONSE="{\"statusCode\": 200, \"body\": \"Hello from Lambda!\"}"
echo $RESPONSE
}
P.S. However in some cases you can't achieve what's needed because of the environment restrictions, such cases need AWS Systems Manager to Run command
, OpsWork (Chef/Puppet) based on what you're more familiar with or periodically using ScheduledTasks
in ECS cluster.
More Information about bash and how to zip and publish it, please check the following links: