feat:CISD初始化
This commit is contained in:
Executable
+144
@@ -0,0 +1,144 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# CISD init flow runner:
|
||||
# status -> preview -> create task -> execute -> query steps -> failed step log
|
||||
#
|
||||
# Usage:
|
||||
# chmod +x scripts/cisd_init_flow.sh
|
||||
# REQUEST_JSON=/tmp/cisd-init-standard-rabbit.json ./scripts/cisd_init_flow.sh
|
||||
#
|
||||
# Optional env:
|
||||
# BASE_URL=http://127.0.0.1:8080
|
||||
# INTERNAL_TOKEN=change-me-internal-token
|
||||
# OUT_DIR=/tmp/cisd-init-run
|
||||
# FETCH_FAILED_STEP_LOG=true
|
||||
|
||||
BASE_URL="${BASE_URL:-http://127.0.0.1:8080}"
|
||||
INTERNAL_TOKEN="${INTERNAL_TOKEN:-change-me-internal-token}"
|
||||
REQUEST_JSON="${REQUEST_JSON:-}"
|
||||
OUT_DIR="${OUT_DIR:-/tmp/cisd-init-run}"
|
||||
FETCH_FAILED_STEP_LOG="${FETCH_FAILED_STEP_LOG:-true}"
|
||||
TIMEOUT_SECONDS="${TIMEOUT_SECONDS:-30}"
|
||||
|
||||
TS="$(date +%Y%m%d%H%M%S)"
|
||||
RUN_DIR="${OUT_DIR}/run-${TS}"
|
||||
|
||||
require_cmd() {
|
||||
local cmd="$1"
|
||||
if ! command -v "$cmd" >/dev/null 2>&1; then
|
||||
echo "[FATAL] command missing: ${cmd}"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
api_get() {
|
||||
local path="$1"
|
||||
curl -sS --max-time "${TIMEOUT_SECONDS}" \
|
||||
-H "X-Internal-Token: ${INTERNAL_TOKEN}" \
|
||||
"${BASE_URL}${path}"
|
||||
}
|
||||
|
||||
api_post_json() {
|
||||
local path="$1"
|
||||
local body_file="$2"
|
||||
curl -sS --max-time "${TIMEOUT_SECONDS}" \
|
||||
-H "X-Internal-Token: ${INTERNAL_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
-X POST "${BASE_URL}${path}" \
|
||||
-d @"${body_file}"
|
||||
}
|
||||
|
||||
api_post_empty() {
|
||||
local path="$1"
|
||||
curl -sS --max-time "${TIMEOUT_SECONDS}" \
|
||||
-H "X-Internal-Token: ${INTERNAL_TOKEN}" \
|
||||
-X POST "${BASE_URL}${path}"
|
||||
}
|
||||
|
||||
expect_success() {
|
||||
local label="$1"
|
||||
local file="$2"
|
||||
if jq -e '.success == true and .code == 200' "${file}" >/dev/null 2>&1; then
|
||||
echo "[PASS] ${label}"
|
||||
else
|
||||
echo "[FAIL] ${label}"
|
||||
cat "${file}"
|
||||
exit 2
|
||||
fi
|
||||
}
|
||||
|
||||
main() {
|
||||
require_cmd curl
|
||||
require_cmd jq
|
||||
|
||||
if [[ -z "${REQUEST_JSON}" ]]; then
|
||||
echo "[FATAL] REQUEST_JSON is required"
|
||||
echo "Example: REQUEST_JSON=/tmp/cisd-init-standard-rabbit.json ./scripts/cisd_init_flow.sh"
|
||||
exit 1
|
||||
fi
|
||||
if [[ ! -f "${REQUEST_JSON}" ]]; then
|
||||
echo "[FATAL] request file not found: ${REQUEST_JSON}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir -p "${RUN_DIR}"
|
||||
echo "[INFO] run dir: ${RUN_DIR}"
|
||||
echo "[INFO] base url: ${BASE_URL}"
|
||||
|
||||
echo "[STEP] device status"
|
||||
api_get "/api/v1/device/status" | tee "${RUN_DIR}/01-device-status.json" >/dev/null
|
||||
expect_success "device status" "${RUN_DIR}/01-device-status.json"
|
||||
jq '.data | {presetProductType,presetVersion,presetSource}' "${RUN_DIR}/01-device-status.json" || true
|
||||
|
||||
echo "[STEP] init preview"
|
||||
api_post_json "/api/v1/init/preview" "${REQUEST_JSON}" | tee "${RUN_DIR}/02-preview.json" >/dev/null
|
||||
expect_success "init preview" "${RUN_DIR}/02-preview.json"
|
||||
jq '.data | {resolvedProductType,presetVersion,stepCount,summary}' "${RUN_DIR}/02-preview.json" || true
|
||||
|
||||
echo "[STEP] create init task"
|
||||
api_post_json "/api/v1/init/tasks" "${REQUEST_JSON}" | tee "${RUN_DIR}/03-create-task.json" >/dev/null
|
||||
expect_success "create task" "${RUN_DIR}/03-create-task.json"
|
||||
TASK_ID="$(jq -r '.data.taskId // empty' "${RUN_DIR}/03-create-task.json")"
|
||||
if [[ -z "${TASK_ID}" ]]; then
|
||||
echo "[FATAL] taskId missing in create task response"
|
||||
cat "${RUN_DIR}/03-create-task.json"
|
||||
exit 2
|
||||
fi
|
||||
echo "[INFO] task id: ${TASK_ID}"
|
||||
|
||||
echo "[STEP] execute init task"
|
||||
api_post_empty "/api/v1/init/tasks/${TASK_ID}/execute" | tee "${RUN_DIR}/04-execute-task.json" >/dev/null
|
||||
expect_success "execute task api call" "${RUN_DIR}/04-execute-task.json"
|
||||
TASK_STATUS="$(jq -r '.data.status // empty' "${RUN_DIR}/04-execute-task.json")"
|
||||
echo "[INFO] task status: ${TASK_STATUS}"
|
||||
|
||||
echo "[STEP] query task steps"
|
||||
api_get "/api/v1/init/tasks/${TASK_ID}/steps" | tee "${RUN_DIR}/05-task-steps.json" >/dev/null
|
||||
expect_success "query task steps" "${RUN_DIR}/05-task-steps.json"
|
||||
jq -r '.data[] | "\(.stepNo)\t\(.stepCode)\t\(.status)\t\(.message // "")"' "${RUN_DIR}/05-task-steps.json" || true
|
||||
|
||||
if [[ "${FETCH_FAILED_STEP_LOG,,}" == "true" ]]; then
|
||||
FAILED_STEP_NO="$(jq -r '.data[] | select(.status=="FAILED") | .stepNo' "${RUN_DIR}/05-task-steps.json" | head -n1 || true)"
|
||||
if [[ -n "${FAILED_STEP_NO}" ]]; then
|
||||
echo "[STEP] fetch failed step log: stepNo=${FAILED_STEP_NO}"
|
||||
api_get "/api/v1/init/tasks/${TASK_ID}/steps/${FAILED_STEP_NO}/log" | tee "${RUN_DIR}/06-failed-step-log.json" >/dev/null || true
|
||||
if jq -e '.success == true and .code == 200' "${RUN_DIR}/06-failed-step-log.json" >/dev/null 2>&1; then
|
||||
jq -r '.data.content' "${RUN_DIR}/06-failed-step-log.json" > "${RUN_DIR}/06-failed-step.log.txt" || true
|
||||
echo "[INFO] failed step log saved: ${RUN_DIR}/06-failed-step.log.txt"
|
||||
else
|
||||
echo "[WARN] failed step log API did not return success"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ "${TASK_STATUS}" == "SUCCESS" ]]; then
|
||||
echo "[DONE] init flow completed successfully, taskId=${TASK_ID}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "[DONE] init flow completed with non-success status=${TASK_STATUS}, taskId=${TASK_ID}"
|
||||
exit 3
|
||||
}
|
||||
|
||||
main "$@"
|
||||
Executable
+173
@@ -0,0 +1,173 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# CISD init on-host precheck.
|
||||
# Usage:
|
||||
# chmod +x scripts/cisd_init_precheck.sh
|
||||
# ./scripts/cisd_init_precheck.sh
|
||||
# Optional:
|
||||
# PRODUCT_TYPE=ENTERPRISE ./scripts/cisd_init_precheck.sh
|
||||
|
||||
PRODUCT_TYPE="${PRODUCT_TYPE:-${TMS_CISD_PRESET_PRODUCT_TYPE:-UNKNOWN}}"
|
||||
MODE="${TMS_INIT_EXECUTOR_MODE:-SIMULATE}"
|
||||
LOG_DIR="${TMS_INIT_EXECUTOR_LOG_DIR:-/tmp/tms-init-logs}"
|
||||
STANDARD_CPCONFIG_PATH="${TMS_INIT_EXECUTOR_STANDARD_CPCONFIG_PATH:-/home/cmep4i/cpconfig.cfg}"
|
||||
DIRECT_DB_SCRIPT_DIR="${TMS_INIT_EXECUTOR_DIRECT_DB_SCRIPT_DIR:-/opt/CAE_Install_Base_Resource/DB}"
|
||||
DIRECT_TLQ_INIT_CFG_DIR="${TMS_INIT_EXECUTOR_DIRECT_TLQ_INIT_CFG_DIR:-/opt/CAE_Install_App_Resource/CAE}"
|
||||
APP_PATTERN_1="${TMS_INIT_EXECUTOR_STANDARD_RABBIT_APP_CONFIG_PATTERN_1:-/home/cmep4i/cmsp/application-prd*.properties}"
|
||||
APP_PATTERN_2="${TMS_INIT_EXECUTOR_STANDARD_RABBIT_APP_CONFIG_PATTERN_2:-/home/cmep4i/cmtp/application-prd*.properties}"
|
||||
RABBIT_CRED_ENCRYPT_ENABLED="${TMS_INIT_EXECUTOR_STANDARD_RABBIT_CREDENTIAL_ENCRYPT_ENABLED:-true}"
|
||||
RABBIT_CRED_SECRET_KEY="${TMS_INIT_EXECUTOR_STANDARD_RABBIT_CREDENTIAL_SECRET_KEY:-ABCDEFGHIJKLMN1234567890}"
|
||||
|
||||
pass_count=0
|
||||
warn_count=0
|
||||
fail_count=0
|
||||
|
||||
pass() {
|
||||
echo "[PASS] $1"
|
||||
pass_count=$((pass_count + 1))
|
||||
}
|
||||
|
||||
warn() {
|
||||
echo "[WARN] $1"
|
||||
warn_count=$((warn_count + 1))
|
||||
}
|
||||
|
||||
fail() {
|
||||
echo "[FAIL] $1"
|
||||
fail_count=$((fail_count + 1))
|
||||
}
|
||||
|
||||
check_cmd() {
|
||||
local cmd="$1"
|
||||
if command -v "$cmd" >/dev/null 2>&1; then
|
||||
pass "command exists: ${cmd}"
|
||||
else
|
||||
fail "command missing: ${cmd}"
|
||||
fi
|
||||
}
|
||||
|
||||
check_file() {
|
||||
local file="$1"
|
||||
if [[ -f "$file" ]]; then
|
||||
pass "file exists: ${file}"
|
||||
else
|
||||
fail "file missing: ${file}"
|
||||
fi
|
||||
}
|
||||
|
||||
check_dir() {
|
||||
local dir="$1"
|
||||
if [[ -d "$dir" ]]; then
|
||||
pass "directory exists: ${dir}"
|
||||
else
|
||||
fail "directory missing: ${dir}"
|
||||
fi
|
||||
}
|
||||
|
||||
check_writable_dir() {
|
||||
local dir="$1"
|
||||
mkdir -p "$dir" 2>/dev/null || true
|
||||
if [[ -d "$dir" && -w "$dir" ]]; then
|
||||
pass "directory writable: ${dir}"
|
||||
else
|
||||
fail "directory not writable: ${dir}"
|
||||
fi
|
||||
}
|
||||
|
||||
check_pattern_match() {
|
||||
local pattern="$1"
|
||||
shopt -s nullglob
|
||||
local matches=($pattern)
|
||||
shopt -u nullglob
|
||||
if (( ${#matches[@]} > 0 )); then
|
||||
pass "pattern matched (${#matches[@]}): ${pattern}"
|
||||
else
|
||||
fail "pattern has no match: ${pattern}"
|
||||
fi
|
||||
}
|
||||
|
||||
check_product_type() {
|
||||
case "$PRODUCT_TYPE" in
|
||||
ENTERPRISE|INDIRECT|DIRECT)
|
||||
pass "product type recognized: ${PRODUCT_TYPE}"
|
||||
;;
|
||||
*)
|
||||
fail "product type invalid: ${PRODUCT_TYPE} (expected ENTERPRISE/INDIRECT/DIRECT)"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
check_mode() {
|
||||
if [[ "$MODE" == "LOCAL" ]]; then
|
||||
pass "executor mode is LOCAL"
|
||||
else
|
||||
warn "executor mode is ${MODE}; on-host initialization should use LOCAL"
|
||||
fi
|
||||
}
|
||||
|
||||
check_encryption_config() {
|
||||
local enabled_lower
|
||||
enabled_lower="$(echo "$RABBIT_CRED_ENCRYPT_ENABLED" | tr '[:upper:]' '[:lower:]')"
|
||||
if [[ "$enabled_lower" == "true" ]]; then
|
||||
pass "rabbit app credential encryption is enabled"
|
||||
if [[ -n "$RABBIT_CRED_SECRET_KEY" ]]; then
|
||||
if [[ ${#RABBIT_CRED_SECRET_KEY} -eq 24 ]]; then
|
||||
pass "rabbit credential secret key length is 24 (DESede)"
|
||||
else
|
||||
warn "rabbit credential secret key length is ${#RABBIT_CRED_SECRET_KEY}, expected 24"
|
||||
fi
|
||||
else
|
||||
fail "rabbit credential secret key is empty"
|
||||
fi
|
||||
else
|
||||
warn "rabbit app credential encryption disabled"
|
||||
fi
|
||||
}
|
||||
|
||||
check_standard_assets() {
|
||||
check_file "$STANDARD_CPCONFIG_PATH"
|
||||
check_file "/home/cmep4i/cpackage/toolsh/setfraq.sh"
|
||||
check_file "/home/cmep4i/cpackage/toolsh/setftq.sh"
|
||||
check_file "/home/cmep4i/cpackage/toolsh/setsql.sh"
|
||||
check_file "/home/cmep4i/cpackage/toolsh/setsptp.sh"
|
||||
check_pattern_match "$APP_PATTERN_1"
|
||||
check_pattern_match "$APP_PATTERN_2"
|
||||
check_cmd "rabbitmqctl"
|
||||
check_cmd "rabbitmqadmin"
|
||||
}
|
||||
|
||||
check_direct_assets() {
|
||||
check_file "$STANDARD_CPCONFIG_PATH"
|
||||
check_dir "$DIRECT_DB_SCRIPT_DIR"
|
||||
check_file "$DIRECT_DB_SCRIPT_DIR/setsql.sh"
|
||||
check_dir "$DIRECT_TLQ_INIT_CFG_DIR"
|
||||
check_file "$DIRECT_TLQ_INIT_CFG_DIR/init_cfg.sh"
|
||||
check_cmd "java"
|
||||
check_cmd "rabbitmqctl"
|
||||
}
|
||||
|
||||
main() {
|
||||
echo "[INFO] CISD init precheck started"
|
||||
echo "[INFO] PRODUCT_TYPE=${PRODUCT_TYPE}"
|
||||
echo "[INFO] MODE=${MODE}"
|
||||
echo "[INFO] LOG_DIR=${LOG_DIR}"
|
||||
|
||||
check_product_type
|
||||
check_mode
|
||||
check_writable_dir "$LOG_DIR"
|
||||
check_encryption_config
|
||||
|
||||
if [[ "$PRODUCT_TYPE" == "DIRECT" ]]; then
|
||||
check_direct_assets
|
||||
else
|
||||
check_standard_assets
|
||||
fi
|
||||
|
||||
echo "[INFO] precheck summary: pass=${pass_count}, warn=${warn_count}, fail=${fail_count}"
|
||||
if (( fail_count > 0 )); then
|
||||
exit 2
|
||||
fi
|
||||
}
|
||||
|
||||
main "$@"
|
||||
Executable
+118
@@ -0,0 +1,118 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# PCIe real-card smoke test template for internal crypto APIs.
|
||||
# Fill env vars below, then run:
|
||||
# chmod +x scripts/pcie_realcard_smoke.sh
|
||||
# ./scripts/pcie_realcard_smoke.sh
|
||||
|
||||
BASE_URL="${BASE_URL:-http://127.0.0.1:8080}"
|
||||
INTERNAL_TOKEN="${INTERNAL_TOKEN:-change-me-internal-token}"
|
||||
TIMEOUT_SECONDS="${TIMEOUT_SECONDS:-15}"
|
||||
|
||||
# Common algorithm IDs (GM/T 0018 style)
|
||||
ALG_SM3="${ALG_SM3:-1}" # digest/hmac
|
||||
ALG_SM4_ECB="${ALG_SM4_ECB:-1025}" # 0x00000401, symmetric encrypt/decrypt
|
||||
|
||||
# Test payloads
|
||||
PLAINTEXT_B64="${PLAINTEXT_B64:-dG1zLXBjaWUtc21va2U=}" # "tms-pcie-smoke"
|
||||
KEY_16_B64="${KEY_16_B64:-MDEyMzQ1Njc4OWFiY2RlZg==}" # "0123456789abcdef"
|
||||
IV_B64="${IV_B64:-}" # ECB can keep empty
|
||||
|
||||
pass_count=0
|
||||
fail_count=0
|
||||
|
||||
require_cmd() {
|
||||
local cmd="$1"
|
||||
if ! command -v "$cmd" >/dev/null 2>&1; then
|
||||
echo "[FATAL] command not found: $cmd"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
api_get() {
|
||||
local path="$1"
|
||||
curl -sS --max-time "${TIMEOUT_SECONDS}" \
|
||||
-H "X-Internal-Token: ${INTERNAL_TOKEN}" \
|
||||
"${BASE_URL}${path}"
|
||||
}
|
||||
|
||||
api_post() {
|
||||
local path="$1"
|
||||
local body="$2"
|
||||
curl -sS --max-time "${TIMEOUT_SECONDS}" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "X-Internal-Token: ${INTERNAL_TOKEN}" \
|
||||
-X POST \
|
||||
"${BASE_URL}${path}" \
|
||||
-d "${body}"
|
||||
}
|
||||
|
||||
assert_success() {
|
||||
local name="$1"
|
||||
local resp="$2"
|
||||
if echo "${resp}" | jq -e '.success == true and .code == 200' >/dev/null 2>&1; then
|
||||
echo "[PASS] ${name}"
|
||||
pass_count=$((pass_count + 1))
|
||||
else
|
||||
echo "[FAIL] ${name}"
|
||||
echo " response: ${resp}"
|
||||
fail_count=$((fail_count + 1))
|
||||
fi
|
||||
}
|
||||
|
||||
run_case_get() {
|
||||
local name="$1"
|
||||
local path="$2"
|
||||
local resp
|
||||
resp="$(api_get "${path}")"
|
||||
assert_success "${name}" "${resp}"
|
||||
}
|
||||
|
||||
run_case_post() {
|
||||
local name="$1"
|
||||
local path="$2"
|
||||
local body="$3"
|
||||
local resp
|
||||
resp="$(api_post "${path}" "${body}")"
|
||||
assert_success "${name}" "${resp}"
|
||||
}
|
||||
|
||||
main() {
|
||||
require_cmd curl
|
||||
require_cmd jq
|
||||
|
||||
echo "[INFO] BASE_URL=${BASE_URL}"
|
||||
echo "[INFO] starting smoke tests..."
|
||||
|
||||
run_case_get "device-count" "/api/v1/device/crypto/device-count"
|
||||
run_case_get "device-info" "/api/v1/device/crypto/device-info"
|
||||
run_case_post "self-test" "/api/v1/device/crypto/self-test" "{}"
|
||||
run_case_get "random-16" "/api/v1/device/crypto/random?length=16"
|
||||
|
||||
run_case_post "digest-sm3" "/api/v1/device/crypto/digest" "$(cat <<JSON
|
||||
{"algId":${ALG_SM3},"dataBase64":"${PLAINTEXT_B64}","outBufferSize":64}
|
||||
JSON
|
||||
)"
|
||||
|
||||
run_case_post "hmac-sm3" "/api/v1/device/crypto/hmac" "$(cat <<JSON
|
||||
{"algId":${ALG_SM3},"keyBase64":"${KEY_16_B64}","dataBase64":"${PLAINTEXT_B64}"}
|
||||
JSON
|
||||
)"
|
||||
|
||||
run_case_post "encrypt-plain-sm4" "/api/v1/device/crypto/encrypt/plain" "$(cat <<JSON
|
||||
{"algId":${ALG_SM4_ECB},"keyBase64":"${KEY_16_B64}","ivBase64":"${IV_B64}","dataBase64":"${PLAINTEXT_B64}","outBufferSize":256}
|
||||
JSON
|
||||
)"
|
||||
|
||||
run_case_post "kek-generate-128" "/api/v1/device/crypto/kek/generate" '{"keyBits":128,"keyIndex":1}'
|
||||
run_case_get "kek-status-1" "/api/v1/device/crypto/kek/status?keyIndex=1"
|
||||
run_case_get "lmk-seed-mac" "/api/v1/device/crypto/lmk/seed-mac"
|
||||
|
||||
echo "[INFO] smoke tests completed: pass=${pass_count}, fail=${fail_count}"
|
||||
if [ "${fail_count}" -gt 0 ]; then
|
||||
exit 2
|
||||
fi
|
||||
}
|
||||
|
||||
main "$@"
|
||||
Executable
+189
@@ -0,0 +1,189 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# TMS runtime script for jar deployment.
|
||||
# Commands:
|
||||
# ./scripts/tms.sh start
|
||||
# ./scripts/tms.sh stop
|
||||
# ./scripts/tms.sh restart
|
||||
# ./scripts/tms.sh status
|
||||
#
|
||||
# External config:
|
||||
# ${APP_HOME}/config/application.yml
|
||||
# ${APP_HOME}/config/application-${SPRING_PROFILES_ACTIVE}.yml
|
||||
|
||||
DEFAULT_APP_HOME="/home/tms"
|
||||
APP_HOME="${APP_HOME:-${DEFAULT_APP_HOME}}"
|
||||
APP_NAME="${APP_NAME:-tms-framework}"
|
||||
RUN_DIR="${RUN_DIR:-${APP_HOME}/run}"
|
||||
LOG_DIR="${LOG_DIR:-${APP_HOME}/logs}"
|
||||
CONF_DIR="${CONF_DIR:-${APP_HOME}/config}"
|
||||
PID_FILE="${PID_FILE:-${RUN_DIR}/${APP_NAME}.pid}"
|
||||
OUT_LOG="${OUT_LOG:-${LOG_DIR}/${APP_NAME}.out.log}"
|
||||
ERR_LOG="${ERR_LOG:-${LOG_DIR}/${APP_NAME}.err.log}"
|
||||
|
||||
SPRING_PROFILES_ACTIVE="${SPRING_PROFILES_ACTIVE:-prod}"
|
||||
JAVA_BIN="${JAVA_BIN:-java}"
|
||||
JAVA_OPTS="${JAVA_OPTS:- -Xms512m -Xmx1024m}"
|
||||
ALLOW_MISSING_EXTERNAL_CONFIG="${ALLOW_MISSING_EXTERNAL_CONFIG:-false}"
|
||||
|
||||
JAR_PATH="${JAR_PATH:-${APP_HOME}/${APP_NAME}.jar}"
|
||||
|
||||
ensure_dirs() {
|
||||
mkdir -p "${RUN_DIR}" "${LOG_DIR}" "${CONF_DIR}"
|
||||
}
|
||||
|
||||
resolve_jar_path() {
|
||||
if [[ -f "${JAR_PATH}" ]]; then
|
||||
return 0
|
||||
fi
|
||||
local found
|
||||
found="$(ls -1 "${APP_HOME}/target/${APP_NAME}"-*.jar 2>/dev/null | grep -vE '(sources|javadoc|original)' | head -n1 || true)"
|
||||
if [[ -n "${found}" ]]; then
|
||||
JAR_PATH="${found}"
|
||||
return 0
|
||||
fi
|
||||
echo "[FATAL] jar not found. set JAR_PATH or place jar at ${APP_HOME}/${APP_NAME}.jar"
|
||||
exit 1
|
||||
}
|
||||
|
||||
check_external_config() {
|
||||
local base_cfg="${CONF_DIR}/application.yml"
|
||||
if [[ "${ALLOW_MISSING_EXTERNAL_CONFIG}" != "true" && ! -f "${base_cfg}" ]]; then
|
||||
echo "[FATAL] external config missing: ${base_cfg}"
|
||||
echo "Copy template: cp ${APP_HOME}/config/application.yml.example ${base_cfg}"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
is_running() {
|
||||
if [[ ! -f "${PID_FILE}" ]]; then
|
||||
return 1
|
||||
fi
|
||||
local pid
|
||||
pid="$(cat "${PID_FILE}")"
|
||||
if [[ -z "${pid}" ]]; then
|
||||
return 1
|
||||
fi
|
||||
if kill -0 "${pid}" >/dev/null 2>&1; then
|
||||
return 0
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
start_app() {
|
||||
ensure_dirs
|
||||
resolve_jar_path
|
||||
check_external_config
|
||||
|
||||
if is_running; then
|
||||
echo "[INFO] ${APP_NAME} already running, pid=$(cat "${PID_FILE}")"
|
||||
return 0
|
||||
fi
|
||||
|
||||
local cfg_location
|
||||
cfg_location="optional:file:${CONF_DIR}/"
|
||||
|
||||
echo "[INFO] starting ${APP_NAME}"
|
||||
echo "[INFO] app home: ${APP_HOME}"
|
||||
echo "[INFO] jar path: ${JAR_PATH}"
|
||||
echo "[INFO] profile: ${SPRING_PROFILES_ACTIVE}"
|
||||
echo "[INFO] external config dir: ${CONF_DIR}"
|
||||
|
||||
# shellcheck disable=SC2086
|
||||
nohup "${JAVA_BIN}" ${JAVA_OPTS} \
|
||||
-jar "${JAR_PATH}" \
|
||||
--spring.profiles.active="${SPRING_PROFILES_ACTIVE}" \
|
||||
--spring.config.additional-location="${cfg_location}" \
|
||||
>"${OUT_LOG}" 2>"${ERR_LOG}" &
|
||||
|
||||
local pid="$!"
|
||||
echo "${pid}" > "${PID_FILE}"
|
||||
sleep 1
|
||||
|
||||
if kill -0 "${pid}" >/dev/null 2>&1; then
|
||||
echo "[INFO] started, pid=${pid}"
|
||||
echo "[INFO] out log: ${OUT_LOG}"
|
||||
echo "[INFO] err log: ${ERR_LOG}"
|
||||
else
|
||||
echo "[ERROR] start failed, check logs"
|
||||
rm -f "${PID_FILE}"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
stop_app() {
|
||||
if ! is_running; then
|
||||
echo "[INFO] ${APP_NAME} not running"
|
||||
rm -f "${PID_FILE}" || true
|
||||
return 0
|
||||
fi
|
||||
|
||||
local pid
|
||||
pid="$(cat "${PID_FILE}")"
|
||||
echo "[INFO] stopping ${APP_NAME}, pid=${pid}"
|
||||
kill "${pid}" >/dev/null 2>&1 || true
|
||||
|
||||
local i
|
||||
for i in $(seq 1 20); do
|
||||
if ! kill -0 "${pid}" >/dev/null 2>&1; then
|
||||
rm -f "${PID_FILE}" || true
|
||||
echo "[INFO] stopped"
|
||||
return 0
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
|
||||
echo "[WARN] graceful stop timeout, force kill pid=${pid}"
|
||||
kill -9 "${pid}" >/dev/null 2>&1 || true
|
||||
rm -f "${PID_FILE}" || true
|
||||
echo "[INFO] stopped(force)"
|
||||
}
|
||||
|
||||
status_app() {
|
||||
if is_running; then
|
||||
echo "[INFO] ${APP_NAME} is running, pid=$(cat "${PID_FILE}")"
|
||||
return 0
|
||||
fi
|
||||
echo "[INFO] ${APP_NAME} is not running"
|
||||
return 1
|
||||
}
|
||||
|
||||
usage() {
|
||||
cat <<EOF
|
||||
Usage: $0 {start|stop|restart|status}
|
||||
|
||||
Environment variables:
|
||||
APP_HOME default: /home/tms
|
||||
APP_NAME default: tms-framework
|
||||
JAR_PATH default: <app_home>/tms-framework.jar
|
||||
CONF_DIR default: <app_home>/config
|
||||
RUN_DIR default: <app_home>/run
|
||||
LOG_DIR default: <app_home>/logs
|
||||
SPRING_PROFILES_ACTIVE default: prod
|
||||
JAVA_BIN default: java
|
||||
JAVA_OPTS default: -Xms512m -Xmx1024m
|
||||
ALLOW_MISSING_EXTERNAL_CONFIG default: false
|
||||
EOF
|
||||
}
|
||||
|
||||
cmd="${1:-}"
|
||||
case "${cmd}" in
|
||||
start)
|
||||
start_app
|
||||
;;
|
||||
stop)
|
||||
stop_app
|
||||
;;
|
||||
restart)
|
||||
stop_app
|
||||
start_app
|
||||
;;
|
||||
status)
|
||||
status_app
|
||||
;;
|
||||
*)
|
||||
usage
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
Reference in New Issue
Block a user