#!/usr/bin/env bash # 宇信达智建 — Linux 公共函数(宿主机物理目录模式,不依赖 Docker) # shellcheck disable=SC2034 set -euo pipefail ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" RUNTIME="$ROOT/.runtime" LOG_DIR="$RUNTIME/logs" PID_DIR="$RUNTIME/pids" VENV_DIR="$RUNTIME/venv" PGDATA="$RUNTIME/postgres" UPLOAD_DIR="$ROOT/platform/data/uploads" PG_PORT="${AJZ_PG_PORT:-5432}" PG_USER="${AJZ_PG_USER:-platform}" PG_PASS="${AJZ_PG_PASS:-platform}" PG_DB="${AJZ_PG_DB:-platform}" mkdir -p "$LOG_DIR" "$PID_DIR" "$UPLOAD_DIR" c_info() { printf '\033[36m==> %s\033[0m\n' "$*"; } c_ok() { printf '\033[32m OK %s\033[0m\n' "$*"; } c_warn() { printf '\033[33m !! %s\033[0m\n' "$*"; } c_err() { printf '\033[31m ERR %s\033[0m\n' "$*" >&2; } have_cmd() { command -v "$1" >/dev/null 2>&1; } docker_ready() { have_cmd docker || return 1 docker info >/dev/null 2>&1 } port_listen() { local port="$1" if have_cmd ss; then ss -ltn "( sport = :$port )" 2>/dev/null | grep -q ":$port" elif have_cmd netstat; then netstat -ltn 2>/dev/null | grep -q "[.:]$port " else (echo >/dev/tcp/127.0.0.1/"$port") >/dev/null 2>&1 fi } wait_port() { local port="$1" name="$2" sec="${3:-40}" local i=0 while (( i < sec * 2 )); do if port_listen "$port"; then c_ok "$name 端口 $port 已监听" return 0 fi sleep 0.5 ((i++)) || true done c_warn "$name 端口 $port 未在 ${sec}s 内就绪" return 1 } wait_http() { local url="$1" name="$2" sec="${3:-40}" local i=0 while (( i < sec * 2 )); do if curl -fsS --max-time 2 "$url" >/dev/null 2>&1; then c_ok "$name 就绪 $url" return 0 fi sleep 0.5 ((i++)) || true done c_warn "$name 未在 ${sec}s 内就绪: $url" return 1 } detect_os() { if [[ -f /etc/os-release ]]; then # shellcheck source=/dev/null . /etc/os-release echo "${ID:-unknown}" else echo "unknown" fi } sudo_run() { if [[ "$(id -u)" -eq 0 ]]; then "$@" elif have_cmd sudo; then sudo "$@" else c_err "需要 root 或 sudo 才能安装系统包: $*" return 1 fi } export ROOT RUNTIME LOG_DIR PID_DIR VENV_DIR PGDATA UPLOAD_DIR export PG_PORT PG_USER PG_PASS PG_DB