因为没有直接使用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
版权声明:本文为tiancen2001原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。