Skip to content

Latest commit

 

History

History
212 lines (156 loc) · 6.25 KB

File metadata and controls

212 lines (156 loc) · 6.25 KB

Lambda Shell Runtime (SAR)

This Serverless Application Repository (SAR) application publishes a Lambda layer that provides a minimal custom runtime for provided.al2023 using /bin/sh, plus AWS CLI v2 and jq.

Applications

Three SAR applications are published:

  • lambda-shell-runtime (wrapper that references both architectures)
  • lambda-shell-runtime-arm64
  • lambda-shell-runtime-amd64

The wrapper application publishes no layer itself; it exposes both architecture layer ARNs as stack outputs. Each architecture-specific application publishes a single Lambda layer version.

Install

Deploy the SAR application that matches your needs. After deployment, read the appropriate output and attach it to your function.

Example (wrapper application):

STACK_NAME=lambda-shell-runtime
LAYER_ARN=$(aws cloudformation describe-stacks \
  --stack-name "$STACK_NAME" \
  --query "Stacks[0].Outputs[?OutputKey=='LayerVersionArnArm64'].OutputValue" \
  --output text)

For x86_64, use LayerVersionArnAmd64 instead.

Example (single architecture):

STACK_NAME=lambda-shell-runtime-arm64
LAYER_ARN=$(aws cloudformation describe-stacks \
  --stack-name "$STACK_NAME" \
  --query "Stacks[0].Outputs[?OutputKey=='LayerVersionArn'].OutputValue" \
  --output text)

Use the layer

  • Runtime: provided.al2023
  • Architecture: arm64 or x86_64 (must match the layer)
  • Handler: function.handler (script stored as function.sh in your function package)

Lambda automatically includes /opt/bin and /opt/lib from layers in PATH and LD_LIBRARY_PATH.

Quick start (create a Lambda function)

If you prefer to work entirely in the AWS Lambda console, skip to Lambda console notes below.

  1. Deploy the SAR application (wrapper or per-arch) and export the layer ARN.

Wrapper (arm64 output example):

STACK_NAME=lambda-shell-runtime
LAYER_ARN=$(aws cloudformation describe-stacks \
  --stack-name "$STACK_NAME" \
  --query "Stacks[0].Outputs[?OutputKey=='LayerVersionArnArm64'].OutputValue" \
  --output text)

Per-arch application:

STACK_NAME=lambda-shell-runtime-arm64
LAYER_ARN=$(aws cloudformation describe-stacks \
  --stack-name "$STACK_NAME" \
  --query "Stacks[0].Outputs[?OutputKey=='LayerVersionArn'].OutputValue" \
  --output text)

For x86_64, use LayerVersionArnAmd64 (wrapper) or deploy the amd64 application.

  1. Create a simple handler and package it:
cat > function.sh <<'SH'
#!/bin/sh

handler() {
  jq -c '{ok:true, input:.}'
}
SH

zip -r function.zip function.sh
  1. Create an execution role (if you do not already have one):
aws iam create-role \
  --role-name lambda-shell-runtime-role \
  --assume-role-policy-document '{
    "Version": "2012-10-17",
    "Statement": [{
      "Effect": "Allow",
      "Principal": {"Service": "lambda.amazonaws.com"},
      "Action": "sts:AssumeRole"
    }]
  }'

aws iam attach-role-policy \
  --role-name lambda-shell-runtime-role \
  --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole

ROLE_ARN=$(aws iam get-role \
  --role-name lambda-shell-runtime-role \
  --query "Role.Arn" \
  --output text)
  1. Create the function with the layer:
aws lambda create-function \
  --function-name hello-shell-runtime \
  --runtime provided.al2023 \
  --handler function.handler \
  --architectures arm64 \
  --role "$ROLE_ARN" \
  --zip-file fileb://function.zip \
  --layers "$LAYER_ARN"

For x86_64, set --architectures x86_64 and use the amd64 layer ARN.

  1. Invoke it:
aws lambda invoke \
  --function-name hello-shell-runtime \
  --payload '{"message":"hello"}' \
  response.json

cat response.json

Lambda console notes (important)

If you create a function in the AWS Lambda console, it may show sample files like bootstrap.sh and hello.sh. Those are for a different custom-runtime tutorial and are not used with this layer. This runtime already provides the bootstrap in the layer. Your function package should only include a handler script (for example, function.sh) that defines a handler function.

Console checklist:

  • Runtime: provided.al2023
  • Architecture: arm64 or x86_64 (must match the layer you attached)
  • Handler: function.handler (script file is function.sh, sourced by /bin/sh)
  • Layers: add the layer ARN from the SAR stack output
  • Performance: the AWS CLI layer is large; cold starts can be slow at 128 MB. Raising memory (for example, to 512 MB) and retrying a second invocation yields faster runs.

Example handler file (save as function.sh in the console editor):

#!/bin/sh

handler() {
  jq -c '{ok:true, input:.}'
}

The runtime sources this file; it does not need to be executable. If you want bash, make the handler file executable, set a #!/bin/bash shebang, and set the Lambda handler to the filename (no dot).

Handler contract

Your handler is a shell script that defines a function. For example, _HANDLER=function.handler loads function.sh from LAMBDA_TASK_ROOT and invokes handler with the event JSON on STDIN.

Execution modes:

  • function.handler: the runtime sources function.sh with /bin/sh and invokes the handler function. The file does not need to be executable and must use POSIX sh syntax.

  • handler (no dot): the runtime treats _HANDLER as a handler file path. If the file is executable, it is run directly (shebang honored). If not, the runtime invokes it with /bin/sh. Use this mode for bash by making the handler executable and starting it with #!/bin/bash.

  • reads the event JSON from STDIN

  • writes the response JSON to STDOUT

  • writes logs to STDERR

The runtime does not transform the event or response payload.

Remaining time helper

LAMBDA_RUNTIME_DEADLINE_MS is an epoch time in milliseconds. The helper below returns the remaining time in milliseconds for POSIX sh handlers.

remaining_time_ms() {
  if [ -z "${LAMBDA_RUNTIME_DEADLINE_MS:-}" ]; then
    return 1
  fi
  now_ms=$(date +%s%3N 2>/dev/null || true)
  case "$now_ms" in
    ''|*[!0-9]*)
      now_ms=$(( $(date +%s) * 1000 ))
      ;;
  esac
  printf '%s\n' "$((LAMBDA_RUNTIME_DEADLINE_MS - now_ms))"
}

On AL2023, date supports %s and %3N. If %3N is unavailable, the helper falls back to second precision.

Versioning

The SAR SemanticVersion matches the bundled AWS CLI v2 version.