Skip to content

Instantly share code, notes, and snippets.

@dguardado
Last active March 13, 2023 07:32
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save dguardado/7fe9ede70af1b3124f2bd519ec33a5cd to your computer and use it in GitHub Desktop.
Save dguardado/7fe9ede70af1b3124f2bd519ec33a5cd to your computer and use it in GitHub Desktop.
Starting an app with a shell script in elastic beanstalk

Starting an app with a shell script in Elastic Beanstalk

Situation

  • You need to use some environment variables in the command called by the Procfile used to start your app, but environment variables are not supported in the Procfile
  • Naturally, you move the command into a shell script where the environment variables are accessible
  • Now, any time you restart the app (deploys, etc), the running application no longer shuts down, and the new app process cannot start. You see a spew of messages in the logs about being unable to bind to the application port because it is already used.

Solution

You should prefix your app launch command inside your shell script with the exec command. So if your app launch command is my_server config.yaml, you should rewrite it to exec my_server config.yaml

Why this works

When stopping/restarting the application, Beanstalk will send kill signals to the process specified to in the Procfile. However, when we launch the application with a shell script, our app is spawned as a child process. The original script process now receives the kill signals, but our app never hears those signals and keeps running.

eg

  • PID: 123 - start_server.sh <-- receives kill signals
    • PID: 124 - my_server <-- does not receive kill signals

Prefixing the command with exec makes it so our app will take over the original process of the script, including PID, environment, etc. When this happens, OUR app will receive the kill signals.

  • PID: 123 - start_server.sh ==> (exec) my_server <-- our app takes over the original process, and now receives kill signals

Scope

This issue affects the AWS Elastic Beanstalk Java platform, and the fix has been demonstrated to work on that platform. It may also affect the Go platform, and the fix may work there but has not been verified. I am not sure if this problem is relevant to other beanstalk platforms.

web: ./start_server.sh # would like to use environment variables here, but it is not supported
#!/bin/bash
# We want to use environment variables here, but can't use them in the procfile
JAVA_OPTS="-Xmx768m -XX:+HeapDumpOnOutOfMemoryError -XX:-OmitStackTraceInFastThrow -XX:MaxJavaStackTraceDepth=-1 -Dnewrelic.environment=$MONITOR_ENV -javaagent:$PWD/newrelic.jar"
# exec here will make our application take over the process of this shell script
exec java $JAVA_OPTS -jar app.jar server config.yaml
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment