221 lines
5.9 KiB
Bash
Executable File
221 lines
5.9 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
repo_root="$(cd "${script_dir}/.." && pwd)"
|
|
|
|
target_dir="${repo_root}/qortal/data"
|
|
target_file=""
|
|
legacy_default_args='-XX:MaxRAMPercentage=25 -XX:+UseG1GC -Xss1024k'
|
|
legacy_autosized_args='-XX:MaxRAMPercentage=66 -XX:+UseG1GC -Xss1024k'
|
|
gib_bytes=$((1024 * 1024 * 1024))
|
|
env_file=""
|
|
seed_args="${QORTAL_JVM_MEMORY_ARGS:-}"
|
|
managed_state_file=""
|
|
|
|
resolve_path() {
|
|
local raw="${1:-}"
|
|
if [[ -z "${raw}" ]]; then
|
|
printf '%s' ""
|
|
return 0
|
|
fi
|
|
if [[ "${raw}" == /* ]]; then
|
|
printf '%s' "${raw}"
|
|
return 0
|
|
fi
|
|
printf '%s' "${repo_root}/${raw}"
|
|
}
|
|
|
|
ensure_qortal_data_permissions() {
|
|
local data_dir="${1:-}"
|
|
if [[ "${EUID:-$(id -u)}" -ne 0 ]]; then
|
|
return 0
|
|
fi
|
|
if [[ -z "${data_dir}" || ! -d "${data_dir}" ]]; then
|
|
return 0
|
|
fi
|
|
|
|
chown -R 1000:100 "${data_dir}" >/dev/null 2>&1 || true
|
|
chmod -R u+rwX,g+rwX "${data_dir}" >/dev/null 2>&1 || true
|
|
}
|
|
|
|
read_host_memory_bytes() {
|
|
if [[ -r /proc/meminfo ]]; then
|
|
awk '/^MemTotal:/ { print $2 * 1024; exit }' /proc/meminfo 2>/dev/null || true
|
|
fi
|
|
}
|
|
|
|
read_cgroup_memory_bytes() {
|
|
local cgroup_file=""
|
|
local value=""
|
|
|
|
for cgroup_file in /sys/fs/cgroup/memory.max /sys/fs/cgroup/memory/memory.limit_in_bytes; do
|
|
[[ -r "${cgroup_file}" ]] || continue
|
|
value="$(tr -d '\r\n' < "${cgroup_file}" 2>/dev/null || true)"
|
|
case "${value}" in
|
|
""|"max")
|
|
continue
|
|
;;
|
|
esac
|
|
if [[ "${value}" =~ ^[0-9]+$ ]] && [[ "${value}" -gt 0 ]]; then
|
|
printf '%s' "${value}"
|
|
return 0
|
|
fi
|
|
done
|
|
|
|
return 1
|
|
}
|
|
|
|
resolve_available_memory_bytes() {
|
|
local host_bytes=""
|
|
local cgroup_bytes=""
|
|
|
|
host_bytes="$(read_host_memory_bytes)"
|
|
cgroup_bytes="$(read_cgroup_memory_bytes || true)"
|
|
|
|
if [[ -n "${host_bytes}" && "${host_bytes}" -gt 0 ]]; then
|
|
if [[ -n "${cgroup_bytes}" && "${cgroup_bytes}" -gt 0 && "${cgroup_bytes}" -lt "${host_bytes}" ]]; then
|
|
printf '%s' "${cgroup_bytes}"
|
|
return 0
|
|
fi
|
|
printf '%s' "${host_bytes}"
|
|
return 0
|
|
fi
|
|
|
|
if [[ -n "${cgroup_bytes}" && "${cgroup_bytes}" -gt 0 ]]; then
|
|
printf '%s' "${cgroup_bytes}"
|
|
return 0
|
|
fi
|
|
|
|
return 1
|
|
}
|
|
|
|
compute_auto_qortal_args() {
|
|
local total_bytes=""
|
|
local target_bytes=""
|
|
local percentage=""
|
|
|
|
total_bytes="$(resolve_available_memory_bytes || true)"
|
|
if [[ -z "${total_bytes}" || "${total_bytes}" -le 0 ]]; then
|
|
printf '%s' "${legacy_autosized_args}"
|
|
return 0
|
|
fi
|
|
|
|
target_bytes=$(( total_bytes * 66 / 100 ))
|
|
if [[ "${total_bytes}" -ge $((6 * gib_bytes)) ]]; then
|
|
if [[ "${target_bytes}" -lt $((4 * gib_bytes)) ]]; then
|
|
target_bytes=$((4 * gib_bytes))
|
|
fi
|
|
if [[ "${target_bytes}" -gt $((8 * gib_bytes)) ]]; then
|
|
target_bytes=$((8 * gib_bytes))
|
|
fi
|
|
fi
|
|
|
|
percentage="$(awk -v target="${target_bytes}" -v total="${total_bytes}" 'BEGIN { if (total <= 0) { print "66"; exit } printf "%.2f", (target / total) * 100 }')"
|
|
printf '%s' "-XX:MaxRAMPercentage=${percentage} -XX:+UseG1GC -Xss1024k"
|
|
}
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
--target-dir)
|
|
target_dir="${2:-}"
|
|
shift 2
|
|
;;
|
|
--target-dir=*)
|
|
target_dir="${1#*=}"
|
|
shift
|
|
;;
|
|
--target-file)
|
|
target_file="${2:-}"
|
|
shift 2
|
|
;;
|
|
--target-file=*)
|
|
target_file="${1#*=}"
|
|
shift
|
|
;;
|
|
-h|--help)
|
|
cat <<USAGE
|
|
Usage: ./scripts/ensure-qortal-start-args.sh [options] [env-file]
|
|
|
|
Initialize a Qortal node start-arguments.txt file.
|
|
|
|
Options:
|
|
--target-dir <path> Start args directory (default: ${repo_root}/qortal/data)
|
|
--target-file <path> Start args file path override
|
|
env-file Optional env file whose QORTAL_JVM_MEMORY_ARGS value overrides auto-sizing
|
|
-h, --help Show this help
|
|
USAGE
|
|
exit 0
|
|
;;
|
|
*)
|
|
if [[ -z "${env_file}" ]]; then
|
|
env_file="${1}"
|
|
shift
|
|
else
|
|
echo "Unknown argument: $1" >&2
|
|
exit 1
|
|
fi
|
|
;;
|
|
esac
|
|
done
|
|
|
|
target_dir="$(resolve_path "${target_dir}")"
|
|
if [[ -z "${target_file}" ]]; then
|
|
target_file="${target_dir%/}/start-arguments.txt"
|
|
else
|
|
target_file="$(resolve_path "${target_file}")"
|
|
target_dir="$(dirname "${target_file}")"
|
|
fi
|
|
managed_state_file="${target_file}.mode"
|
|
|
|
if [[ -n "${env_file}" && -f "${env_file}" ]]; then
|
|
if [[ "${env_file}" != /* ]]; then
|
|
env_file="$(resolve_path "${env_file}")"
|
|
fi
|
|
value_from_env_file="$(grep -E '^QORTAL_JVM_MEMORY_ARGS=' "${env_file}" | tail -n1 | cut -d= -f2- || true)"
|
|
if [[ -n "${value_from_env_file}" ]]; then
|
|
seed_args="${value_from_env_file}"
|
|
fi
|
|
fi
|
|
|
|
mkdir -p "${target_dir}"
|
|
ensure_qortal_data_permissions "${target_dir}"
|
|
|
|
auto_args="$(compute_auto_qortal_args)"
|
|
existing_args=""
|
|
existing_mode=""
|
|
|
|
if [[ -f "${target_file}" && -s "${target_file}" ]]; then
|
|
existing_args="$(tr -d '\r' < "${target_file}" | sed 's/[[:space:]]*$//')"
|
|
fi
|
|
if [[ -f "${managed_state_file}" && -s "${managed_state_file}" ]]; then
|
|
existing_mode="$(tr -d '\r' < "${managed_state_file}" | sed 's/[[:space:]]*$//')"
|
|
fi
|
|
|
|
if [[ -n "${seed_args}" ]]; then
|
|
printf '%s\n' "${seed_args}" > "${target_file}"
|
|
printf '%s\n' "manual" > "${managed_state_file}"
|
|
if [[ "${existing_args}" == "${seed_args}" ]]; then
|
|
echo "Using Qortal JVM start args from env: ${target_file}"
|
|
else
|
|
echo "Updated Qortal JVM start args from env: ${target_file}"
|
|
fi
|
|
exit 0
|
|
fi
|
|
|
|
if [[ -f "${target_file}" && -s "${target_file}" ]]; then
|
|
if [[ "${existing_mode}" == "auto" || "${existing_args}" == "${legacy_default_args}" || "${existing_args}" == "${legacy_autosized_args}" ]]; then
|
|
printf '%s\n' "${auto_args}" > "${target_file}"
|
|
printf '%s\n' "auto" > "${managed_state_file}"
|
|
echo "Updated auto-sized Qortal JVM start args: ${target_file}"
|
|
exit 0
|
|
fi
|
|
|
|
echo "Using existing Qortal JVM start args: ${target_file}"
|
|
exit 0
|
|
fi
|
|
|
|
printf '%s\n' "${auto_args}" > "${target_file}"
|
|
printf '%s\n' "auto" > "${managed_state_file}"
|
|
echo "Initialized auto-sized Qortal JVM start args: ${target_file}"
|