#!/usr/bin/env bash # nc-status.sh — Cloverleaf engine runtime status. Native v3 wrapper around # the shipped status/tstat binaries — modelled on v1 `status`, `tstats`, # `tstat`, `thread_status`, `procstatus`, `dstatus`, `connstatus`, `not_up`. # # Subcommands: # sites site-level status (daemon + processes + threads) # threads thread-level status (port, state, host) # not-up only threads not in 'up' state # connections raw connection state (from connstatus binary if available) # queued threads with messages queued # raw pass-through to the underlying tstat binary # # Flags (where applicable): # --site SITE single site; default = all sites under $HCIROOT # --filter REGEX match on thread name # --format text|tsv default text # # This is V1-modeled but native-bash. The exact binary names depend on the # Cloverleaf version; we auto-discover under $HCIROOT/bin (and server/bin). set -o pipefail NC_SELF="$0" die() { printf 'nc-status: %s\n' "$*" >&2; exit 1; } warn() { printf 'nc-status: %s\n' "$*" >&2; } resolve_binary() { local name="$1" if command -v "$name" >/dev/null 2>&1; then command -v "$name"; return; fi for d in "${HCIROOT:-}/bin" "${HCIROOT:-}/server/bin"; do [ -x "$d/$name" ] && { echo "$d/$name"; return; } done return 1 } list_sites() { local root="${HCIROOT:-}" [ -d "$root" ] || die "no \$HCIROOT or it doesn't exist" find "$root" -mindepth 1 -maxdepth 2 -name NetConfig -type f 2>/dev/null \ | xargs -I{} dirname {} 2>/dev/null \ | xargs -I{} basename {} 2>/dev/null \ | sort -u } cmd_sites() { local target_site="" local format="text" while [ $# -gt 0 ]; do case "$1" in --site) shift; target_site="$1" ;; --format) shift; format="$1" ;; *) die "unknown flag: $1" ;; esac shift done local hcienginestat; hcienginestat=$(resolve_binary hcienginestat 2>/dev/null || true) local sites_to_check if [ -n "$target_site" ]; then sites_to_check="$target_site"; else sites_to_check=$(list_sites); fi [ "$format" = "tsv" ] && printf 'site\tstate\tdetail\n' while IFS= read -r s; do [ -z "$s" ] && continue local detail="" state="?" if [ -n "$hcienginestat" ]; then detail=$(HCISITE="$s" "$hcienginestat" 2>&1 || true) if echo "$detail" | grep -qiE 'running|active|up'; then state="up" elif echo "$detail" | grep -qiE 'stopped|down'; then state="down" else state="unknown"; fi else # Fallback: check for lock file / pid file as a poor-man's check if [ -e "${HCIROOT:-}/$s/lock" ] || [ -e "${HCIROOT:-}/$s/exec/processes" ]; then state="config-present" fi fi if [ "$format" = "tsv" ]; then printf '%s\t%s\t%s\n' "$s" "$state" "$(echo "$detail" | head -1)" else printf '== %-20s [%s] ==\n%s\n' "$s" "$state" "$(echo "$detail" | head -10)" fi done <<< "$sites_to_check" } cmd_threads() { local target_site="${HCISITE:-}" local filter="" local format="text" while [ $# -gt 0 ]; do case "$1" in --site) shift; target_site="$1" ;; --filter) shift; filter="$1" ;; --format) shift; format="$1" ;; *) die "unknown flag: $1" ;; esac shift done local tstat; tstat=$(resolve_binary tstat) || die "tstat binary not found under \$HCIROOT/bin or PATH" local args=() [ -n "$target_site" ] && args+=("-s" "$target_site") local output; output=$(HCISITE="$target_site" "$tstat" "${args[@]}" 2>&1 || true) if [ -n "$filter" ]; then output=$(printf '%s' "$output" | grep -E -- "$filter") fi if [ "$format" = "tsv" ]; then # Best-effort: parse the tstat output into TSV printf '%s\n' "$output" | awk 'NR>1 && NF>0 { gsub(/ +/, "\t"); print }' else printf '%s\n' "$output" fi } cmd_not_up() { local site="${HCISITE:-}" local filter="" while [ $# -gt 0 ]; do case "$1" in --site) shift; site="$1" ;; --filter) shift; filter="$1" ;; *) die "unknown flag: $1" ;; esac shift done cmd_threads --site "$site" ${filter:+--filter "$filter"} \ | awk 'NR==1 || tolower($0) !~ /\/' } cmd_connections() { local connstatus; connstatus=$(resolve_binary connstatus 2>/dev/null) || die "connstatus binary not found" "$connstatus" "$@" } cmd_queued() { local site="${HCISITE:-}" cmd_threads --site "$site" "$@" \ | awk 'NR==1 || tolower($0) ~ /queued|obq|ibq/' } cmd_raw() { local tstat; tstat=$(resolve_binary tstat) || die "tstat binary not found" "$tstat" "$@" } SUB="${1:-sites}" case "$SUB" in sites) shift; cmd_sites "$@" ;; threads) shift; cmd_threads "$@" ;; not-up) shift; cmd_not_up "$@" ;; connections) shift; cmd_connections "$@" ;; queued) shift; cmd_queued "$@" ;; raw) shift; cmd_raw "$@" ;; help|-h|--help) sed -n '2,20p' "$NC_SELF" ;; *) die "unknown subcommand: $SUB" ;; esac