├── README.md ├── core.sh ├── deploy.sh ├── input.txt ├── lambdabash.js ├── lambdabash.zip ├── outputfile.txt ├── package.json ├── settings.conf └── test.sh /README.md: -------------------------------------------------------------------------------- 1 | # AWS Lambda Bash Function Blueprint Template 2 | 3 | #### by Jacob Baloul 4 | 5 | #### tags: aws lambda bash template, lambda bash shell script wrapped in nodejs handler 6 | 7 | ### Description: 8 | Currently, aws lambda does not support running bash functions directly. 9 | This basic lambda function wraps a bash shell script with a nodejs handler. 10 | The nodejs lambda handler calls the "core" bash script, that includes example random generator code. 11 | Replace or modify the core.sh script to include your own shell-fu. 12 | You can use core.sh to call ./yourScripts.sh 13 | 14 | Currently logging stdout to cloudwatch 15 | 16 | 17 | 18 | ### Prerequisites 19 | 20 | * install aws cli - http://docs.aws.amazon.com/cli/latest/userguide/installing.html 21 | * run 'aws configure' to create your ~/.aws/credentials & ~/.aws/config file 22 | * make sure your user has permissions to create lambda functions 23 | 24 | 25 | ### Recommended 26 | 27 | * brew install nodejs 28 | 29 | 30 | 31 | ### Step 1: setup settings file 32 | 33 | * Create the Execution Role (IAM Role), and use the arn string in the IAMARN variable 34 | http://docs.aws.amazon.com/lambda/latest/dg/with-userapp-walkthrough-custom-events-create-iam-role.html 35 | 36 | * Edit settings.conf and replace IAMARN with your iam roles arn 37 | 38 | 39 | 40 | ### Step 2: Package, Deploy & Test lambda bash function on your aws account: 41 | 42 | ``` 43 | $ ./deploy.sh 44 | ``` 45 | 46 | 47 | 48 | 49 | ##### more... 50 | 51 | ### Test locally 52 | 53 | ``` 54 | $ node lambdabash.js 55 | ``` 56 | 57 | 58 | ### Test lambdabash function, defaults to 10 loops, control with first arg 59 | ``` 60 | $ ./test.sh 61 | 62 | $ ./test.sh 1 63 | 64 | $ ./test.sh 5 65 | ``` 66 | 67 | 68 | ### Simple Load Test, 2K invocations, with some parallel execution 69 | ``` 70 | $ seq 1 200 | while read cnt 71 | do 72 | ./test.sh 10 & 73 | done 74 | ``` 75 | 76 | 77 | ### Ex: Create Lambda Function 78 | ``` 79 | aws lambda create-function \ 80 | --function-name lambdabash \ 81 | --zip-file fileb://lambdabash.zip \ 82 | --role arn:aws:iam::292361995972:role/lambda_s3_exec_role \ 83 | --handler lambdabash.handler \ 84 | --runtime nodejs 85 | ``` 86 | 87 | ### Ex: Invoke Lambda Function 88 | ``` 89 | aws lambda invoke \ 90 | --invocation-type RequestResponse \ 91 | --function-name lambdabash \ 92 | --region us-east-1 \ 93 | --log-type Tail \ 94 | --payload file://input.txt \ 95 | --output json \ 96 | outputfile.txt 97 | ``` 98 | 99 | OR 100 | 101 | ``` 102 | aws lambda invoke \ 103 | --invocation-type RequestResponse \ 104 | --function-name lambdabash \ 105 | --region us-east-1 \ 106 | --log-type Tail \ 107 | --payload '{"key1":"value1", "key2":"value2", "key3":"value3"}' \ 108 | outputfile.txt 109 | ``` 110 | 111 | ### Delete the Lambda Function 112 | ``` 113 | aws lambda delete-function \ 114 | --function-name lambdabash \ 115 | --region us-east-1 116 | ``` 117 | 118 | 119 | ### Ex: Successful output after uploading the new zip to lambda... 120 | 121 | ``` 122 | ------------------------------------------------------------------------------- 123 | | CreateFunction | 124 | +--------------+--------------------------------------------------------------+ 125 | | CodeSha256 | WDYd3sOWHej9r5HmhsJAiSPUzupAwBUvhrAuAc+rqEI= | 126 | | CodeSize | 1862 | 127 | | Description | | 128 | | FunctionArn | arn:aws:lambda:us-east-1:292361995972:function:lambdabash | 129 | | FunctionName| lambdabash | 130 | | Handler | lambdabash.handler | 131 | | LastModified| 2016-03-02T16:05:32.917+0000 | 132 | | MemorySize | 128 | 133 | | Role | arn:aws:iam::292361995972:role/lambda_s3_exec_role | 134 | | Runtime | nodejs | 135 | | Timeout | 3 | 136 | | Version | $LATEST | 137 | +--------------+--------------------------------------------------------------+ 138 | ``` 139 | 140 | ### Ex: Successful test of new lambda function by invoking... 141 | 142 | ``` 143 | { 144 | "LogResult": "U1RBUlQgUmVxdWVzdElkOiA5OGExNTM1My1lMDkwLTExZTUtOTA0MC1mNTliMGZkNjIzOTQgVmVyc2lvbjogJExBVEVTVAoyMDE2LTAzLTAyVDE2OjA1OjM1LjMzM1oJOThhMTUzNTMtZTA5MC0xMWU1LTkwNDAtZjU5YjBmZDYyMzk0CXN0ZG91dDogQkFTSCBSQU5ET006IDEzNDQKCkVORCBSZXF1ZXN0SWQ6IDk4YTE1MzUzLWUwOTAtMTFlNS05MDQwLWY1OWIwZmQ2MjM5NApSRVBPUlQgUmVxdWVzdElkOiA5OGExNTM1My1lMDkwLTExZTUtOTA0MC1mNTliMGZkNjIzOTQJRHVyYXRpb246IDE1OS40NyBtcwlCaWxsZWQgRHVyYXRpb246IDIwMCBtcyAJTWVtb3J5IFNpemU6IDEyOCBNQglNYXggTWVtb3J5IFVzZWQ6IDI5IE1CCQo=", 145 | "StatusCode": 200 146 | } 147 | ``` 148 | 149 | 150 | ### Decoding the response 151 | 152 | ``` 153 | $ echo "_LogResult_" | base64 --decode 154 | ``` 155 | 156 | ``` 157 | $ echo "U1RBUlQgUmVxdWVzdElkOiA5OGExNTM1My1lMDkwLTExZTUtOTA0MC1mNTliMGZkNjIzOTQgVmVyc2lvbjogJExBVEVTVAoyMDE2LTAzLTAyVDE2OjA1OjM1LjMzM1oJOThhMTUzNTMtZTA5MC0xMWU1LTkwNDAtZjU5YjBmZDYyMzk0CXN0ZG91dDogQkFTSCBSQU5ET006IDEzNDQKCkVORCBSZXF1ZXN0SWQ6IDk4YTE1MzUzLWUwOTAtMTFlNS05MDQwLWY1OWIwZmQ2MjM5NApSRVBPUlQgUmVxdWVzdElkOiA5OGExNTM1My1lMDkwLTExZTUtOTA0MC1mNTliMGZkNjIzOTQJRHVyYXRpb246IDE1OS40NyBtcwlCaWxsZWQgRHVyYXRpb246IDIwMCBtcyAJTWVtb3J5IFNpemU6IDEyOCBNQglNYXggTWVtb3J5IFVzZWQ6IDI5IE1CCQo=" | base64 --decode 158 | START RequestId: 98a15353-e090-11e5-9040-f59b0fd62394 Version: $LATEST 159 | 2016-03-02T16:05:35.333Z 98a15353-e090-11e5-9040-f59b0fd62394 stdout: BASH RANDOM: 1344 160 | 161 | END RequestId: 98a15353-e090-11e5-9040-f59b0fd62394 162 | REPORT RequestId: 98a15353-e090-11e5-9040-f59b0fd62394 Duration: 159.47 ms Billed Duration: 200 ms Memory Size: 128 MB Max Memory Used: 29 MB 163 | ``` 164 | 165 | 166 | ### More Documentation 167 | * http://docs.aws.amazon.com/lambda/latest/dg/with-userapp-walkthrough-custom-events-create-test-function.html 168 | -------------------------------------------------------------------------------- /core.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # core.sh 3 | # simple shell script to be executed by aws lambda nodejs wrapper 4 | # Author: @JacobBaloul 5 | 6 | 7 | ### 8 | ### MAIN 9 | ### 10 | echo "=START=" 11 | 12 | # TODO: 13 | # Customize below... 14 | # any bash commands and shell-fu here. 15 | # you can package your existing shell scripts and call them here 16 | # 17 | echo "BASH RANDOM: $RANDOM" && seq 1 18 && echo {19..36} 18 | uname -a 19 | uptime 20 | cat /proc/cpuinfo 21 | free -m 22 | df -h 23 | date 24 | ls -ltrh / /root /home /var /var/log 25 | cat /etc/passwd 26 | whoami 27 | 28 | echo "=END=" 29 | ### 30 | -------------------------------------------------------------------------------- /deploy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # deploy lambdabash function to aws 3 | # author: @jacobbaloul 4 | # 5 | # 6 | function check_error(){ 7 | if test $? -gt 0 ; then 8 | echo "oops! something went wrong, aborting." 9 | exit 1 10 | fi 11 | } 12 | # 13 | 14 | ## 15 | ## BEGIN 16 | ## 17 | source settings.conf 18 | check_error 19 | 20 | echo " 21 | deleting old zip... 22 | " 23 | rm lambdabash.zip 24 | # check_error 25 | 26 | echo " 27 | packaging lambdabash, creating new zip... 28 | " 29 | zip lambdabash.zip lambdabash.js README.md package.json core.sh 30 | check_error 31 | 32 | echo " 33 | removing old lambda function (deleting zip remotely) from amazon aws lambda... 34 | " 35 | aws lambda delete-function \ 36 | --function-name lambdabash \ 37 | --profile $PROFILE \ 38 | --region $REGION 39 | 40 | #--# add if exist logic ^ 41 | #--# check_error 42 | 43 | echo " 44 | uploading new zip to lambda... 45 | " 46 | aws lambda create-function --function-name lambdabash --zip-file fileb://lambdabash.zip --role $IAMARN --handler lambdabash.handler --runtime nodejs --profile $PROFILE --region $REGION 47 | 48 | check_error 49 | 50 | echo " 51 | testing new lambda function by invoking... 52 | " 53 | aws lambda invoke \ 54 | --invocation-type RequestResponse \ 55 | --function-name lambdabash \ 56 | --region $REGION \ 57 | --log-type Tail \ 58 | --payload file://input.txt \ 59 | --profile $PROFILE \ 60 | --output json \ 61 | outputfile.txt 62 | 63 | check_error 64 | 65 | echo " 66 | ======= 67 | SUCCESS: lambdabash has been deployed 68 | ======= 69 | " 70 | -------------------------------------------------------------------------------- /input.txt: -------------------------------------------------------------------------------- 1 | { 2 | "key1":"value1", 3 | "key2":"value2", 4 | "key3":"value3" 5 | 6 | } 7 | -------------------------------------------------------------------------------- /lambdabash.js: -------------------------------------------------------------------------------- 1 | /* 2 | * lambdabash.js 3 | * Lambda Bash Function: nodejs to wrap and execute a Bash Shell Script 4 | * Author: @JacobBaloul 5 | */ 6 | 7 | console.log('Loading Lambda Bash function'); 8 | 9 | /* aws lambda handler */ 10 | exports.handler = function(event, context) { 11 | 12 | /* use spawn */ 13 | var util = require('util'), 14 | spawn = require('child_process').spawn, 15 | 16 | // ex: execute shell command 17 | // bash = spawn('ls', ['-lh', '/usr']); // the second arg is the command 18 | // options 19 | // MAIN: call the shell script 20 | bash = spawn('./core.sh', ['', '']); // [''] place holders for args 21 | 22 | bash.stdout.on('data', function (data) { // stdout handler 23 | console.log('stdout: ' + data); 24 | context.succeed('stdout: ' + data); 25 | }); 26 | 27 | bash.stderr.on('data', function (data) { // stderr handler 28 | console.log('stderr: ' + data); 29 | context.fail('stderr: ' + data); 30 | // context.fail('Something went wrong'); 31 | }); 32 | 33 | bash.on('exit', function (code) { // exit code handler 34 | console.log('lambda bash exited with code ' + code); 35 | }); 36 | }; 37 | -------------------------------------------------------------------------------- /lambdabash.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacov/lambda-bash/11177540fd4093999e20051a34cff4b3182ffff3/lambdabash.zip -------------------------------------------------------------------------------- /outputfile.txt: -------------------------------------------------------------------------------- 1 | "stdout: =START=\nBASH RANDOM: 9455\n" -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "lambdabash", 3 | "version": "1.0.0", 4 | "description": "nodejs lambda function to invoke a bash shell script", 5 | "main": "lambdabash.js", 6 | "scripts": { 7 | "test": "node lambdabash.js" 8 | }, 9 | "keywords": [ 10 | "nodejs", 11 | "lambda" 12 | ], 13 | "author": "Jacob Baloul", 14 | "license": "ISC" 15 | } 16 | -------------------------------------------------------------------------------- /settings.conf: -------------------------------------------------------------------------------- 1 | # lambdabash function configuration file 2 | 3 | # IAM ARN Role 4 | # 5 | # Create the Execution Role (IAM Role), and use the arn string in the IAMARN variable 6 | # http://docs.aws.amazon.com/lambda/latest/dg/with-userapp-walkthrough-custom-events-create-iam-role.html 7 | # 8 | export IAMARN="arn:aws:iam::2929292929229:role/lambda_s3_exec_role" 9 | 10 | 11 | # Default Lambda region 12 | export REGION="us-east-1" 13 | 14 | # Default Profile 15 | export PROFILE="default" 16 | 17 | -------------------------------------------------------------------------------- /test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # test lambdabash function in aws 3 | # author: @jacobbaloul 4 | # 5 | # 6 | function check_error(){ 7 | if test $? -gt 0 ; then 8 | echo "oops! something went wrong, aborting." 9 | exit 1 10 | fi 11 | } 12 | # 13 | 14 | ## 15 | ## BEGIN 16 | ## 17 | source settings.conf 18 | check_error 19 | 20 | 21 | 22 | if [ "$1" = '' ] 23 | then 24 | export CNT=10 # default to 10 loops for the test 25 | else 26 | export CNT=$1 27 | fi 28 | 29 | # BEGIN 30 | export CURRENTCNT=1 31 | 32 | seq 1 $CNT | while read cnt 33 | 34 | do 35 | 36 | echo " == Test #$CURRENTCNT: ==" 37 | 38 | # run the test 39 | echo " 40 | testing new lambda function by invoking... 41 | " 42 | aws lambda invoke \ 43 | --invocation-type RequestResponse \ 44 | --function-name lambdabash \ 45 | --region $REGION \ 46 | --log-type Tail \ 47 | --payload file://input.txt \ 48 | --profile $PROFILE \ 49 | --output json \ 50 | outputfile.txt 51 | 52 | 53 | cat outputfile.txt 54 | 55 | # increment current count 56 | export CURRENTCNT=$[$CURRENTCNT+1] 57 | 58 | done 59 | 60 | 61 | echo " 62 | 63 | ===== 64 | 65 | executed $CNT tests. 66 | 67 | DONE 68 | 69 | ===== 70 | " 71 | 72 | # END 73 | --------------------------------------------------------------------------------