fabric8镜像的deployments脚本

因为没有直接使用fabric8的镜像(https://hub.docker.com/r/fabric8/java-jboss-openjdk8-jdk/~/dockerfile/), 但是又羡慕其自动内存计算的功能, 所以从facric8的把"/deployments"目录下的脚本都活剥出来, 也就是抄袭出来, 打算加到自己的镜像中去.

run-java.sh: 

#!/bin/sh

# Fail on a single failed command
set -eo pipefail

# ==========================================================
# Generic run script for running arbitrary Java applications
#
# Source and Documentation can be found
# at https://github.com/fabric8io/run-java-sh
#
# ==========================================================

# Error is indicated with a prefix in the return value
check_error() {
  local msg=$1
  if echo ${msg} | grep -q "^ERROR:"; then
    echo ${msg}
    exit 1
  fi
}

# The full qualified directory where this script is located
get_script_dir() {
  # Default is current directory
  local dir=`dirname "$0"`
  local full_dir=`cd "${dir}" ; pwd`
  echo ${full_dir}
}

# Try hard to find a sane default jar-file
auto_detect_jar_file() {
  local dir=$1

  # Filter out temporary jars from the shade plugin which start with 'original-'
  local old_dir=$(pwd)
  cd ${dir}
  if [ $? = 0 ]; then
    local nr_jars=`ls *.jar 2>/dev/null | grep -v '^original-' | wc -l | tr -d '[[:space:]]'`
    if [ ${nr_jars} = 1 ]; then
      ls *.jar | grep -v '^original-'
      exit 0
    fi
    cd ${old_dir}
    echo "ERROR: Neither \$JAVA_MAIN_CLASS nor \$JAVA_APP_JAR is set and ${nr_jars} found in ${dir} (1 expected)"
  else
    echo "ERROR: No directory ${dir} found for auto detection"
  fi
}

# Check directories (arg 2...n) for a jar file (arg 1)
get_jar_file() {
  local jar=$1
  shift;

  if [ "${jar:0:1}" = "/" ]; then
    if [ -f "${jar}" ]; then
      echo "${jar}"
    else
      echo "ERROR: No such file ${jar}"
    fi
  else
    for dir in $*; do
      if [ -f "${dir}/$jar" ]; then
        echo "${dir}/$jar"
        return
      fi
    done
    echo "ERROR: No ${jar} found in $*"
  fi
}

load_env() {
  local script_dir=$1

  # Configuration stuff is read from this file
  local run_env_sh="run-env.sh"

  # Load default default config
  if [ -f "${script_dir}/${run_env_sh}" ]; then
    source "${script_dir}/${run_env_sh}"
  fi

  # Check also $JAVA_APP_DIR. Overrides other defaults
  # It's valid to set the app dir in the default script
  if [ -z "${JAVA_APP_DIR}" ]; then
    JAVA_APP_DIR="${script_dir}"
  else
    if [ -f "${JAVA_APP_DIR}/${run_env_sh}" ]; then
      source "${JAVA_APP_DIR}/${run_env_sh}"
    fi
  fi
  export JAVA_APP_DIR

  # Read in container limits and export the as environment variables
  if [ -f "${script_dir}/container-limits" ]; then
    source "${script_dir}/container-limits"
  fi

  # JAVA_LIB_DIR defaults to JAVA_APP_DIR
  export JAVA_LIB_DIR="${JAVA_LIB_DIR:-${JAVA_APP_DIR}}"
  if [ -z "${JAVA_MAIN_CLASS}" ] && [ -z "${JAVA_APP_JAR}" ]; then
    JAVA_APP_JAR="$(auto_detect_jar_file ${JAVA_APP_DIR})"
    check_error "${JAVA_APP_JAR}"
  fi

  if [ "x${JAVA_APP_JAR}" != x ]; then
    local jar="$(get_jar_file ${JAVA_APP_JAR} ${JAVA_APP_DIR} ${JAVA_LIB_DIR})"
    check_error "${jar}"
    export JAVA_APP_JAR=${jar}
  else
    export JAVA_MAIN_CLASS
  fi
}

# Check for standard /opt/run-java-options first, fallback to run-java-options in the path if not existing
run_java_options() {
  if [ -f "/opt/run-java-options" ]; then
    echo `sh /opt/run-java-options`
  else
    which run-java-options >/dev/null 2>&1
    if [ $? = 0 ]; then
      echo `run-java-options`
    fi
  fi
}

# Combine all java options
get_java_options() {
  local dir=$(get_script_dir)
  local java_opts
  local debug_opts
  if [ -f "$dir/java-default-options" ]; then
    java_opts=$($dir/java-default-options)
  fi
  if [ -f "$dir/debug-options" ]; then
    debug_opts=$($dir/debug-options)
  fi
  # Normalize spaces with awk (i.e. trim and elimate double spaces)
  echo "${JAVA_OPTIONS} $(run_java_options) ${debug_opts} ${java_opts}" | awk '$1=$1'
}

# Read in a classpath either from a file with a single line, colon separated
# or given line-by-line in separate lines
# Arg 1: path to claspath (must exist), optional arg2: application jar, which is stripped from the classpath in
# multi line arrangements
format_classpath() {
  local cp_file="$1"
  local app_jar="$2"

  local wc_out=`wc -l $1 2>&1`
  if [ $? -ne 0 ]; then
    echo "Cannot read lines in ${cp_file}: $wc_out"
    exit 1
  fi

  local nr_lines=`echo $wc_out | awk '{ print $1 }'`
  if [ ${nr_lines} -gt 1 ]; then
    local sep=""
    local classpath=""
    while read file; do
      local full_path="${JAVA_LIB_DIR}/${file}"
      # Don't include app jar if include in list
      if [ x"${app_jar}" != x"${full_path}" ]; then
        classpath="${classpath}${sep}${full_path}"
      fi
      sep=":"
    done < "${cp_file}"
    echo "${classpath}"
  else
    # Supposed to be a single line, colon separated classpath file
    cat "${cp_file}"
  fi
}

# Fetch classpath from env or from a local "run-classpath" file
get_classpath() {
  local cp_path="."
  if [ "x${JAVA_LIB_DIR}" != "x${JAVA_APP_DIR}" ]; then
    cp_path="${cp_path}:${JAVA_LIB_DIR}"
  fi
  if [ -z "${JAVA_CLASSPATH}" ] && [ "x${JAVA_MAIN_CLASS}" != x ]; then
    if [ "x${JAVA_APP_JAR}" != x ]; then
      cp_path="${cp_path}:${JAVA_APP_JAR}"
    fi
    if [ -f "${JAVA_LIB_DIR}/classpath" ]; then
      # Classpath is pre-created and stored in a 'run-classpath' file
      cp_path="${cp_path}:`format_classpath ${JAVA_LIB_DIR}/classpath ${JAVA_APP_JAR}`"
    else
      # No order implied
      cp_path="${cp_path}:${JAVA_APP_DIR}/*"
    fi
  elif [ "x${JAVA_CLASSPATH}" != x ]; then
    # Given from the outside
    cp_path="${JAVA_CLASSPATH}"
  fi
  echo "${cp_path}"
}

# Set process name if possible
get_exec_args() {
  EXEC_ARGS=""
  if [ "x${JAVA_APP_NAME}" != x ]; then
    # Not all shells support the 'exec -a newname' syntax..
    `exec -a test true 2>/dev/null`
    if [ "$?" = 0 ] ; then
      echo "-a '${JAVA_APP_NAME}'"
    else
      # Lets switch to bash if you have it installed...
      if [ -f "/bin/bash" ] ; then
        exec "/bin/bash" $0 $@
      fi
    fi
  fi
}

# Start JVM
startup() {
  # Initialize environment
  load_env $(get_script_dir)

  local args
  cd ${JAVA_APP_DIR}
  if [ "x${JAVA_MAIN_CLASS}" != x ] ; then
     args="${JAVA_MAIN_CLASS}"
  else
     args="-jar ${JAVA_APP_JAR}"
  fi
  echo exec $(get_exec_args) java $(get_java_options) -cp "$(get_classpath)" ${args} $*
  exec $(get_exec_args) java $(get_java_options) -cp "$(get_classpath)" ${args} $*
}

# =============================================================================
# Fire up
startup $*

java-default-options:

#!/bin/sh
# =================================================================
# Detect whether running in a container and set appropriate options
# for limiting Java VM resources
#
# Usage: JAVA_OPTIONS="$(java-default-options.sh)"

# Env Vars evaluated:

# JAVA_OPTIONS: Checked for already set options
# JAVA_MAX_MEM_RATIO: Ratio use to calculate a default maximum Memory, in percent.
#                     E.g. the default value "50" implies that 50% of the Memory
#                     given to the container is used as the maximum heap memory with
#                     '-Xmx'. It is a heuristic and should be better backed up with real
#                     experiments and measurements.
#                     For a good overviews what tuning options are available -->
#                             https://youtu.be/Vt4G-pHXfs4
#                             https://www.youtube.com/watch?v=w1rZOY5gbvk
#                             https://vimeo.com/album/4133413/video/181900266
# Also note that heap is only a small portion of the memory used by a JVM. There are lot
# of other memory areas (metadata, thread, code cache, ...) which addes to the overall
# size. There is no easy solution for this, 50% seems to be are reasonable compromise.
# However, when your container gets killed because of an OOM, then you should tune
# the absolute values
#

# Check for memory options and calculate a sane default if not given
max_memory() {
  # Check whether -Xmx is already given in JAVA_OPTIONS. Then we dont
  # do anything here
  if echo "${JAVA_OPTIONS}" | grep -q -- "-Xmx"; then
    return
  fi

  # Check if explicitely disabled
  if [ "x$JAVA_MAX_MEM_RATIO" = "x0" ]; then
    return
  fi

  # Check for the 'real memory size' and caluclate mx from a ratio
  # given (default is 50%)
  if [ "x$CONTAINER_MAX_MEMORY" != x ]; then
    local max_mem="${CONTAINER_MAX_MEMORY}"
    local ratio=${JAVA_MAX_MEM_RATIO:-50}
    local mx=$(echo "${max_mem} ${ratio} 1048576" | awk '{printf "%d\n" , ($1*$2)/(100*$3) + 0.5}')
    echo "-Xmx${mx}m"
  fi
}

# Switch on diagnostics except when switched off
diagnostics() {
  if [ "x$JAVA_DIAGNOSTICS" != "x" ]; then
    echo "-XX:NativeMemoryTracking=summary -XX:+PrintGC -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -XX:+UnlockDiagnosticVMOptions"
  fi
}

cpu_core_tunning() {
  local core_limit="${JAVA_CORE_LIMIT}"
  if [ "x$core_limit" = "x0" ]; then
    return
  fi

  if [ "x$CONTAINER_CORE_LIMIT" != x ]; then
    if [ "x$core_limit" = x ]; then
      core_limit="${CONTAINER_CORE_LIMIT}"
    fi
    echo "-XX:ParallelGCThreads=${core_limit} " \
         "-XX:ConcGCThreads=${core_limit} " \
         "-Djava.util.concurrent.ForkJoinPool.common.parallelism=${core_limit}"
  fi
}

# Echo options, trimming trailing and multiple spaces
echo "$(max_memory) $(diagnostics) $(cpu_core_tunning)" | awk '$1=$1'

debug-options:

#!/bin/sh

# Check for debug options and echo them if enabled. Meant to be included by
# a run script.

debug_options() {
  if [ "x${JAVA_ENABLE_DEBUG}" != "x" -o "x${JAVA_DEBUG_ENABLE}" != "x" -o "x${JAVA_DEBUG}" != "x" ]; then
    local debug_port=${JAVA_DEBUG_PORT:-5005}
    echo "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=${debug_port}"
  fi
}

## Echo options, trimming trailing and multiple spaces
echo "$(debug_options)" | awk '$1=$1'

container-limits:

#!/bin/sh

# Detected container limits
# If found these are exposed as the following environment variables:
#
# - CONTAINER_MAX_MEMORY
# - CONTAINER_CORE_LIMIT
#
# This script is meant to be sourced.

ceiling() {
  awk -vnumber="$1" -vdiv="$2" '
    function ceiling(x){
      return x%1 ? int(x)+1 : x
    }
    BEGIN{
      print ceiling(number/div)
    }
  '
}

# Based on the cgroup limits, figure out the max number of core we should utilize
core_limit() {
  local cpu_period_file="/sys/fs/cgroup/cpu/cpu.cfs_period_us"
  local cpu_quota_file="/sys/fs/cgroup/cpu/cpu.cfs_quota_us"
  if [ -r "${cpu_period_file}" ]; then
    local cpu_period="$(cat ${cpu_period_file})"

    if [ -r "${cpu_quota_file}" ]; then
      local cpu_quota="$(cat ${cpu_quota_file})"
      # cfs_quota_us == -1 --> no restrictions
      if [ "x$cpu_quota" != "x-1" ]; then
        ceiling "$cpu_quota" "$cpu_period"
      fi
    fi
  fi
}

max_memory() {
  # High number which is the max limit unti which memory is supposed to be
  # unbounded. 512 TB for now.
  local max_mem_unbounded="562949953421312"
  local mem_file="/sys/fs/cgroup/memory/memory.limit_in_bytes"
  if [ -r "${mem_file}" ]; then
    local max_mem="$(cat ${mem_file})"
    if [ ${max_mem} -lt ${max_mem_unbounded} ]; then
      echo "${max_mem}"
    fi
  fi
}

limit="$(core_limit)"
if [ x$limit != x ]; then
   export CONTAINER_CORE_LIMIT="${limit}"
fi
unset limit

limit="$(max_memory)"
if [ x$limit != x ]; then
  export CONTAINER_MAX_MEMORY="$limit"
fi
unset limit

猜你喜欢

转载自rickgong.iteye.com/blog/2367197